Skip to content

Add block_failure telemetry to jersey, resteasy, commons-fileupload and okhttp - #12519

Merged
gh-worker-dd-mergequeue-cf854d[bot] merged 3 commits into
masterfrom
block-telemetry-2b
Sep 18, 2026
Merged

gh-worker-dd-mergequeue-cf854d[bot] merged 3 commits into
masterfrom
block-telemetry-2b

Conversation

@jandro996

@jandro996 jandro996 commented Sep 16, 2026 •

Copy link
Copy Markdown
Member

What Does This Do

Reports a block_failure tag on the appsec.waf.requests metric whenever a WAF-decided
block silently fails to actually commit, for jersey (2.x/3.x), resteasy (3.x),
commons-fileupload, and okhttp (client-side RASP/SSRF). This is Group 2b of a broader
effort covering all frameworks with blocking support.

The check is centralized in a new default method on BlockResponseFunction:
tryCommitBlockingResponse(RequestContext, RequestBlockingAction). It attempts the commit via
the existing (TraceSegment, RequestBlockingAction) overload and, on false, resolves
AppSecContext from RequestContextSlot.APPSEC data (instanceof AppSecContext check, never
cast directly to AppSecRequestContext) and calls reportBlockFailure(). Any exception thrown
by the underlying commit still propagates unchanged. The existing 2-arg overload is left
untouched so call sites outside this task's scope (RASP) keep their current behavior.

New callsites

All 13 Group 2b call sites now call the new overload with a single line,
brf.tryCommitBlockingResponse(ctx, rba):

  • jersey2/MultiPartHelper#tryBlock(), MessageBodyReaderInstrumentation, UriRoutingContextInstrumentation
  • jersey3/MultiPartHelper#tryBlock(), MessageBodyReaderInstrumentation
  • resteasy/MultipartHelper#tryBlock(), DecodedFormParametersInstrumentation, MessageBodyReaderInvocationInstrumentation, MethodExpressionInstrumentation
  • commons-fileupload/CommonsFileUploadAppSecInstrumentation (both the filenames and file content call sites)
  • okhttp2/AppSecInterceptor#publish(), okhttp3/AppSecInterceptor#publish()

netty/NettyMultipartHelper#tryBlock() (already merged in #12316) was updated to the same
overload for consistency, since it implements the identical pattern.

No new cross-module helper class was introduced and no helperClassNames() changes were made
anywhere: BlockResponseFunction already lives in internal-api and every call site already
invoked its pre-existing default method via ordinary virtual dispatch, so adding a second
overload there carries none of the classloader/muzzle risk a new shared helper class would.

Tests

  • New JUnit 5 test BlockResponseFunctionTest (hand-written test doubles, no Mockito) covers
    the centralized commit-and-report logic directly.
  • Per-call-site tests (Groovy/Spock instrumentation specs and the okhttp Mockito tests) were
    simplified to verify wiring only, i.e. that tryCommitBlockingResponse(ctx, rba) is called -
    the commit/report behavior itself is now covered once, centrally.
  • One incidental fix: GlassFishBlockingHelperTest (tomcat-appsec-7.0, unrelated to this task's
    scope) used an untyped Mockito any() matcher that became ambiguous once
    BlockResponseFunction gained a second overload; retyped to any(TraceSegment.class).

Motivation

Part of the block-outcome telemetry effort: without this, a block decision that silently fails to
commit (e.g. response already committed by the container) is indistinguishable from a successful
block in the appsec.waf.requests metric, hiding real blocking failures from monitoring.

The centralization itself was requested during review (see PR discussion): every call site
funneled into tryCommitBlockingResponse, so reportBlockFailure belongs there instead of being
duplicated at each site.

Additional Notes

None.

Contributor Checklist

Jira ticket: APPSEC-62696

Note: Once your PR is ready to merge, add it to the merge queue by commenting /merge. /merge -c cancels the queue request. /merge -f --reason "reason" skips all merge queue checks; please use this judiciously, as some checks do not run at the PR-level. For more information, see this doc.

…t (Group 2b)

Group 2b: jersey (2.x/3.x), resteasy (3.x), commons-fileupload, and okhttp
(client-side RASP/SSRF). Each call site checks the boolean return of
BlockResponseFunction#tryCommitBlockingResponse(...) and, on false, reports
the failure via AppSecContext#reportBlockFailure() (instanceof-checked, never
cast to AppSecRequestContext). Only reported when a BlockResponseFunction was
actually present.

Adds JUnit5 unit tests for the extractable call sites (jersey2/3 and resteasy
MultiPartHelper/MultipartHelper.tryBlock(), okhttp2/3 AppSecInterceptor) and
extends existing Groovy/Spock instrumentation tests for the inline @advice
sites that cannot be unit tested in isolation.
@jandro996 jandro996 added type: feature Enhancements and improvements comp: asm waf Application Security Management (WAF) inst: okhttp Square OkHttp instrumentation inst: others All other instrumentations tag: no release notes Changes to exclude from release notes and removed tag: no release notes Changes to exclude from release notes labels Sep 16, 2026
@jandro996

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 16, 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-17T08:58:54.103092Z 01b021b Manual request
🔒 Security Review ✅ Completed 2026-09-17T08:58:54.704596Z 01b021b Manual request
ℹ️ 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.

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 6320ac38f5

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 6320ac38f5

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@datadog-datadog-prod-us1

This comment has been minimized.

@dd-octo-sts

dd-octo-sts Bot commented Sep 16, 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.98 s 13.98 s [-0.7%; +0.6%] (no difference)
startup:insecure-bank:tracing:Agent 12.88 s 12.98 s [-1.4%; -0.1%] (maybe better)
startup:petclinic:appsec:Agent 17.57 s 17.41 s [+0.1%; +1.7%] (maybe worse)
startup:petclinic:iast:Agent 17.44 s 17.60 s [-1.8%; +0.0%] (no difference)
startup:petclinic:profiling:Agent 17.35 s 16.63 s [-0.2%; +8.8%] (no difference)
startup:petclinic:sca:Agent 17.67 s 17.51 s [+0.1%; +1.8%] (maybe worse)
startup:petclinic:tracing:Agent 16.32 s 16.65 s [-6.2%; +2.2%] (no difference)

Commit: 01b021b4 · 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
jandro996 marked this pull request as ready for review September 16, 2026 11:58
@jandro996
jandro996 requested review from a team as code owners September 16, 2026 11:58
@jandro996
jandro996 requested review from claponcet, manuel-alvarez-alvarez and ygree and removed request for a team September 16, 2026 11:58

@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.

Datadog Autotest: PASS

More details

Each changed call site reports a block failure only when the response function exists and the commit returns false. The handling is consistent across all changed integrations.

Was this helpful? React 👍 or 👎

Open Bits AI session

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

@ygree ygree 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.

It seems there is an opportunity to improve these changes by reducing code duplication.

Specifically, all calls to the tryCommitBlockingResponse method result in a call to reportBlockFailure if blocking fails. This raises the question: Should reportBlockFailure be part of tryCommitBlockingResponse instead?

This would also make the tests cleaner. There would be no need to verify that it's called in all cases where tryCommitBlockingResponse returns false. We would only need to verify that it's called by tryCommitBlockingResponse when blocking isn't possible, assuming that the existing tests already verify that tryCommitBlockingResponse is wired correctly.

Address reviewer feedback (review #5228047427) by moving the
commit-and-report logic into a new default overload,
tryCommitBlockingResponse(RequestContext, RequestBlockingAction),
instead of duplicating the check at each of the 13 call sites plus
Netty's. The existing (TraceSegment, RequestBlockingAction) overload
is left untouched so out-of-scope RASP call sites keep their current
behavior.

Per-call-site tests now verify wiring only; the commit-and-report
logic is covered once in the new BlockResponseFunctionTest.
…erTest

The new BlockResponseFunction#tryCommitBlockingResponse(RequestContext, RequestBlockingAction)
overload added in this branch makes the untyped any() matcher ambiguous against the
pre-existing (TraceSegment, RequestBlockingAction) overload this test actually exercises.
@jandro996

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

Reviewed commit: 01b021b457

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 01b021b457

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@jandro996

Copy link
Copy Markdown
Member Author

It seems there is an opportunity to improve these changes by reducing code duplication.

Specifically, all calls to the tryCommitBlockingResponse method result in a call to reportBlockFailure if blocking fails. This raises the question: Should reportBlockFailure be part of tryCommitBlockingResponse instead?

This would also make the tests cleaner. There would be no need to verify that it's called in all cases where tryCommitBlockingResponse returns false. We would only need to verify that it's called by tryCommitBlockingResponse when blocking isn't possible, assuming that the existing tests already verify that tryCommitBlockingResponse is wired correctly.

Good catch, and I agree. I'd originally kept this inlined at every call site on purpose to avoid introducing a new cross-module helper class, since a shared helper injected across instrumentation modules has classloader/muzzle implications I wanted to avoid for a telemetry-only change.
Looking closer, BlockResponseFunction already has a default tryCommitBlockingResponse(TraceSegment, RequestBlockingAction) overload in internal-api, and all 13 call sites here (plus Netty's, from #12316) use exactly that one. So we already have a single choke point

@jandro996
jandro996 requested a review from ygree September 17, 2026 09:48
jandro996 added a commit that referenced this pull request Sep 17, 2026
Replace the repeated inline pattern (commit blocking response, then
manually check AppSecContext and call reportBlockFailure() on failure)
with the new BlockResponseFunction.tryCommitBlockingResponse(RequestContext,
Flow.Action.RequestBlockingAction) default overload added in
block-telemetry-2b (#12519). That overload already performs the
AppSecContext lookup and reportBlockFailure() call internally, so call
sites only need to pass the RequestContext instead of the TraceSegment.

Applies to the 37 call sites identified as mechanically substitutable:
akka-http-10.0, grizzly-http-2.3.20, jetty-appsec (7.0, 8.1.3, 9.2, 9.3,
9.4, 11.0), jetty-server (7.0, 7.6), liberty (20.0, 23.0), spring-webmvc
(3.1, 6.0), and undertow-2.0. Excludes GrizzlyBlockingHelper (grizzly-2.0,
manual reflection-based commit) and jetty-server-9.0's
JettyCommitResponseInstrumentation (compound res && _committed.get()
condition, not mechanically equivalent to the new overload's plain
boolean return).
jandro996 added a commit that referenced this pull request Sep 17, 2026
Replace the repeated inline pattern (commit blocking response, then
manually check AppSecContext and call reportBlockFailure() on failure)
with the new BlockResponseFunction.tryCommitBlockingResponse(RequestContext,
Flow.Action.RequestBlockingAction) default overload added in
block-telemetry-2b (#12519). That overload already performs the
AppSecContext lookup and reportBlockFailure() call internally, so call
sites only need to pass the RequestContext instead of the TraceSegment.

Applies to the 37 call sites identified as mechanically substitutable:
akka-http-10.0, grizzly-http-2.3.20, jetty-appsec (7.0, 8.1.3, 9.2, 9.3,
9.4, 11.0), jetty-server (7.0, 7.6), liberty (20.0, 23.0), spring-webmvc
(3.1, 6.0), and undertow-2.0. Excludes GrizzlyBlockingHelper (grizzly-2.0,
manual reflection-based commit) and jetty-server-9.0's
JettyCommitResponseInstrumentation (compound res && _committed.get()
condition, not mechanically equivalent to the new overload's plain
boolean return).

@ygree ygree 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.

IDM approved

@jandro996
jandro996 added this pull request to the merge queue Sep 18, 2026
@dd-octo-sts

dd-octo-sts Bot commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

/merge

@gh-worker-devflow-routing-ef8351

gh-worker-devflow-routing-ef8351 Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

View all feedbacks in Devflow UI.

2026-09-18 07:17:10 UTC ℹ️ Start processing command /merge


2026-09-18 07:17:16 UTC ℹ️ MergeQueue: pull request added to the queue

The expected merge time in master is approximately 1h (p90).


2026-09-18 08:31:43 UTC ℹ️ MergeQueue: This merge request was merged

@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Sep 18, 2026
@gh-worker-dd-mergequeue-cf854d
gh-worker-dd-mergequeue-cf854d Bot merged commit b0a9e8e into master Sep 18, 2026
605 checks passed
@gh-worker-dd-mergequeue-cf854d
gh-worker-dd-mergequeue-cf854d Bot deleted the block-telemetry-2b branch September 18, 2026 08:31
@github-actions github-actions Bot added this to the 1.67.0 milestone Sep 18, 2026
jandro996 added a commit that referenced this pull request Sep 22, 2026
Master (#12519) added a default BlockResponseFunction.tryCommitBlockingResponse(RequestContext, RequestBlockingAction)
overload alongside the existing TraceSegment-based one, making bare any()
matchers ambiguous. Disambiguate with any(TraceSegment.class), matching
the overload GlassFishBlockingHelper actually invokes via BlockFailureReporter.
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: okhttp Square OkHttp instrumentation inst: others All other instrumentations type: feature Enhancements and improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants