Skip to content

fix(aap): use ASGI raw_path for WAF URI evaluation to enable LFI detection on FastAPI#17223

Draft
christophe-papazian wants to merge 5 commits intomainfrom
christophe-papazian/fix_fastapi_test
Draft

fix(aap): use ASGI raw_path for WAF URI evaluation to enable LFI detection on FastAPI#17223
christophe-papazian wants to merge 5 commits intomainfrom
christophe-papazian/fix_fastapi_test

Conversation

@christophe-papazian
Copy link
Copy Markdown
Contributor

@christophe-papazian christophe-papazian commented Mar 31, 2026

APPSEC-61974

Description

The ASGI middleware was passing the framework-resolved scope["path"] as raw_uri to the WAF. ASGI frameworks like Starlette/FastAPI resolve path traversal sequences (e.g. /waf/../ becomes /) in scope["path"] before the middleware sees it. This prevented some URI-based detection rules from triggering on ASGI-based frameworks. The fix uses scope["raw_path"] which preserves the original URI as sent by the client, matching how the WSGI integration already uses RAW_URI.

Changes

Production fix (ddtrace/contrib/internal/asgi/middleware.py):

  • Use scope["raw_path"] for the raw_uri parameter passed to set_http_meta / WAF evaluation
  • scope["path"] is still used for the http.url span tag (user-facing, shows resolved URL)
  • Falls back to scope["path"] when raw_path is not available

Test client fix (tests/appsec/contrib_appsec/test_fastapi.py):

  • Patched the FastAPI TestClient transport to inject the original URL path as scope["raw_path"] in the ASGI scope
  • httpx resolves path traversal at the HTTP client level before creating the ASGI scope; real ASGI servers (uvicorn) preserve it
  • Guarded with getattr(client, "_transport", None) for older Starlette/httpx versions that don't expose the transport

Test enablement (tests/appsec/contrib_appsec/utils.py):

  • Removed the FastAPI skip on test_request_suspicious_request_block_match_uri_lfi
  • Added a skip for old FastAPI versions where the TestClient doesn't support _transport (raw_path injection not possible)

Testing

  • Full appsec_threats_fastapi_no_iast suite (py3.13, fastapi ~0.114.2): 1003 passed, 0 failed
  • FastAPI 0.86.0 (oldest): LFI test skipped cleanly (no _transport available)
  • LFI test passes on all 4 frameworks with recent versions (Flask, Django, Tornado, FastAPI)

Risks

  • scope["raw_path"] may not be present in all ASGI servers — the code falls back to scope["path"] when raw_path is None, so there's no regression risk.

Additional Notes

  • The WSGI integration already correctly uses RAW_URI / REQUEST_URI (see ddtrace/contrib/internal/wsgi/wsgi.py line 248). This fix brings ASGI to parity.

@christophe-papazian christophe-papazian added the ASM Application Security Monitoring label Mar 31, 2026
@cit-pr-commenter-54b7da
Copy link
Copy Markdown

cit-pr-commenter-54b7da bot commented Mar 31, 2026

Codeowners resolved as

tests/appsec/contrib_appsec/test_fastapi.py                             @DataDog/asm-python
tests/appsec/contrib_appsec/utils.py                                    @DataDog/asm-python

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ASM Application Security Monitoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant