mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-01-30 06:15:18 +01:00
🔒 fix: Better SSRF protection for Actions (#11143)
Addresses Server-Side Request Forgery vulnerability that allowed authenticated attackers to interact with arbitrary internal/external HTTP services via the Actions feature, including the internal RAG API, localhost services, and cloud metadata endpoints. ## Security Changes ### 1. SSRF Target Blocklist (when allowedDomains is empty) - Block localhost and loopback addresses (127.0.0.0/8, ::1) - Block private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) - Block link-local/cloud metadata IPs (169.254.0.0/16) - Block common internal Docker/Kubernetes service names (rag_api, redis, mongo, etc.) - Block .internal and .local TLDs Admins can still explicitly allow internal targets by adding them to `actions.allowedDomains` in librechat.yaml. ### 2. Protocol and Port Restrictions Enhanced `allowedDomains` to support protocol and port constraints: - `example.com` - any protocol, any port (existing behavior) - `https://example.com` - HTTPS only, any port - `https://api.example.com:8443` - HTTPS only, port 8443 only This allows admins to restrict actions to specific protocols/ports, preventing attackers from accessing unintended services on allowed domains. ### 3. Redirect-based SSRF Prevention Disabled automatic redirect following in action HTTP requests (`maxRedirects: 0`). This prevents attackers from bypassing domain restrictions by: 1. Pointing action to allowed external domain 2. External domain redirects to internal service (e.g., 127.0.0.1) 3. Server follows redirect and accesses internal service ## Files Changed - packages/api/src/auth/domain.ts: Added isSSRFTarget(), parseDomainSpec(), updated isActionDomainAllowed() with protocol/port matching - packages/api/src/auth/domain.spec.ts: Added tests for SSRF protection, protocol restrictions, and port restrictions - packages/data-provider/src/actions.ts: Added maxRedirects: 0 to axios config ## Configuration Example # librechat.yaml actions: allowedDomains: - "https://api.example.com" # HTTPS only - "https://api.example.com:8443" # HTTPS + specific port - "http://localhost:3000" # Admin override for local devRef: SBA-ADV-20251205-02 CVSSv3: 9.1 (Critical) - CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:L
This commit is contained in:
parent
a59bab4dc7
commit
4fd09946d2
3 changed files with 445 additions and 32 deletions
|
|
@ -290,7 +290,21 @@ class RequestExecutor {
|
|||
...(this.config.contentType ? { 'Content-Type': this.config.contentType } : {}),
|
||||
};
|
||||
const method = this.config.method.toLowerCase();
|
||||
const axios = _axios.create();
|
||||
|
||||
/**
|
||||
* SECURITY: Disable automatic redirects to prevent SSRF bypass.
|
||||
* Attackers could use redirects to access internal services:
|
||||
* 1. Set action URL to allowed external domain
|
||||
* 2. External domain redirects to internal service (e.g., 127.0.0.1, rag_api)
|
||||
* 3. Without this protection, axios would follow the redirect
|
||||
*
|
||||
* By setting maxRedirects: 0, we prevent this attack vector.
|
||||
* The action will receive the redirect response (3xx) instead of following it.
|
||||
*/
|
||||
const axios = _axios.create({
|
||||
maxRedirects: 0,
|
||||
validateStatus: (status) => status >= 200 && status < 400, // Accept 3xx but don't follow
|
||||
});
|
||||
|
||||
// Initialize separate containers for query and body parameters.
|
||||
const queryParams: Record<string, unknown> = {};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue