Skip to content

Finish HTTP client spans and close scopes when AppSec blocks requests - #12611

Open
amarziali wants to merge 1 commit into
masterfrom
andrea.marziali/fix-http-blocking-scope-cleanup
Open

amarziali wants to merge 1 commit into
masterfrom
andrea.marziali/fix-http-blocking-scope-cleanup

Conversation

@amarziali

@amarziali amarziali commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

What Does This Do

AppSec blocking could leave an HTTP client span unfinished and its scope active in:

  • JDK HTTP client (send and sendAsync)
  • Apache HttpClient 4
  • Commons HttpClient 2

These instrumentations create and activate a client span before calling DECORATE.onRequest(). If AppSec throws BlockingException, entry advice aborts before handing the scope to exit advice. For async requests, no completion callback has been registered either.

Consequently, nobody finishes the client span or closes its scope. The unfinished client span cannot be reported as completed, and the lingering active context interferes with enclosing Spring and servlet scope cleanup. This does not necessarily prevent other finished spans in the trace from being published.

This PR cleans up the span and scope in the blocking path before rethrowing the exception, preserving call-depth reset and blocking behavior.

flowchart LR
  A[Create span and activate scope] --> B[AppSec blocks]
  B -->|Before| C[Entry advice aborts]
  C --> D[Unfinished span and active scope]
  B -->|Fixed| E[Decorate blocking error]
  E --> F[Close scope and restore parent]
  F --> G[Finish client span and rethrow]

  classDef broken fill:#fee2e2,stroke:#dc2626
  classDef healthy fill:#dcfce7,stroke:#16a34a
  class C,D broken
  class E,F,G healthy
Loading

Motivation

Instrumentation tests did not exercise the blocking callback path. Existing AppSec smoke tests checked the blocking response and security event, which could succeed despite incomplete tracing cleanup.

Enabling scope diagnostics in smoke tests exposed the missing cleanup.

Additional Notes

Contributor Checklist

Jira ticket: [PROJ-IDENT]

@amarziali amarziali added the type: bug fix Bug fix label Sep 23, 2026
@amarziali
amarziali requested review from a team as code owners September 23, 2026 13:50
@amarziali
amarziali requested review from PerfectSlayer and removed request for a team September 23, 2026 13:50
@amarziali amarziali added inst: others All other instrumentations comp: asm waf Application Security Management (WAF) tag: ai generated Largely based on code generated by an AI or LLM labels Sep 23, 2026
@amarziali
amarziali requested review from jordan-wong and removed request for a team September 23, 2026 13:50
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 23, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-23T13:55:32.744092Z 04c2d1a PR opened
🔒 Security Review Completed 2026-09-23T13:57:44.731829Z 04c2d1a PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@amarziali
amarziali requested a review from jandro996 September 23, 2026 13:51
@amarziali amarziali added the tag: override groovy enforcement Override the "Enforce Groovy Migration" check label Sep 23, 2026
@datadog-datadog-prod-us1

Copy link
Copy Markdown
Contributor

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 68.82% (+9.52%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 04c2d1a | Docs | Give us feedback!

@datadog-datadog-prod-us1 datadog-datadog-prod-us1 Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bits Code Review: PASS

More details

The blocking paths now reset call depth, restore the parent context, close the scope, and finish the client span before they throw the blocking exception.

Was this helpful? React 👍 or 👎

Open Bits AI session

🤖 Bits Code Review · Commit 04c2d1a · @DataDog review to ask questions

@dd-octo-sts

dd-octo-sts Bot commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

🟢 Java Benchmark SLOs — All performance SLOs passed

Suite Status
Startup 🟢 pass

SLO thresholds are defined here based on automatically generated metrics. A warning is raised when results are within 5% of the threshold.

PR vs. master results
Scenario Candidate master Δ (95% CI of mean)
startup:insecure-bank:iast:Agent 13.93 s 13.89 s [-0.5%; +1.2%] (no difference)
startup:insecure-bank:tracing:Agent 12.88 s 12.91 s [-0.9%; +0.4%] (no difference)
startup:petclinic:appsec:Agent 17.10 s 16.93 s [+0.1%; +1.9%] (maybe worse)
startup:petclinic:iast:Agent 16.93 s 17.05 s [-1.7%; +0.3%] (no difference)
startup:petclinic:profiling:Agent 16.63 s 16.91 s [-2.6%; -0.7%] (maybe better)
startup:petclinic:sca:Agent 16.99 s 16.85 s [-0.1%; +1.7%] (no difference)
startup:petclinic:tracing:Agent 16.20 s 16.21 s [-1.0%; +0.8%] (no difference)

Commit: 04c2d1a1 · CI Pipeline · Benchmarking Platform UI


Load and DaCapo benchmarks can be triggered manually in the GitLab pipeline. Results will appear in the Benchmarking Platform UI after completion.

@jandro996

Copy link
Copy Markdown
Member

Hey @amarziali not sure if this is part of a group of PRs to solve this kind of issues but I found that apache-httpclient-5.0 has the identical span/scope leak on BlockingException. activateHttpSpan() has no try/catch around DECORATE.onRequest(), and HelperMethods.onBlockingRequest() only resets CallDepthThreadLocalMap, never touches the span/scope. Worth a follow-up PR (or confirm it's intentionally out of scope here) since it's the same bug, one HTTP client version up.

@jandro996 jandro996 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM!

@amarziali

Copy link
Copy Markdown
Contributor Author

Hey @amarziali not sure if this is part of a group of PRs to solve this kind of issues but I found that apache-httpclient-5.0 has the identical span/scope leak on BlockingException. activateHttpSpan() has no try/catch around DECORATE.onRequest(), and HelperMethods.onBlockingRequest() only resets CallDepthThreadLocalMap, never touches the span/scope. Worth a follow-up PR (or confirm it's intentionally out of scope here) since it's the same bug, one HTTP client version up.

Good catch. Actually the diagnostics is plugged for trial on #12609 but can only audit things covered by a smoke tests. So yes it deserves a followup PR and a smoke tests so

DECORATE.afterStart(span);
DECORATE.onRequest(span, request);
} catch (BlockingException e) {
try {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

❔ question: ‏Should we have try / catch block here?
The only exception allowed is now a BlockingException since decorator methods are no longer allowed to raised anything else.

This branch has not been deployed

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

Labels

comp: asm waf Application Security Management (WAF) inst: others All other instrumentations tag: ai generated Largely based on code generated by an AI or LLM tag: override groovy enforcement Override the "Enforce Groovy Migration" check type: bug fix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants