Skip to content

Preserve captured response body when AppSec response hook fails - #12388

Open
dougqh wants to merge 1 commit into
dougqh/fix-appsec-interceptor-duplicate-requestfrom
dougqh/fix-appsec-interceptor-response-body-on-hook-failure
Open

Preserve captured response body when AppSec response hook fails#12388
dougqh wants to merge 1 commit into
dougqh/fix-appsec-interceptor-duplicate-requestfrom
dougqh/fix-appsec-interceptor-response-body-on-hook-failure

Conversation

@dougqh

@dougqh dougqh commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

What Does This Do

Wraps the publish() call for the AppSec response hook inside AppSecInterceptor.onResponse() in its own try/catch (matching the existing pattern for the request-hook path), so a non-blocking exception from the response hook no longer discards the already-rebuilt response.

Motivation

onResponse() rebuilds the response with the body it captured for AppSec analysis into a local result. If the response hook (publish()) then threw an exception other than BlockingException, that exception propagated out of onResponse() and intercept()'s outer catch fell back to the original response object — whose body had already been consumed reading it into result. Callers ended up seeing an empty/closed body instead of the real one.

Stacked on #12242, which fixed a related NPE (span.getTag(Tags.HTTP_URL) risk) flagged during the same review pass on that PR.

Additional Notes

  • Applied identically to both okhttp-2.2 and okhttp-3.0 instrumentation modules.
  • Added responseHookFailureAfterBodyCapturePreservesCapturedBody to AppSecInterceptorTest in both modules, verifying the response body survives a throwing response hook.
  • Existing AppSecInterceptorTest suites pass for both modules; ./gradlew spotlessApply run.
  • /techdebt and /perf-review run over the branch diff: no findings.

Contributor Checklist

Jira ticket: [PROJ-IDENT]

If publish() throws inside onResponse() after the response body has
already been read and rebuilt into `result`, the exception propagated
out of onResponse() and caused intercept() to fall back to the
original response, whose body had already been consumed. Callers then
saw an empty/closed body instead of the real one. Catch and log
non-blocking failures from publish() locally so the rebuilt response
is always returned.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@dougqh dougqh added type: bug fix Bug fix tag: ai generated Largely based on code generated by an AI or LLM inst: okhttp Square OkHttp instrumentation labels Sep 3, 2026
@dougqh
dougqh marked this pull request as ready for review September 3, 2026 00:24
@dougqh
dougqh requested a review from a team as a code owner September 3, 2026 00:24
@dougqh
dougqh requested review from vandonr and removed request for a team September 3, 2026 00:24
@datadog-prod-us1-5

Copy link
Copy Markdown
Contributor

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 69.74% (+0.00%)

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

@datadog-prod-us1-5 datadog-prod-us1-5 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.

Datadog Autotest: PASS

More details

The new catch keeps the rebuilt response when the AppSec hook fails. It does not catch BlockingException.

Was this helpful? React 👍 or 👎

Open Bits AI session

🤖 Datadog Autotest · Commit 04ae7fb · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest

@dd-octo-sts

dd-octo-sts Bot commented Sep 3, 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 14.71 s 14.64 s [-0.2%; +1.2%] (no difference)
startup:insecure-bank:tracing:Agent 13.71 s 13.72 s [-0.7%; +0.6%] (no difference)
startup:petclinic:appsec:Agent 17.56 s 17.30 s [+0.6%; +2.5%] (maybe worse)
startup:petclinic:iast:Agent 17.44 s 17.01 s [-2.0%; +7.0%] (no difference)
startup:petclinic:profiling:Agent 17.36 s 17.28 s [-0.9%; +1.8%] (no difference)
startup:petclinic:sca:Agent 17.43 s 17.33 s [-0.5%; +1.6%] (no difference)
startup:petclinic:tracing:Agent 16.37 s 16.21 s [-3.4%; +5.4%] (no difference)

Commit: 04ae7fbc · 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.

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

Labels

inst: okhttp Square OkHttp instrumentation tag: ai generated Largely based on code generated by an AI or LLM type: bug fix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant