Skip to content

Commit d073819

Browse files
authored
🧭 docs: Document Port-Scoped allowedAddresses (#573)
1 parent 7104a72 commit d073819

8 files changed

Lines changed: 97 additions & 69 deletions

File tree

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
date: 2026-05-08
3+
title: ⚙️ Config v1.3.10
4+
version: '1.3.10'
5+
---
6+
7+
- Changed `allowedAddresses` entries to require an explicit port
8+
- Applies to `actions.allowedAddresses`, `mcpSettings.allowedAddresses`, and `endpoints.allowedAddresses`
9+
- Entries must use `host:port`, `private.ip:port`, or `[ipv6]:port`
10+
- Bare hosts and IPs such as `localhost`, `127.0.0.1`, and `host.docker.internal` are rejected
11+
- This scopes each SSRF exemption to one intended private service instead of every port on the same host
12+
13+
- Preserved private-IP scoping for `allowedAddresses`
14+
- URLs, paths, CIDR ranges, whitespace, invalid ports, and public IP literals remain invalid
15+
- Hostname entries still trust whatever private IP that hostname resolves to on the listed port
16+
17+
- Clarified how `allowedAddresses` interacts with `allowedDomains`
18+
- `allowedAddresses` is used when `allowedDomains` is not configured
19+
- When `allowedDomains` is configured, it acts as the authoritative strict whitelist

content/docs/configuration/librechat_yaml/object_structure/actions.mdx

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,17 @@ More info: [Agents - Actions](/docs/features/agents#actions)
1212
```yaml filename="Actions Object Structure"
1313
# Example Actions Object Structure
1414
actions:
15-
allowedDomains:
16-
- "swapi.dev"
17-
- "librechat.ai"
18-
- "google.com"
19-
- "https://api.example.com:8443" # With protocol and port
15+
# Strict whitelist mode:
16+
# allowedDomains:
17+
# - "swapi.dev"
18+
# - "librechat.ai"
19+
# - "google.com"
20+
# - "https://api.example.com:8443" # With protocol and port
21+
22+
# Default SSRF mode with private service exemptions:
2023
allowedAddresses:
21-
- "host.docker.internal" # Permit one private host
22-
- "10.0.0.5" # Permit one private IP
24+
- "host.docker.internal:11434" # Permit one private host on one port
25+
- "10.0.0.5:8080" # Permit one private IP on one port
2326
```
2427
2528
## allowedDomains
@@ -52,7 +55,7 @@ LibreChat includes SSRF (Server-Side Request Forgery) protection with the follow
5255
- **Internal TLDs** (`.internal`, `.local`, `.localhost`)
5356
- **Common internal service names** (`redis`, `mongodb`, `postgres`, `api`, etc.)
5457

55-
If your actions need to access internal services, you **must explicitly add them** to `allowedDomains`.
58+
If your actions need to access internal services, either add them to the strict `allowedDomains` whitelist, or leave `allowedDomains` unset and add the exact private service to `allowedAddresses`.
5659

5760
### Pattern Formats
5861

@@ -95,37 +98,38 @@ allowedDomains:
9598

9699
## allowedAddresses
97100

98-
`allowedAddresses` is an **exemption list** for the SSRF private-IP block — not a domain whitelist. It is the right tool when you want to permit one or two specific private/internal hosts without restricting what your Actions can reach in the public internet.
101+
`allowedAddresses` is an **exemption list** for the SSRF private-IP block — not a domain whitelist. It is the right tool when you want to permit one or two specific private/internal services without restricting what your Actions can reach in the public internet.
99102

100103
### When to use it instead of `allowedDomains`
101104

102105
`allowedDomains` is a strict whitelist: when it is set, **only** listed entries are reachable. Adding a private IP there to permit, say, a self-hosted internal API also blocks every public action endpoint that you didn't also list.
103106

104-
`allowedAddresses` is orthogonal: it permits specific private targets while leaving the rest of the public internet reachable through the default SSRF policy.
107+
`allowedAddresses` is used only when `allowedDomains` is not configured. It permits specific private `host:port` targets while leaving the rest of the public internet reachable through the default SSRF policy.
105108

106109
```yaml filename="default SSRF + permitted private host"
107110
actions:
108111
allowedAddresses:
109-
- "host.docker.internal"
110-
- "10.0.0.5"
112+
- "host.docker.internal:11434"
113+
- "10.0.0.5:8080"
111114
# allowedDomains is intentionally not set — public destinations
112-
# remain reachable, only listed private hosts are exempted.
115+
# remain reachable, only listed private host:port services are exempted.
113116
```
114117

115-
You can also combine both: use `allowedDomains` as your strict whitelist and `allowedAddresses` to permit specific private hosts not covered by the domain rules.
118+
If `allowedDomains` is configured, it is authoritative: private services must be listed there instead of relying on `allowedAddresses`.
116119

117120
### Acceptable entries
118121

119-
- **Bare hostnames**: `host.docker.internal`, `ollama.internal`, `localhost`
120-
- **Private IPv4 literals**: `10.0.0.5`, `127.0.0.1`, `192.168.1.10`, `169.254.169.254`
121-
- **Private IPv6 literals**: `::1`, `fc00::1`, `fe80::1`, `[::1]` (brackets are stripped)
122+
- **Hostnames with port**: `host.docker.internal:11434`, `ollama.internal:8080`, `localhost:11434`
123+
- **Private IPv4 literals with port**: `10.0.0.5:8080`, `127.0.0.1:11434`, `192.168.1.10:443`, `169.254.169.254:80`
124+
- **Bracketed private IPv6 literals with port**: `[::1]:11434`, `[fc00::1]:8080`, `[fe80::1]:8080`
122125

123126
### Rejected entries (validated at config load)
124127

125128
- **URLs / paths / CIDR ranges**: `http://10.0.0.5`, `10.0.0.0/24`, `/path`
126-
- **Host with port**: `localhost:8080`, `[::1]:8080` — list the bare hostname or IP only
127-
- **Public IP literals**: `8.8.8.8`, `1.1.1.1`, `2001:4860::` — the field is scoped to private IP space; public IPs are not SSRF targets and a public-IP exemption has no defensive purpose
129+
- **Bare hostnames or IPs**: `localhost`, `10.0.0.5`, `::1`, `[::1]` — every entry must include a port
130+
- **Invalid ports**: `localhost:0`, `localhost:65536`, `localhost:http`
131+
- **Public IP literals**: `8.8.8.8:53`, `1.1.1.1:53`, `[2001:4860::8888]:443` — the field is scoped to private IP space; public IPs are not SSRF targets and a public-IP exemption has no defensive purpose
128132

129133
### Hostname trust
130134

131-
A hostname entry trusts whatever IP that hostname resolves to at runtime. If the DNS for a listed hostname is rotated or hijacked to point at a different private IP, the exemption follows. Only list hostnames whose DNS you control. **Prefer literal IPs when you can.**
135+
A hostname entry trusts whatever IP that hostname resolves to at runtime on the listed port. If the DNS for a listed hostname is rotated or hijacked to point at a different private IP, the exemption follows. Only list hostnames whose DNS you control. **Prefer literal IPs when you can.**

content/docs/configuration/librechat_yaml/object_structure/config.mdx

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ icon: Settings
1010

1111
<OptionTable
1212
options={[
13-
['version', 'String', 'Specifies the version of the configuration file.', 'version: 1.3.9' ],
13+
['version', 'String', 'Specifies the version of the configuration file.', 'version: 1.3.10' ],
1414
]}
1515
/>
1616

@@ -441,7 +441,7 @@ see: [Summarization Object Structure](/docs/configuration/librechat_yaml/object_
441441
<OptionTable
442442
options={[
443443
['allowedDomains', 'Array of Strings', 'Strict whitelist of domains for actions. When set, only listed domains are reachable.', ''],
444-
['allowedAddresses', 'Array of Strings', 'SSRF exemption list (private IP space only). Permits specific private hosts without restricting public destinations.', ''],
444+
['allowedAddresses', 'Array of Strings', 'SSRF exemption list (private IP space only). Permits specific private host:port services without restricting public destinations when `allowedDomains` is not configured.', ''],
445445
]}
446446
/>
447447

@@ -526,13 +526,13 @@ see: [Model Specs Object Structure](/docs/configuration/librechat_yaml/object_st
526526
['azureAssistants', 'Object', 'Azure Assistants endpoint-specific configuration.', ''],
527527
['agents', 'Object', 'Agents endpoint-specific configuration.', ''],
528528
['all', 'Object', 'Global endpoint settings that apply to all endpoints. See Shared Endpoint Settings.', ''],
529-
['allowedAddresses', 'Array of Strings', 'SSRF exemption list (private IP space only). Permits user-provided baseURLs to point at specific private hosts (e.g. self-hosted Ollama) without disabling SSRF protection for everything else.', ''],
529+
['allowedAddresses', 'Array of Strings', 'SSRF exemption list (private IP space only). Permits user-provided baseURLs to point at specific private host:port services (e.g. self-hosted Ollama) without disabling SSRF protection for everything else.', ''],
530530
]}
531531
/>
532532

533533
> **Note:** All endpoints support [Shared Endpoint Settings](/docs/configuration/librechat_yaml/object_structure/shared_endpoint_settings) which include `streamRate`, `titleModel`, `titleMethod`, `titlePrompt`, `titlePromptTemplate`, `titleEndpoint`, and `maxToolResultChars`. These can be configured individually per endpoint or globally using the `all` key. The `all` key does not accept `baseURL`.
534534

535-
> **Note:** `endpoints.allowedAddresses` applies to user-provided `baseURL` values (when an admin configures a custom endpoint with `apiKey: 'user_provided'` and `baseURL: 'user_provided'`). Each user-supplied baseURL is validated against the SSRF block at request time; entries listed here are exempted. See [`mcpSettings.allowedAddresses`](/docs/configuration/librechat_yaml/object_structure/mcp_settings#allowedaddresses) for the field semantics — same rules apply (private IP space only, no URLs/CIDR/ports).
535+
> **Note:** `endpoints.allowedAddresses` applies to user-provided `baseURL` values (when an admin configures a custom endpoint with `apiKey: 'user_provided'` and `baseURL: 'user_provided'`). Each user-supplied baseURL is validated against the SSRF block at request time; entries listed here are exempted. See [`mcpSettings.allowedAddresses`](/docs/configuration/librechat_yaml/object_structure/mcp_settings#allowedaddresses) for the field semantics — same rules apply (private IP space only, port required, no URLs/paths/CIDR/bare hosts/public IP literals).
536536

537537
## mcpSettings
538538

@@ -547,29 +547,31 @@ see: [Model Specs Object Structure](/docs/configuration/librechat_yaml/object_st
547547
<OptionTable
548548
options={[
549549
['allowedDomains', 'Array of Strings', 'Strict whitelist of domains for MCP server connections. When set, only listed entries are reachable.', ''],
550-
['allowedAddresses', 'Array of Strings', 'SSRF exemption list (private IP space only). Permits specific private hosts without flipping `allowedDomains` into strict-whitelist mode.', ''],
550+
['allowedAddresses', 'Array of Strings', 'SSRF exemption list (private IP space only). Permits specific private host:port services without flipping `allowedDomains` into strict-whitelist mode.', ''],
551551
]}
552552
/>
553553

554554
- **Notes**:
555555
- This is a security feature to protect against abuse / misuse of internal addresses via MCP servers
556556
- By default, LibreChat restricts MCP servers from connecting to internal, local, or private network addresses
557-
- MCP servers using local IP addresses or domains can either be added to the strict `allowedDomains` whitelist (which then becomes the only reachable set), or — to keep public destinations reachable — exempted via `allowedAddresses`
557+
- MCP servers using local IP addresses or domains can either be added to the strict `allowedDomains` whitelist (which then becomes the only reachable set), or — to keep public destinations reachable — exempted as exact host:port services via `allowedAddresses`
558558
- As with all yaml configuration changes, a LibreChat restart is required to take effect
559559
- Supports domains, wildcard subdomains (`*.example.com`), docker domains, and IP addresses
560560

561561
**Example:**
562562

563563
```yaml filename="mcpSettings"
564564
mcpSettings:
565-
allowedDomains:
566-
- "example.com" # Specific domain
567-
- "*.example.com" # All subdomains
568-
- "mcp-server" # Local Docker domain
569-
- "172.24.1.165" # Internal network IP
565+
# Strict whitelist mode:
566+
# allowedDomains:
567+
# - "example.com" # Specific domain
568+
# - "*.example.com" # All subdomains
569+
# - "http://mcp-server:3000" # Internal service, explicitly whitelisted
570+
571+
# Default SSRF mode with private service exemptions:
570572
allowedAddresses:
571-
- "host.docker.internal" # Permit a single private host
572-
- "10.0.0.5" # Permit a single private IP
573+
- "host.docker.internal:8080" # Permit one private host on one port
574+
- "10.0.0.5:8000" # Permit one private IP on one port
573575
```
574576

575577
see: [MCP Settings Object Structure](/docs/configuration/librechat_yaml/object_structure/mcp_settings)

content/docs/configuration/librechat_yaml/object_structure/mcp_servers.mdx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -403,22 +403,22 @@ mcpServers:
403403
- **`sse`**: Connects to an external MCP server via Server-Sent Events (SSE).
404404
- **`streamable-http`**: Connects to an external MCP server via HTTP with support for streaming responses.
405405
- **Internal/Local Addresses:**
406-
- **Important**: MCP servers using internal IP addresses (e.g., `172.24.1.165`, `192.168.1.100`), or local domains (e.g., `mcp-server`, `host.docker.internal`) **must** be explicitly allowed in [`mcpSettings.allowedDomains`](/docs/configuration/librechat_yaml/object_structure/mcp_settings).
406+
- **Important**: MCP servers using internal IP addresses (e.g., `172.24.1.165`, `192.168.1.100`), or local domains (e.g., `mcp-server`, `host.docker.internal`) **must** be explicitly allowed. Use [`mcpSettings.allowedAddresses`](/docs/configuration/librechat_yaml/object_structure/mcp_settings#allowedaddresses) for exact private host:port services when you want public destinations to remain reachable, or [`mcpSettings.allowedDomains`](/docs/configuration/librechat_yaml/object_structure/mcp_settings#alloweddomains) when you want a strict whitelist.
407407
- See [MCP Settings](/docs/configuration/librechat_yaml/object_structure/mcp_settings) for configuration details.
408408

409409
## Examples
410410

411411
### Configuration with Internal Addresses
412412

413-
When using internal/local MCP servers, you must configure `mcpSettings.allowedDomains`:
413+
When using internal/local MCP servers and no strict domain whitelist is needed, configure `mcpSettings.allowedAddresses` with the exact host and port:
414414

415415
```yaml filename="Complete MCP Configuration with Internal Servers"
416416
# MCP Settings - Required for internal/local addresses
417417
mcpSettings:
418-
allowedDomains:
419-
- "172.24.1.165" # Internal IP
420-
- "mcp-prod" # Docker container
421-
- "host.docker.internal" # Docker host
418+
allowedAddresses:
419+
- "172.24.1.165:8000" # Internal IP and port
420+
- "mcp-prod:8001" # Docker container and port
421+
- "host.docker.internal:8080" # Docker host and port
422422
423423
# MCP Servers - Individual configurations
424424
mcpServers:

0 commit comments

Comments
 (0)