fix(appsec): report request headers on Lambda spans#9257
Conversation
🎉 All green!🧪 All tests passed 🎯 Code Coverage (details) 🔗 Commit SHA: 0900ced | Docs | Datadog PR Page | Give us feedback! |
Overall package sizeSelf size: 6.65 MB Dependency sizes| name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.3.1 | 122.62 kB | 437.94 kB | | opentracing | 0.14.7 | 194.81 kB | 194.81 kB | | dc-polyfill | 0.1.11 | 25.74 kB | 25.74 kB |🤖 This report was automatically generated by heaviest-objects-in-the-universe |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted filesFlags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
BenchmarksBenchmark execution time: 2026-07-08 12:37:13 Comparing candidate commit 0900ced in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 2318 metrics, 40 unstable metrics.
|
What does this PR do?
Creates a single synthetic request object (
{ headers }) per Lambda invocation and uses it as thereqkey throughout the entire invocation lifecycle:waf.run,waf.disposeContext, andReporter.finishRequest.This gives
getCollectedHeadersaccess toreq.headersso that the standard ASM header tags are collected on Lambda spans when AppSec is enabledMotivation
Lambda spans were missing all
http.request.headers.*tags even when AppSec was active. The root cause was thatReporter.finishRequestwas called with the span asreq; sincespan.headersisundefined,getCollectedHeadersreturned empty tags every time.A first fix passed
{ headers }only tofinishRequest, but that introduced a WeakMap key mismatch:waf.runwas still keyed byspan, sometricsStoreMapandextendedDataCollectionRequestwere populated under one key and looked up under another. The result was that_dd.appsec.waf.duration,waf.timeouts, all RASP metrics, and extended data collection for attacks were silently dropped.Additional Notes
activeInvocationschanges fromWeakSet<span>toWeakMap<span, req>wherereq = { headers: headers ?? {} }.waf.disposeContextnow receivesreqinstead ofspan, the WAF context was already keyed by whichever object is passed towaf.run, so both must use the same object.'should use the same synthetic req key across WAF run, dispose, and finishRequest'pins object identity for all four call-sites and asserts the key is never the span, catching exactly the key-mismatch regression this PR fixes._dd.appsec.waf.duration,duration_ext, andhttp.request.headers.*tags all appear on real Lambda traces.