fix(web): re-check Firecrawl final URLs for SSRF - #35840
Conversation
tonydwb
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Approved ⚡
✅ What's Good
- Good SSRF defense-in-depth: Firecrawl can report a different final URL after scrape/redirect via
metadata.sourceURL. This patch properly re-checks that final URL withis_safe_url()before returning scraped content — closing a real SSRF bypass vector. - Clean integration: The new check sits naturally alongside the existing
check_website_accessredirect check. Thecontinueafter the block prevents any content leakage. - Well-structured test: The test verifies that the unsafe final URL is blocked, that the website policy check is NOT called for unsafe final URLs, and that scraped content is wiped. The mock setup is clean and focused.
- No scope creep: 2 files changed, 64 additions, 0 deletions — tightly scoped to the security concern.
- Existing test fix: The test monkeypatch for
is_safe_urlwas added to the redirected-final-url test to prevent false failures, showing good awareness of test interactions.
Summary
A tightly scoped, well-tested security fix. No issues found.
Reviewed by Hermes Agent
…al-url-ssrf-20260531
|
Recommendation: rebase or resolve the current-main conflict before merge. The security fix itself validated in focused checks. Checked current Validation:
GitHub currently reports Signed: GPT-5.5-xhigh in Codex |
Follow-up for salvaged PR #35840: current main removed the use_llm_processing kwarg (LLM summarization dropped) and moved the input SSRF gate to async_is_safe_url. Adjust the new firecrawl-final-url test to match.
|
Merged via PR #56143. Your commit was cherry-picked onto current main with your authorship preserved in git log (commit 2e12401). I added one small follow-up commit adapting the new test to the current web_extract_tool signature (main removed the use_llm_processing kwarg and moved the input SSRF gate to async_is_safe_url). Thanks for the security fix. |
Follow-up for salvaged PR NousResearch#35840: current main removed the use_llm_processing kwarg (LLM summarization dropped) and moved the input SSRF gate to async_is_safe_url. Adjust the new firecrawl-final-url test to match.
Follow-up for salvaged PR NousResearch#35840: current main removed the use_llm_processing kwarg (LLM summarization dropped) and moved the input SSRF gate to async_is_safe_url. Adjust the new firecrawl-final-url test to match.
Follow-up for salvaged PR NousResearch#35840: current main removed the use_llm_processing kwarg (LLM summarization dropped) and moved the input SSRF gate to async_is_safe_url. Adjust the new firecrawl-final-url test to match.
Follow-up for salvaged PR NousResearch#35840: current main removed the use_llm_processing kwarg (LLM summarization dropped) and moved the input SSRF gate to async_is_safe_url. Adjust the new firecrawl-final-url test to match.
Follow-up for salvaged PR NousResearch#35840: current main removed the use_llm_processing kwarg (LLM summarization dropped) and moved the input SSRF gate to async_is_safe_url. Adjust the new firecrawl-final-url test to match.
Follow-up for salvaged PR NousResearch#35840: current main removed the use_llm_processing kwarg (LLM summarization dropped) and moved the input SSRF gate to async_is_safe_url. Adjust the new firecrawl-final-url test to match.
Summary
metadata.sourceURLfinal URLs withis_safe_url()before returning scraped content.Security impact
web_extractalready rejects unsafe input URLs before dispatching to a backend. Firecrawl can report a different final URL after scrape/redirect viametadata.sourceURL; this patch blocks that final target before any scraped content is returned to the agent.Verification
uv run --extra dev ruff check plugins/web/firecrawl/provider.py tests/tools/test_website_policy.pyuv run --extra dev python -X utf8 -m pytest tests/tools/test_website_policy.py::TestWebToolPolicy::test_web_extract_blocks_firecrawl_unsafe_final_url tests/tools/test_website_policy.py::TestWebToolPolicy::test_web_extract_blocks_redirected_final_url -q --timeout-method=threaduv run --extra dev python -X utf8 -m pytest tests/tools/test_website_policy.py -q --timeout-method=threaduv run --extra dev ruff check .