Skip to content

feat: add SSRF protection configuration for API Requests#10544

Merged
jordanrfrazier merged 22 commits into
mainfrom
issue-10355
Nov 12, 2025
Merged

feat: add SSRF protection configuration for API Requests#10544
jordanrfrazier merged 22 commits into
mainfrom
issue-10355

Conversation

@jordanrfrazier
Copy link
Copy Markdown
Collaborator

@jordanrfrazier jordanrfrazier commented Nov 10, 2025

Adds configuration to enable SSRF protection in the API Request Component. We will leave the defaults for (most*) parameters as-is to avoid breaking changes, but have added appropriate warnings and notices to update to the more secure behaviors in the next major release.

Allows configures an allowlist for specific domains.

*The only parameter updated is in API Request Component to follow_redirects. As this is a component-level change, we can safely update this parameter without breaking existing users' flows, as they will be prompted to manually update the component and can decline.

Addresses #10355

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced Server-Side Request Forgery (SSRF) protection to block unauthorized access to private networks, localhost, and cloud metadata endpoints.
    • Added configuration options to enable/disable SSRF protection and customize allowed hosts and network ranges.
  • Security Improvements

    • Changed default behavior: HTTP redirects now disabled by default for enhanced security.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 10, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

A new SSRF protection system is introduced with validation utilities, configuration settings, and integration into the API request component. Default protection is disabled with optional warn-only mode for gradual enforcement.

Changes

Cohort / File(s) Change Summary
SSRF Protection Core Utilities
src/lfx/src/lfx/utils/ssrf_protection.py
New module implementing SSRF validation with blocked IP ranges (private, loopback, metadata endpoints), custom SSRFProtectionError exception, and utility functions for allowlist matching, IP blocking checks, hostname resolution, and URL validation with support for warn-only and enforcement modes.
Settings Configuration
src/lfx/src/lfx/services/settings/base.py
Added two new public configuration attributes: ssrf_protection_enabled (bool, default False) and ssrf_allowed_hosts (list[str], default empty) with documentation for protected IP ranges and supported allowlist patterns.
API Request Component
src/lfx/src/lfx/components/data/api_request.py
Integrated SSRF validation into make_api_request() and make_request() methods via validate_url_for_ssrf() call. Changed follow_redirects default from True to False with security warning in UI description. Added runtime security warning log when redirects enabled.
Test Coverage
src/lfx/tests/unit/utils/test_ssrf_protection.py
New comprehensive test module validating SSRF utilities: configuration parsing, IP blocking, hostname resolution, allowlist matching (exact/wildcard/CIDR), warn-only vs enforcement modes, public/private/IPv6 handling, and integration scenarios.
API Request Component Tests
src/backend/tests/unit/components/data/test_api_request_component.py
Updated default follow_redirects fixture from True to False. Added new test suite TestAPIRequestSSRFProtection validating disabled-by-default behavior, protection enforcement when enabled, allowlist bypasses, warn-only mode logging, URL normalization, and error handling.

Sequence Diagram

sequenceDiagram
    participant Client
    participant APIComponent as API Request<br/>Component
    participant SSRF as SSRF<br/>Validator
    participant DNS as DNS<br/>Resolver
    participant HTTP as HTTP<br/>Client

    Client->>APIComponent: make_api_request(url, ...)
    APIComponent->>APIComponent: Normalize URL
    APIComponent->>SSRF: validate_url_for_ssrf(url)
    
    alt SSRF Protection Enabled
        SSRF->>SSRF: Check allowlist
        alt Host in allowlist
            SSRF-->>APIComponent: ✓ Allowed
        else Direct IP
            SSRF->>SSRF: is_ip_blocked(ip)
            alt IP blocked
                SSRF-->>APIComponent: ✗ Blocked / ⚠ Warn
            else IP allowed
                SSRF-->>APIComponent: ✓ Allowed
            end
        else Hostname
            SSRF->>DNS: resolve_hostname()
            alt Resolution fails
                SSRF-->>APIComponent: ✗ Error / ⚠ Warn
            else IPs resolved
                SSRF->>SSRF: Check all IPs blocked
                alt Any allowed
                    SSRF-->>APIComponent: ✓ Allowed
                else All blocked
                    SSRF-->>APIComponent: ✗ Blocked / ⚠ Warn
                end
            end
        end
    else SSRF Protection Disabled
        SSRF-->>APIComponent: ✓ Allowed (bypass)
    end

    APIComponent->>HTTP: Execute request
    HTTP-->>Client: Response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • SSRF utility module complexity: Dense logic involving IP range validation, CIDR matching, DNS resolution with extensive error handling and multiple code paths requires careful review of correctness and security assumptions.
  • Integration points: Validation logic insertion into API component must be verified for proper placement (after URL normalization, before request execution) and error handling consistency.
  • Test coverage verification: Large test suite with multiple scenarios (IPv4/IPv6, public/private, allowlists, warn modes) should be sampled for edge case coverage and mock DNS behavior correctness.
  • Configuration impact: New settings introduction and default disable-by-default behavior should be verified against migration/compatibility considerations.

Pre-merge checks and finishing touches

✅ Passed checks (7 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding SSRF protection configuration for API Requests.
Docstring Coverage ✅ Passed Docstring coverage is 98.31% which is sufficient. The required threshold is 80.00%.
Test Coverage For New Implementations ✅ Passed PR includes comprehensive test coverage: new test_ssrf_protection.py with multiple test functions covering all public functions and SSRFProtectionError; TestAPIRequestSSRFProtection class added to test_api_request_component.py with multiple async test methods verifying SSRF scenarios; all tests contain actual implementations with assertions and mocks, not placeholders.
Test Quality And Coverage ✅ Passed Test suite comprehensively covers SSRF protection with 15+ utility tests, 8+ API component integration tests, proper error handling with pytest.raises, HTTP mocking with respx, and verification of critical security scenarios including localhost/private network blocking, allowlist bypass, IPv6 handling, and redirect following.
Test File Naming And Structure ✅ Passed Test files follow pytest naming conventions (test_*.py) and are properly organized in directory hierarchies. The backend test file contains well-organized test classes with highly descriptive function names covering SSRF protection scenarios comprehensively.
Excessive Mock Usage Warning ✅ Passed Tests appropriately mock external dependencies (DNS, HTTP) while testing core SSRF logic with real implementations. Assertions verify behavior, not mock invocations.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Nov 10, 2025
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (1)
src/lfx/src/lfx/utils/ssrf_protection.py (1)

139-162: Consider Pythonic refactor for IP blocking check.

The loop checking blocked ranges (lines 155-159) can be simplified using any() for a more Pythonic approach:

     try:
-        if isinstance(ip, str):
-            ip_obj = ipaddress.ip_address(ip)
-        else:
-            ip_obj = ip
+        ip_obj = ipaddress.ip_address(ip) if isinstance(ip, str) else ip
 
-        # Check against all blocked ranges
-        for blocked_range in BLOCKED_IP_RANGES:
-            if ip_obj in blocked_range:
-                return True
-
-        return False
+        return any(ip_obj in blocked_range for blocked_range in BLOCKED_IP_RANGES)
     except (ValueError, ipaddress.AddressValueError):
         # If we can't parse the IP, treat it as blocked for safety
         return True
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 403b939 and e9cf4e1.

📒 Files selected for processing (5)
  • src/backend/tests/unit/components/data/test_api_request_component.py (3 hunks)
  • src/lfx/src/lfx/components/data/api_request.py (4 hunks)
  • src/lfx/src/lfx/services/settings/base.py (1 hunks)
  • src/lfx/src/lfx/utils/ssrf_protection.py (1 hunks)
  • src/lfx/tests/unit/utils/test_ssrf_protection.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
src/backend/tests/unit/components/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

src/backend/tests/unit/components/**/*.py: Mirror the component directory structure for unit tests in src/backend/tests/unit/components/
Use ComponentTestBaseWithClient or ComponentTestBaseWithoutClient as base classes for component unit tests
Provide file_names_mapping for backward compatibility in component tests
Create comprehensive unit tests for all new components

Files:

  • src/backend/tests/unit/components/data/test_api_request_component.py
{src/backend/**/*.py,tests/**/*.py,Makefile}

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

{src/backend/**/*.py,tests/**/*.py,Makefile}: Run make format_backend to format Python code before linting or committing changes
Run make lint to perform linting checks on backend Python code

Files:

  • src/backend/tests/unit/components/data/test_api_request_component.py
src/backend/tests/unit/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/backend_development.mdc)

Test component integration within flows using create_flow, build_flow, and get_build_events utilities

Files:

  • src/backend/tests/unit/components/data/test_api_request_component.py
src/backend/tests/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/testing.mdc)

src/backend/tests/**/*.py: Unit tests for backend code must be located in the 'src/backend/tests/' directory, with component tests organized by component subdirectory under 'src/backend/tests/unit/components/'.
Test files should use the same filename as the component under test, with an appropriate test prefix or suffix (e.g., 'my_component.py' → 'test_my_component.py').
Use the 'client' fixture (an async httpx.AsyncClient) for API tests in backend Python tests, as defined in 'src/backend/tests/conftest.py'.
When writing component tests, inherit from the appropriate base class in 'src/backend/tests/base.py' (ComponentTestBase, ComponentTestBaseWithClient, or ComponentTestBaseWithoutClient) and provide the required fixtures: 'component_class', 'default_kwargs', and 'file_names_mapping'.
Each test in backend Python test files should have a clear docstring explaining its purpose, and complex setups or mocks should be well-commented.
Test both sync and async code paths in backend Python tests, using '@pytest.mark.asyncio' for async tests.
Mock external dependencies appropriately in backend Python tests to isolate unit tests from external services.
Test error handling and edge cases in backend Python tests, including using 'pytest.raises' and asserting error messages.
Validate input/output behavior and test component initialization and configuration in backend Python tests.
Use the 'no_blockbuster' pytest marker to skip the blockbuster plugin in tests when necessary.
Be aware of ContextVar propagation in async tests; test both direct event loop execution and 'asyncio.to_thread' scenarios to ensure proper context isolation.
Test error handling by mocking internal functions using monkeypatch in backend Python tests.
Test resource cleanup in backend Python tests by using fixtures that ensure proper initialization and cleanup of resources.
Test timeout and performance constraints in backend Python tests using 'asyncio.wait_for' and timing assertions.
Test Langflow's Messag...

Files:

  • src/backend/tests/unit/components/data/test_api_request_component.py
src/backend/**/*component*.py

📄 CodeRabbit inference engine (.cursor/rules/icons.mdc)

In your Python component class, set the icon attribute to a string matching the frontend icon mapping exactly (case-sensitive).

Files:

  • src/backend/tests/unit/components/data/test_api_request_component.py
src/backend/**/components/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/icons.mdc)

In your Python component class, set the icon attribute to a string matching the frontend icon mapping exactly (case-sensitive).

Files:

  • src/backend/tests/unit/components/data/test_api_request_component.py
🧠 Learnings (7)
📚 Learning: 2025-07-21T14:16:14.125Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-21T14:16:14.125Z
Learning: Applies to src/backend/tests/**/*.py : Test Langflow's REST API endpoints in backend Python tests using the async client fixture and asserting response codes and payloads.

Applied to files:

  • src/backend/tests/unit/components/data/test_api_request_component.py
📚 Learning: 2025-08-05T22:51:27.961Z
Learnt from: edwinjosechittilappilly
Repo: langflow-ai/langflow PR: 0
File: :0-0
Timestamp: 2025-08-05T22:51:27.961Z
Learning: The TestComposioComponentAuth test in src/backend/tests/unit/components/bundles/composio/test_base_composio.py demonstrates proper integration testing patterns for external API components, including real API calls with mocking for OAuth completion, comprehensive resource cleanup, and proper environment variable handling with pytest.skip() fallbacks.

Applied to files:

  • src/backend/tests/unit/components/data/test_api_request_component.py
📚 Learning: 2025-07-18T18:25:54.486Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/backend_development.mdc:0-0
Timestamp: 2025-07-18T18:25:54.486Z
Learning: Applies to src/backend/tests/unit/components/**/*.py : Create comprehensive unit tests for all new components

Applied to files:

  • src/backend/tests/unit/components/data/test_api_request_component.py
📚 Learning: 2025-07-21T14:16:14.125Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-21T14:16:14.125Z
Learning: Applies to src/backend/tests/**/*.py : Test backward compatibility across Langflow versions in backend Python tests by mapping component files to supported versions using 'VersionComponentMapping'.

Applied to files:

  • src/backend/tests/unit/components/data/test_api_request_component.py
📚 Learning: 2025-07-21T14:16:14.125Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-21T14:16:14.125Z
Learning: Applies to src/backend/tests/**/*.py : Test components that require external APIs using appropriate pytest markers (e.g., 'api_key_required', 'no_blockbuster') and environment variables for API keys.

Applied to files:

  • src/backend/tests/unit/components/data/test_api_request_component.py
📚 Learning: 2025-07-21T14:16:14.125Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-21T14:16:14.125Z
Learning: Applies to src/backend/tests/**/*.py : Test component configuration updates in backend Python tests by asserting correct updates to build configuration objects.

Applied to files:

  • src/backend/tests/unit/components/data/test_api_request_component.py
📚 Learning: 2025-07-21T14:16:14.125Z
Learnt from: CR
Repo: langflow-ai/langflow PR: 0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-21T14:16:14.125Z
Learning: Applies to src/backend/tests/**/*.py : Use 'anyio' and 'aiofiles' for async file operations in backend Python tests that involve file handling.

Applied to files:

  • src/backend/tests/unit/components/data/test_api_request_component.py
🧬 Code graph analysis (4)
src/lfx/src/lfx/utils/ssrf_protection.py (1)
src/backend/base/langflow/services/deps.py (1)
  • get_settings_service (122-135)
src/lfx/src/lfx/components/data/api_request.py (2)
src/lfx/src/lfx/utils/ssrf_protection.py (2)
  • SSRFProtectionError (35-38)
  • validate_url_for_ssrf (204-327)
src/lfx/src/lfx/custom/custom_component/component.py (1)
  • log (1480-1497)
src/lfx/tests/unit/utils/test_ssrf_protection.py (2)
src/lfx/src/lfx/utils/ssrf_protection.py (6)
  • SSRFProtectionError (35-38)
  • get_allowed_hosts (72-82)
  • is_host_allowed (85-136)
  • is_ip_blocked (139-162)
  • resolve_hostname (165-201)
  • validate_url_for_ssrf (204-327)
src/backend/tests/unit/components/data/test_api_request_component.py (1)
  • test_ssrf_protection_disabled_by_default (376-386)
src/backend/tests/unit/components/data/test_api_request_component.py (3)
src/lfx/src/lfx/components/data/api_request.py (2)
  • APIRequestComponent (45-577)
  • make_api_request (422-487)
src/lfx/src/lfx/schema/data.py (1)
  • Data (26-288)
src/lfx/src/lfx/utils/ssrf_protection.py (1)
  • SSRFProtectionError (35-38)
🪛 GitHub Actions: Ruff Style Check
src/backend/tests/unit/components/data/test_api_request_component.py

[error] 393-393: SIM117 Use a single with statement with multiple contexts instead of nested with statements.

🪛 GitHub Check: Ruff Style Check (3.13)
src/lfx/src/lfx/utils/ssrf_protection.py

[failure] 155-159: Ruff (SIM110)
src/lfx/src/lfx/utils/ssrf_protection.py:155:9: SIM110 Use return any(ip_obj in blocked_range for blocked_range in BLOCKED_IP_RANGES) instead of for loop


[failure] 149-152: Ruff (SIM108)
src/lfx/src/lfx/utils/ssrf_protection.py:149:9: SIM108 Use ternary operator ip_obj = ipaddress.ip_address(ip) if isinstance(ip, str) else ip instead of if-else-block


[failure] 73-78: Ruff (D212)
src/lfx/src/lfx/utils/ssrf_protection.py:73:5: D212 Multi-line docstring summary should start at the first line


[failure] 38-38: Ruff (PIE790)
src/lfx/src/lfx/utils/ssrf_protection.py:38:5: PIE790 Unnecessary pass statement


[failure] 27-32: Ruff (I001)
src/lfx/src/lfx/utils/ssrf_protection.py:27:1: I001 Import block is un-sorted or un-formatted

src/backend/tests/unit/components/data/test_api_request_component.py

[failure] 488-489: Ruff (SIM117)
src/backend/tests/unit/components/data/test_api_request_component.py:488:9: SIM117 Use a single with statement with multiple contexts instead of nested with statements


[failure] 473-477: Ruff (SIM117)
src/backend/tests/unit/components/data/test_api_request_component.py:473:9: SIM117 Use a single with statement with multiple contexts instead of nested with statements


[failure] 458-462: Ruff (SIM117)
src/backend/tests/unit/components/data/test_api_request_component.py:458:9: SIM117 Use a single with statement with multiple contexts instead of nested with statements


[failure] 427-428: Ruff (SIM117)
src/backend/tests/unit/components/data/test_api_request_component.py:427:9: SIM117 Use a single with statement with multiple contexts instead of nested with statements


[failure] 393-394: Ruff (SIM117)
src/backend/tests/unit/components/data/test_api_request_component.py:393:9: SIM117 Use a single with statement with multiple contexts instead of nested with statements

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 5
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 1
  • GitHub Check: Lint Backend / Run Mypy (3.10)
  • GitHub Check: Lint Backend / Run Mypy (3.11)
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 4
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 2
  • GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 3
  • GitHub Check: Lint Backend / Run Mypy (3.13)
  • GitHub Check: Run Backend Tests / LFX Tests - Python 3.10
  • GitHub Check: Run Backend Tests / Integration Tests - Python 3.10
  • GitHub Check: Test Starter Templates
  • GitHub Check: Update Starter Projects
  • GitHub Check: Update Component Index
🔇 Additional comments (16)
src/lfx/src/lfx/services/settings/base.py (1)

320-329: LGTM! Well-documented backward-compatible settings.

The SSRF protection settings are appropriately designed with:

  • Clear documentation explaining the protection scope
  • Default values that maintain backward compatibility (protection disabled by default)
  • Forward-looking notes about v2.0 breaking changes
  • Support for flexible allowlist patterns (exact hostnames, wildcards, IPs, CIDR ranges)

The integration with the existing CustomSource for comma-separated list parsing is clean.

src/lfx/src/lfx/utils/ssrf_protection.py (1)

204-327: Excellent validation logic with clear error messages.

The main validation function is well-structured:

  • Early exit for disabled protection (line 224)
  • Allowlist bypass checks before expensive DNS resolution
  • Clear, actionable error messages with remediation steps
  • Proper handling of both direct IPs and hostnames
  • IPv6 zone ID cleanup in DNS resolution

The warn-only mode provides a smooth migration path for users.

src/lfx/src/lfx/components/data/api_request.py (4)

30-30: Good integration of SSRF protection imports.

The imports are correctly placed and will provide the necessary validation capabilities.


146-157: Security-focused breaking change well-documented.

Changing follow_redirects default from True to False is the right security posture. The expanded warning message clearly explains the SSRF bypass risk and references OWASP best practices.

This is a component-level change that prompts users to review, allowing them to opt-in if needed.


433-440: Effective runtime security warning.

The runtime warning when redirects are enabled reinforces the security implications and will help users understand the risks during development and debugging.


454-462: SSRF validation properly integrated.

The validation is correctly positioned:

  1. After URL normalization (line 447)
  2. After URL validation (line 450-452)
  3. Before query parameter processing (line 463-472)

The warn_only=True parameter provides backward compatibility while still logging warnings to prepare users for v2.0.

src/backend/tests/unit/components/data/test_api_request_component.py (4)

33-33: Test fixture correctly updated for security default.

The change to follow_redirects: False aligns with the component's new secure default.


346-375: Comprehensive SSRF test class added.

Good test organization with a dedicated class for SSRF protection scenarios. The fixtures are properly structured and reuse the component setup pattern.


376-558: Excellent SSRF protection test coverage.

The test suite comprehensively covers:

  • Default disabled state
  • Blocking scenarios (localhost, private networks, cloud metadata)
  • Public URL allowance
  • Allowlist bypass (exact hosts, CIDR ranges)
  • Warn-only mode behavior
  • Security warnings for redirects
  • URL normalization

This provides strong confidence in the SSRF protection implementation.


411-422: Simplify nested with statements in loop.

Same issue as above - combine the nested contexts.

Apply this pattern for each iteration:

-        with patch.dict(os.environ, {"LANGFLOW_SSRF_PROTECTION_ENABLED": "true"}):
             for url in private_ips:
                 component.url_input = url
 
-                with patch("lfx.components.data.api_request.validate_url_for_ssrf") as mock_validate:
+        with patch.dict(os.environ, {"LANGFLOW_SSRF_PROTECTION_ENABLED": "true"}):
+            for url in private_ips:
+                component.url_input = url
+
+                with patch("lfx.components.data.api_request.validate_url_for_ssrf") as mock_validate:
                     from lfx.utils.ssrf_protection import SSRFProtectionError
 
                     mock_validate.side_effect = SSRFProtectionError(f"Access to {url} blocked")
 
                     with pytest.raises(ValueError, match="SSRF Protection"):
                         await component.make_api_request()

Actually, the current structure is fine since the patch needs to be recreated for each iteration. The outer with should stay as is.

Likely an incorrect or invalid review comment.

src/lfx/tests/unit/utils/test_ssrf_protection.py (6)

1-72: Well-structured configuration tests.

The TestSSRFProtectionConfiguration class thoroughly tests:

  • Default disabled state (with TODO noting v2.0 change)
  • Environment variable parsing with parametrized true/false values
  • Allowlist parsing for various formats

Good use of @pytest.mark.parametrize for comprehensive coverage.


74-143: Comprehensive IP blocking test coverage.

The TestIPBlocking class validates all blocked IP ranges:

  • Loopback addresses
  • RFC 1918 private networks
  • Cloud metadata endpoints (169.254.169.254)
  • Special-use ranges
  • IPv6 private ranges

Also tests public IP allowance and invalid IP safety handling.


195-217: Good hostname resolution tests.

Tests cover:

  • Public hostname resolution (using stable dns.google)
  • Localhost resolution
  • Invalid hostname error handling

The use of a stable public service is smart for reliable CI runs.


219-359: Extensive URL validation tests.

The TestURLValidation class provides comprehensive coverage:

  • Protection disabled mode
  • Scheme validation (http/https only, blocks ftp/file)
  • Direct IP blocking (loopback, private, metadata)
  • Public IP/hostname allowance
  • Allowlist bypass (hostname, IP, CIDR)
  • Warn-only mode
  • Malformed URLs
  • IPv6 addresses

Excellent use of mocking for DNS resolution to test deterministically.


361-408: Realistic integration scenario tests.

The TestIntegrationScenarios class validates real-world attack vectors:

  • AWS metadata endpoint (169.254.169.254)
  • Internal admin panels
  • Legitimate external APIs
  • Docker internal networking

These tests demonstrate the practical security value of the protection.


145-193: Remove the false bug claim and approve the tests.

The TestHostnameAllowlist class provides thorough coverage of hostname allowlist functionality including exact matches, wildcards, IP addresses, and CIDR ranges. The implementation of get_allowed_hosts() is correct—it expects a string from settings, splits it into a list, and returns list[str]. The is_host_allowed() function correctly consumes this list. No type mismatch bug exists. The test failure you may encounter is likely due to environment configuration (module import path), not a code defect.

Comment thread src/backend/tests/unit/components/data/test_api_request_component.py Outdated
Comment thread src/backend/tests/unit/components/data/test_api_request_component.py Outdated
Comment thread src/backend/tests/unit/components/data/test_api_request_component.py Outdated
Comment thread src/backend/tests/unit/components/data/test_api_request_component.py Outdated
Comment thread src/backend/tests/unit/components/data/test_api_request_component.py Outdated
Comment thread src/lfx/src/lfx/utils/ssrf_protection.py Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Nov 10, 2025

Frontend Unit Test Coverage Report

Coverage Summary

Lines Statements Branches Functions
Coverage: 15%
14.66% (3955/26977) 7.45% (1533/20560) 8.99% (532/5914)

Unit Test Results

Tests Skipped Failures Errors Time
1588 0 💤 0 ❌ 0 🔥 17.625s ⏱️

@codecov
Copy link
Copy Markdown

codecov Bot commented Nov 10, 2025

Codecov Report

❌ Patch coverage is 82.01439% with 25 lines in your changes missing coverage. Please review.
✅ Project coverage is 31.55%. Comparing base (b535950) to head (fa93aaa).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
src/lfx/src/lfx/utils/ssrf_protection.py 81.48% 21 Missing and 4 partials ⚠️

❌ Your project status has failed because the head coverage (39.58%) is below the target coverage (60.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #10544      +/-   ##
==========================================
+ Coverage   31.45%   31.55%   +0.10%     
==========================================
  Files        1328     1329       +1     
  Lines       60153    60292     +139     
  Branches     8994     9022      +28     
==========================================
+ Hits        18920    19025     +105     
- Misses      40326    40356      +30     
- Partials      907      911       +4     
Flag Coverage Δ
backend 51.07% <ø> (-0.06%) ⬇️
frontend 13.55% <ø> (ø)
lfx 39.58% <82.01%> (+0.30%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/lfx/src/lfx/services/settings/base.py 69.63% <100.00%> (+0.29%) ⬆️
src/lfx/src/lfx/utils/ssrf_protection.py 81.48% <81.48%> (ø)

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread src/lfx/src/lfx/services/settings/base.py
Comment thread src/lfx/src/lfx/utils/ssrf_protection.py Outdated
Comment thread src/lfx/src/lfx/utils/ssrf_protection.py Outdated
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Nov 10, 2025
Copy link
Copy Markdown
Contributor

@ogabrielluiz ogabrielluiz left a comment

Choose a reason for hiding this comment

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

LGTM

@github-actions github-actions Bot added lgtm This PR has been approved by a maintainer enhancement New feature or request and removed enhancement New feature or request labels Nov 10, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Nov 12, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Nov 12, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Nov 12, 2025
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Nov 12, 2025
@jordanrfrazier jordanrfrazier added this pull request to the merge queue Nov 12, 2025
Merged via the queue into main with commit 7b84a7e Nov 12, 2025
81 of 82 checks passed
@jordanrfrazier jordanrfrazier deleted the issue-10355 branch November 12, 2025 03:29
@mendonk mendonk mentioned this pull request Nov 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request lgtm This PR has been approved by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants