Skip to content

feat(core): Add SSRF protection config#26424

Open
tomi wants to merge 4 commits intomasterfrom
cat-2383-implement-ssrfprotectionconfig-with-environment-variable
Open

feat(core): Add SSRF protection config#26424
tomi wants to merge 4 commits intomasterfrom
cat-2383-implement-ssrfprotectionconfig-with-environment-variable

Conversation

@tomi
Copy link
Collaborator

@tomi tomi commented Mar 2, 2026

Summary

  • Add SsrfProtectionConfig to @n8n/config and wire it into GlobalConfig as ssrfProtection.
  • Add SSRF env-backed settings, including default blocked ranges, allow lists, DNS cache TTL, and DNS cache size.
  • Export SsrfProtectionConfig and SSRF_DEFAULT_BLOCKED_IP_RANGES from the config package index.
  • Add unit tests covering defaults, env parsing, numeric overrides, and fallback behavior for invalid numeric values.

Related Linear tickets, Github issues, and Community forum posts

Review / Merge checklist

  • PR title and summary are descriptive. (conventions)
  • Docs updated or follow-up ticket created.
  • Tests included.
  • PR Labeled with release/backport (if the PR is an urgent fix that needs to be backported)

@tomi tomi changed the title feat(config): add SSRF protection config feat(core): Add SSRF protection config Mar 2, 2026
@n8n-assistant n8n-assistant bot added the n8n team Authored by the n8n team label Mar 2, 2026
@codecov
Copy link

codecov bot commented Mar 2, 2026

Codecov Report

❌ Patch coverage is 86.95652% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
.../@n8n/config/src/configs/ssrf-protection.config.ts 88.88% 0 Missing and 2 partials ⚠️
packages/@n8n/config/src/index.ts 80.00% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@blacksmith-sh

This comment has been minimized.

@tomi tomi force-pushed the cat-2383-implement-ssrfprotectionconfig-with-environment-variable branch from 58aaabf to 97736fb Compare March 2, 2026 15:15
@tomi tomi marked this pull request as ready for review March 2, 2026 18:17
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cubic analysis

No issues found across 4 files

Linked issue analysis

Linked issue: CAT-2383: Implement SsrfProtectionConfig with environment variable parsing

Status Acceptance criteria Notes
Config class parses all environment variables with correct defaults Config fields declared with @env and sensible defaults
'default' keyword expands to the full set of blocked ranges sanitize() sets resolvedBlockedIpRanges to default list
⚠️ Comma-separated values are correctly parsed into arrays Blocked list parsing implemented; allowed fields rely on decorator/runtime
⚠️ Invalid values are handled gracefully (log warning, use defaults) Tests expect warn + fallback, but class has no explicit warn/parsing code
⚠️ Configuration is loaded once at startup Added to GlobalConfig @nested but no explicit 'load once at startup' code shown
All configuration paths have positive and negative test cases Unit tests cover defaults, positive overrides and invalid cases
N8N_SSRF_PROTECTION_ENABLED env var (boolean) with default false enabled property declared with @env and default false
N8N_SSRF_BLOCKED_IP_RANGES env var (string) with default 'default' blockedIpRanges default set to 'default' in config
⚠️ N8N_SSRF_ALLOWED_IP_RANGES env var parsed (default empty -> array) Type and tests present but no explicit parse code shown in class
⚠️ N8N_SSRF_ALLOWED_HOSTNAMES env var parsed (default empty -> array) Typed and tested, parsing appears delegated to framework
⚠️ N8N_SSRF_DNS_CACHE_MAX_TTL_SECONDS numeric env with default 300 and invalid fallback Field present and tests for override/fallback; parsing/warn not explicit
⚠️ N8N_SSRF_DNS_CACHE_MAX_SIZE numeric env with default 1024*1024 and invalid fallback Field present and tests for override/fallback; parsing/warn not explicit
Default blocked ranges include RFC1918, loopback, link-local, IPv6 unique local, reserved ranges SSRF_DEFAULT_BLOCKED_IP_RANGES constant lists all required CIDRs
Export SsrfProtectionConfig and SSRF_DEFAULT_BLOCKED_IP_RANGES from package index Index file exports both symbols
Wire SsrfProtectionConfig into GlobalConfig as ssrfProtection GlobalConfig includes @nested ssrfProtection property
Unit tests for environment parsing, defaults, comma-separated parsing and invalid values Test file covers defaults, parsing, trimming, numeric overrides and invalids
GlobalConfig tests updated to include ssrfProtection defaults GlobalConfig test default config now contains ssrfProtection section
Architecture diagram
sequenceDiagram
    participant OS as Process Environment
    participant DI as DI Container
    participant SSRF as SsrfProtectionConfig
    participant Node as HTTP Request Node
    participant DNS as DNS Cache / Resolver

    Note over OS, SSRF: Initialization Phase

    DI->>SSRF: NEW: Instantiate via @Config
    SSRF->>OS: Read N8N_SSRF_* variables
    OS-->>SSRF: Enabled status, CIDR ranges, DNS settings

    SSRF->>SSRF: NEW: sanitize()
    alt N8N_SSRF_BLOCKED_IP_RANGES is 'default'
        SSRF->>SSRF: Load SSRF_DEFAULT_BLOCKED_IP_RANGES
    else custom CIDR string
        SSRF->>SSRF: Split and trim CSV into resolvedBlockedIpRanges
    end

    Note over SSRF, DNS: Runtime Request Flow (Implied Consumer)

    Node->>SSRF: Check if enabled
    SSRF-->>Node: return true/false

    opt SSRF Protection Enabled
        Node->>SSRF: NEW: Get allowedHostnames & allowedIpRanges
        Node->>SSRF: NEW: Get resolvedBlockedIpRanges
        
        Node->>DNS: NEW: Resolve hostname with SSRF constraints
        DNS->>DNS: Apply dnsCacheMaxTtlSeconds & dnsCacheMaxSize
        
        alt IP in resolvedBlockedIpRanges AND NOT in allowedIpRanges
            Node->>Node: Block request (SSRF Violation)
        else IP is allowed or not blocked
            Node->>Node: Proceed with HTTP request
        end
    end

    Note over SSRF: Defaults to false, blocks RFC1918/Local by default
Loading

@codecov
Copy link

codecov bot commented Mar 2, 2026

Bundle Report

Bundle size has no change ✅

Affected Assets, Files, and Routes:

view changes for bundle: editor-ui-esm

Assets Changed:

Asset Name Size Change Total Size Change (%)
assets/worker-*.js 2.91MB 2.92MB 21725.55% ⚠️
assets/worker-*.js -2.91MB 13.37kB -99.54%

@dlavrenuek dlavrenuek self-requested a review March 3, 2026 10:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

n8n team Authored by the n8n team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant