mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-03-16 20:56:35 +01:00
🫷 fix: Validate User-Provided Base URL in Endpoint Init (#12248)
* 🛡️ fix: Block SSRF via user-provided baseURL in endpoint initialization User-provided baseURL values (when endpoint is configured with `user_provided`) were passed through to the OpenAI SDK without validation. Combined with `directEndpoint`, this allowed arbitrary server-side requests to internal/metadata URLs. Adds `validateEndpointURL` that checks against known SSRF targets and DNS-resolves hostnames to block private IPs. Applied in both custom and OpenAI endpoint initialization paths. * 🧪 test: Add validateEndpointURL SSRF tests Covers unparseable URLs, localhost, private IPs, link-local/metadata, internal Docker/K8s hostnames, DNS resolution to private IPs, and legitimate public URLs. * 🛡️ fix: Add protocol enforcement and import order fix - Reject non-HTTP/HTTPS schemes (ftp://, file://, data:, etc.) in validateEndpointURL before SSRF hostname checks - Document DNS rebinding limitation and fail-open semantics in JSDoc - Fix import order in custom/initialize.ts per project conventions * 🧪 test: Expand SSRF validation coverage and add initializer integration tests Unit tests for validateEndpointURL: - Non-HTTP/HTTPS schemes (ftp, file, data) - IPv6 loopback, link-local, and unique-local addresses - .local and .internal TLD hostnames - DNS fail-open path (lookup failure allows request) Integration tests for initializeCustom and initializeOpenAI: - Guard fires when userProvidesURL is true - Guard skipped when URL is system-defined or falsy - SSRF rejection propagates and prevents getOpenAIConfig call * 🐛 fix: Correct broken env restore in OpenAI initialize spec process.env was captured by reference, not by value, making the restore closure a no-op. Snapshot individual env keys before mutation so they can be properly restored after each test. * 🛡️ fix: Throw structured ErrorTypes for SSRF base URL validation Replace plain-string Error throws in validateEndpointURL with JSON-structured errors using type 'invalid_base_url' (matching new ErrorTypes.INVALID_BASE_URL enum value). This ensures the client-side Error component can look up a localized message instead of falling through to the raw-text default. Changes across workspaces: - data-provider: add INVALID_BASE_URL to ErrorTypes enum - packages/api: throwInvalidBaseURL helper emits structured JSON - client: add errorMessages entry and localization key - tests: add structured JSON format assertion * 🧹 refactor: Use ErrorTypes enum key in Error.tsx for consistency Replace bare string literal 'invalid_base_url' with computed property [ErrorTypes.INVALID_BASE_URL] to match every other entry in the errorMessages map.
This commit is contained in:
parent
f9927f0168
commit
f7ab5e645a
9 changed files with 446 additions and 1 deletions
|
|
@ -41,6 +41,7 @@ const errorMessages = {
|
|||
[ErrorTypes.NO_USER_KEY]: 'com_error_no_user_key',
|
||||
[ErrorTypes.INVALID_USER_KEY]: 'com_error_invalid_user_key',
|
||||
[ErrorTypes.NO_BASE_URL]: 'com_error_no_base_url',
|
||||
[ErrorTypes.INVALID_BASE_URL]: 'com_error_invalid_base_url',
|
||||
[ErrorTypes.INVALID_ACTION]: `com_error_${ErrorTypes.INVALID_ACTION}`,
|
||||
[ErrorTypes.INVALID_REQUEST]: `com_error_${ErrorTypes.INVALID_REQUEST}`,
|
||||
[ErrorTypes.REFUSAL]: 'com_error_refusal',
|
||||
|
|
|
|||
|
|
@ -372,6 +372,7 @@
|
|||
"com_error_missing_model": "No model selected for {{0}}. Please select a model and try again.",
|
||||
"com_error_models_not_loaded": "Models configuration could not be loaded. Please refresh the page and try again.",
|
||||
"com_error_moderation": "It appears that the content submitted has been flagged by our moderation system for not aligning with our community guidelines. We're unable to proceed with this specific topic. If you have any other questions or topics you'd like to explore, please edit your message, or create a new conversation.",
|
||||
"com_error_invalid_base_url": "The base URL you provided targets a restricted address. Please use a valid external URL and try again.",
|
||||
"com_error_no_base_url": "No base URL found. Please provide one and try again.",
|
||||
"com_error_no_user_key": "No key found. Please provide a key and try again.",
|
||||
"com_error_refusal": "Response refused by safety filters. Rewrite your message and try again. If you encounter this frequently while using Claude Sonnet 4.5 or Opus 4.1, you can try Sonnet 4, which has different usage restrictions.",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue