mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-16 16:30:15 +01:00
🔒 feat: Implement Cross-Platform IP Validation Functionality
* Added a new `isIP` function for validating IP addresses in both Node.js and browser environments, replacing the previous reliance on the Node.js `net` module. * Updated domain extraction and validation logic to utilize the new `isIP` function, ensuring consistent IP validation across the application. * Enhanced handling of IPv4 and IPv6 addresses, including proper formatting for URLs.
This commit is contained in:
parent
086e9a92dc
commit
ba974604b1
1 changed files with 32 additions and 7 deletions
|
|
@ -1,7 +1,6 @@
|
|||
import { z } from 'zod';
|
||||
import { URL } from 'url';
|
||||
import _axios from 'axios';
|
||||
import * as net from 'net';
|
||||
import crypto from 'crypto';
|
||||
import { load } from 'js-yaml';
|
||||
import type { ActionMetadata, ActionMetadataRuntime } from './types/agents';
|
||||
|
|
@ -567,6 +566,32 @@ export type ValidationResult = {
|
|||
serverUrl?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Cross-platform IP validation (works in Node.js and browser).
|
||||
* @param input - String to check if it's an IP address
|
||||
* @returns 0 if not IP, 4 for IPv4, 6 for IPv6
|
||||
*/
|
||||
function isIP(input: string): number {
|
||||
// IPv4 regex - matches 0.0.0.0 to 255.255.255.255
|
||||
const ipv4Regex =
|
||||
/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
||||
|
||||
if (ipv4Regex.test(input)) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
// IPv6 regex - simplified but covers most cases
|
||||
// Handles compressed (::), full, and mixed notations
|
||||
const ipv6Regex =
|
||||
/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/;
|
||||
|
||||
if (ipv6Regex.test(input)) {
|
||||
return 6;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts domain from URL (protocol + hostname).
|
||||
* @param url - URL to extract from
|
||||
|
|
@ -576,8 +601,8 @@ export function extractDomainFromUrl(url: string): string {
|
|||
try {
|
||||
/** Parsed URL object */
|
||||
const parsedUrl = new URL(url);
|
||||
// Preserve brackets for IPv6 addresses using net.isIP
|
||||
const ipVersion = net.isIP(parsedUrl.hostname);
|
||||
// Preserve brackets for IPv6 addresses using isIP
|
||||
const ipVersion = isIP(parsedUrl.hostname);
|
||||
const hostname = ipVersion === 6 ? `[${parsedUrl.hostname}]` : parsedUrl.hostname;
|
||||
return `${parsedUrl.protocol}//${hostname}`;
|
||||
} catch {
|
||||
|
|
@ -616,7 +641,7 @@ export function validateActionDomain(
|
|||
/** Spec hostname only */
|
||||
const specHostname = specUrl.hostname;
|
||||
/** Spec domain with protocol (handle IPv6 brackets) */
|
||||
const specIpVersion = net.isIP(specHostname);
|
||||
const specIpVersion = isIP(specHostname);
|
||||
const normalizedSpecDomain =
|
||||
specIpVersion === 6
|
||||
? `${specUrl.protocol}//[${specHostname}]`
|
||||
|
|
@ -651,8 +676,8 @@ export function validateActionDomain(
|
|||
const normalizedClientHostname = clientHostname.replace(/^\[(.+)\]$/, '$1');
|
||||
const normalizedSpecHostname = specHostname.replace(/^\[(.+)\]$/, '$1');
|
||||
|
||||
/** Check if hostname is valid IP using Node.js built-in net module */
|
||||
const isIPAddress = net.isIP(normalizedClientHostname) !== 0;
|
||||
/** Check if hostname is valid IP using cross-platform isIP */
|
||||
const isIPAddress = isIP(normalizedClientHostname) !== 0;
|
||||
|
||||
/** Normalized client domain */
|
||||
let normalizedClientDomain: string;
|
||||
|
|
@ -662,7 +687,7 @@ export function validateActionDomain(
|
|||
// IP addresses inherit protocol from spec, domains default to https
|
||||
if (isIPAddress) {
|
||||
// IPv6 addresses need brackets in URLs
|
||||
const ipVersion = net.isIP(normalizedClientHostname);
|
||||
const ipVersion = isIP(normalizedClientHostname);
|
||||
const hostname =
|
||||
ipVersion === 6 && !clientHostname.startsWith('[')
|
||||
? `[${normalizedClientHostname}]`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue