Skip to content

Add server.request.body.files_content AppSec address for Jersey and RESTEasy#11229

Draft
jandro996 wants to merge 46 commits intomasterfrom
alejandro.gonzalez/APPSEC-61875-files-content-jersey-resteasy
Draft

Add server.request.body.files_content AppSec address for Jersey and RESTEasy#11229
jandro996 wants to merge 46 commits intomasterfrom
alejandro.gonzalez/APPSEC-61875-files-content-jersey-resteasy

Conversation

@jandro996
Copy link
Copy Markdown
Member

@jandro996 jandro996 commented Apr 29, 2026

What Does This Do

Extends the server.request.body.files_content WAF address to Jersey 2.0, Jersey 3.0, and RESTEasy 3.0 multipart instrumentations, complementing the Tomcat + Netty implementation (PR #11198).

Jersey 2.0 and 3.0

  • Extends collectBodyPart() with a fourth List<String> filesContent parameter; content is collected when rawFilename != null (filename attribute present, even if empty) and the count limit has not been reached
  • Adds readContent(FormDataBodyPart) using try-with-resources around getEntityAs(InputStream.class) — backed by BodyPartEntity, which supports re-reading from an in-memory buffer
  • Adds tryBlock(RequestContext, Flow<Void>, String) helper with canonical ordering: BlockingException created before effectivelyBlocked()
  • Updates MultiPartReaderServerSideInstrumentation to fetch contentCallback, add the three-way guard (callback == null && filenamesCallback == null && contentCallback == null), collect filesContent, and dispatch the content callback gated on t == null (fires only if neither body nor filenames blocked)

RESTEasy 3.0

  • Adds collectFilesContent(MultipartFormDataInput) mirroring collectFilenames(): uses the cached static final GET_HEADERS reflection handle to read Content-Disposition per part; collects content when rawFilenameFromContentDisposition() returns non-null (present-but-empty filename still yields content)
  • Adds readContent(InputPart, String) with try-with-resources around InputPart.getBody(InputStream.class, null)
  • Adds tryBlock(RequestContext, Flow<Void>, String) with the same canonical ordering as Jersey
  • Updates MultipartFormDataReaderInstrumentation with the three-way guard and content callback dispatch gated on t == null

Tests

  • MultiPartHelperTest (jersey-appsec-2.0 and -3.0): new tests for readContent() (empty/null/non-empty filename gate, graceful skip on exception, MAX_FILES_TO_INSPECT limit) and four tryBlock tests (null brf, blocking action, interaction verification, null action)
  • MultipartHelperTest (resteasy-appsec-3.0): new tests for rawFilenameFromContentDisposition (absent / present-but-empty / non-empty, via reflection) and four tryBlock tests

Motivation

Part of APPSEC-61875 — full server.request.body.files_content coverage for all supported multipart frameworks. This PR covers Jersey and RESTEasy; Tomcat and Netty are covered by PR #11198.

Additional Notes

RESTEasy uses a cached static final Method GET_HEADERS (initialized once in a static {} block) to call InputPart.getHeaders() via reflection. This avoids a direct bytecode reference to MultivaluedMap, whose package differs between RESTEasy 3.x (javax.ws.rs.core) and RESTEasy 6.x (jakarta.ws.rs.core). A direct reference would cause muzzle validation to fail for one of the two version families.

This PR is stacked on alejandro.gonzalez/APPSEC-61875-files-content-tomcat-netty (PR #11198).

Contributor Checklist

Jira ticket: APPSEC-61875

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.

…entDecoder

Replaces hardcoded UTF-8 (no-charset default) and ISO-8859-1 (fallback)
with Charset.defaultCharset() in both cases, per reviewer feedback.
…ltipart

Read up to 4096 bytes per file (ISO-8859-1, max 25 files) and fire the
server.request.body.files_content callback after the filenames callback, only
when the request has not already been blocked.

- ParameterCollector: add readContent() via reflection on getInputStream(),
  getContents() getter, and MAX_FILES_TO_INSPECT guard
- ParsePartsInstrumentation: dispatch requestFilesContent() after
  requestFilesFilenames() when t == null
- HttpPostRequestDecoderInstrumentation: collect file content inline in the
  getBodyHttpDatas() loop (in-memory via ByteBuf, on-disk via FileInputStream)
  and dispatch requestFilesContent() when thr == null after filenames
- Add ParameterCollectorImplTest covering truncation, 25-file cap, form-field
  skip, IOException fallback, and ISO-8859-1 round-trip
…tation

Issue 1 — Netty: extract MAX_CONTENT_BYTES=4096 and MAX_FILES_TO_INSPECT=25 as
named constants in ParseBodyAdvice, replacing raw magic literals.

Issue 3 — Tomcat + Netty: call effectivelyBlocked() after tryCommitBlockingResponse
in both the filenames and files_content blocking paths, matching the behaviour
already present in CommonsFileUploadAppSecInstrumentation.

Issue 4 — Netty: collect file content for ALL FileUpload data items regardless
of whether filename is present or empty; HttpDataType.FileUpload is the
file-vs-form-field discriminator in Netty's model, so the filename-empty check
was incorrectly skipping content for unnamed file parts (inconsistent with
FileItemContentReader which only skips isFormField() items).
…ation

Issue 1 — Tomcat: inspect file content even when submitted filename is empty.
getSubmittedFileName() returns null for form fields (no filename parameter) and ""
for file uploads whose client explicitly sent filename="". Null is now the only
skip condition, so file parts with an empty filename are inspected but not added
to the filenames list, matching the commons-fileupload and Netty behaviour.

Issue 2 — Netty: remove unnecessary (long) casts in Math.min; both operands are
already int so Math.min(int,int) resolves directly.

Issue 3 — Netty: replace manual try/finally on FileInputStream with
try-with-resources, consistent with FileItemContentReader style.
…tty files_content

Move BlockingException assignment inside the brf != null guard so it is
only thrown when the blocking response was actually committed.  Also add
effectivelyBlocked() to the Tomcat body-processed path, and remove the
redundant if (t == null) guard there.

For the Netty body-processed path (urlencoded), effectivelyBlocked() is
intentionally omitted: tryCommitBlockingResponse() finishes the Netty
span synchronously, so calling effectivelyBlocked() afterwards would
interact with an already-closed TraceSegment.
…callback is unregistered

Pre-fetch the requestFilesContent callback before the body-data loop and
guard ByteBuf/FileInputStream reads behind it, consistent with how
CommonsFileUploadAppSecInstrumentation already does. Also flattens the
post-loop dispatch block by one nesting level.
…ad loop

Move thr = new BlockingException(...) for the filenames path in Netty
inside the brf != null guard, consistent with the body-processed and
content paths in the same advice and with the Tomcat/Liberty pattern.

Merge the two FileItem iterations in CommonsFileUploadAppSecInstrumentation
into a single loop that builds both filenames and filesContent in one pass,
calling FileItemContentReader.readContent() per item instead of a separate
FileItemContentReader.readContents() sweep.
The bulk readContents(List<FileItem>) method is no longer called — the
advice iterates file items inline calling readContent(FileItem) per item.
Remove the method, its now-unused ArrayList/List imports, and the
corresponding test cases. Also fix redundant type witness on ArrayList
construction in CommonsFileUploadAppSecInstrumentation.
…oad guard style

Skip filesContent ArrayList allocation in Netty ParseBodyAdvice when the
requestFilesContent callback is not registered, matching the null-sentinel
pattern already used in CommonsFileUploadAppSecInstrumentation.

Replace the early-return in CommonsFileUploadAppSecInstrumentation's
filenames blocking branch with a t == null guard on the content dispatch
block, aligning control flow with ParsePartsInstrumentation and
HttpPostRequestDecoderInstrumentation.
… callback is unregistered

Add an inspectContent boolean to ParameterCollectorImpl, set from the
presence of the requestFilesContent callback in ParsePartsInstrumentation
before(). When false, addPart() still collects filenames but skips the
getInputStream() read, matching the lazy-init approach already used by
the Netty and commons-fileupload integrations.
… paths

The content path in Netty and both the filenames and content paths in
Tomcat were setting the BlockingException outside the if (brf != null)
block, meaning the exception would be thrown even when no blocking
response had actually been committed. Align all three with the canonical
pattern: tryCommitBlockingResponse + effectivelyBlocked + exception
assignment all inside if (brf != null).

The Netty body-processed path intentionally still omits effectivelyBlocked()
because tryCommitBlockingResponse() closes the Netty span synchronously in
the test environment, making a subsequent effectivelyBlocked() call fail.
…meterCollector

- Replace per-call getMethod() with volatile (Class, Method) entry cache so
  reflection resolves once per concrete Part class rather than per file per request.
- Use try-with-resources for InputStream in readContent() instead of try/finally.
- Add unit test covering the Tomcat 7 getFilename() fallback path.
… file content

Also fix HttpPostRequestDecoderInstrumentation to fire on PREEPILOGUE+isLastChunk
so that multipart requests delivered as a FullHttpRequest (single shot) trigger the
requestBodyProcessed/requestFilesFilenames/requestFilesContent callbacks. The
PREEPILOGUE→EPILOGUE transition requires a second parseBody() call which never
comes when the full request arrives in one shot; PREEPILOGUE+isLastChunk is
equivalent to EPILOGUE in that scenario.
…adContentReader helper

Move the in-memory/disk-backed FileUpload content reading logic out of ParseBodyAdvice
into a testable static helper class. Also fixes the partial-read risk on disk-backed
uploads (single fis.read() replaced by a loop) and broadens the catch to Exception to
handle IllegalReferenceCountException from released ByteBufs.
…k is absent

When only requestFilesContent is registered, avoid calling getValue()
on form attributes (which may trigger disk reads for large fields).
…MAX_FILE_CONTENT_BYTES/COUNT

Replace hardcoded constants MAX_CONTENT_BYTES=4096 and MAX_FILES_TO_INSPECT=25
(duplicated across commons-fileupload, Netty, and Tomcat) with two Config-backed
variables: appsec.max.file-content.bytes and appsec.max.file-content.count.
…ix muzzle validation

Static fields in @RequiresRequestContext advice inner classes trigger muzzle to
treat the advice class itself as a user-classpath class; moving the constant to
NettyFileUploadContentReader (a helper) avoids the self-referential muzzle failure.
…rn gate

requestFilesFilenames() was consulted after data collection, so when it was
the only registered AppSec callback (no requestBodyProcessed, no
requestFilesContent) the early-return gate fired and filenames were never
published to the WAF. Fetch all three callbacks upfront and gate on all three.
Introduces MultipartContentDecoder (internal-api) to decode multipart file bytes
using the charset declared in each part's Content-Type header, with JVM-default
fallback and REPLACE on malformed input. Mirrors the approach in PR #11212 for
commons-fileupload so all three integrations share the same decoding logic.
…ContentDecoder

Add readInputStream(InputStream, int, String) to eliminate the identical bounded
read loop duplicated across FileItemContentReader, NettyFileUploadContentReader and
ParameterCollector. Each caller still owns its own MAX_CONTENT_BYTES constant.

Also consolidate the two volatile reflection caches in ParameterCollector.readContent
(getInputStream + getContentType) into a single Method[] entry to halve volatile reads
per invocation.
Deduplicates the identical RequestBlockingAction dispatch pattern
that appeared three times in the Netty multipart advice.
@jandro996 jandro996 added type: enhancement Enhancements and improvements comp: asm waf Application Security Management (WAF) labels Apr 29, 2026
jandro996 and others added 4 commits April 29, 2026 13:00
…asy (#11171)

Add server.request.body.filenames support for Jersey and RESTEasy

Accept MIME linear whitespace around filename= parameter in Content-Disposition

Tabs after ';' and optional SP/HT around '=' are valid per MIME and are
delivered by RESTEasy as-is; the previous parser only skipped literal spaces,
so those variants bypassed server.request.body.filenames detection.

Fix misleading BlockingException message and add missing test coverage

- Correct BlockingException message in jersey-appsec-2.0 and jersey-appsec-3.0:
  was "MultiPartReaderClientSide/readFrom", now "MultiPartReaderServerSide/readMultiPart"
- Add combined body-map + filenames test to jersey-appsec-2.0 and jersey-appsec-3.0
  MultiPartHelperTest to cover the case where both outputs are populated simultaneously
- Add null input test to resteasy MultipartHelperTest for filenameFromContentDisposition

Merge branch 'master' into alejandro.gonzalez/APPSEC-61873-5-jersey-resteasy

Apply spotless formatting

Co-authored-by: devflow.devflow-routing-intake <devflow.devflow-routing-intake@kubernetes.us1.ddbuild.io>
Adds server.request.body.files_content support to Jersey 2/3 and RESTEasy
multipart instrumentations, following the canonical three-callback ordering
(body always fires; filenames always fires; content fires only if body did
not block).

- MultiPartHelper (Jersey 2/3): add MAX_CONTENT_BYTES/MAX_FILES_TO_INSPECT
  constants, extend collectBodyPart to accept a filesContent list, add
  readContent and tryBlock helpers, remove unused filenameFromBodyPart
- MultiPartReaderServerSideInstrumentation (Jersey 2/3): obtain and dispatch
  requestFilesContent callback gated on t == null
- MultipartHelper (RESTEasy): add collectFilesContent, readContent,
  rawFilenameFromContentDisposition, tryBlock helpers and MAX constants;
  refactor filenameFromContentDisposition to delegate to raw variant
- MultipartFormDataReaderInstrumentation (RESTEasy): obtain and dispatch
  requestFilesContent callback; replace inline blocking with tryBlock helper
- MultiPartHelperTest (Jersey 2/3): update collectBodyPart call sites to
  four-arg signature; add content tests (empty/null/non-empty filename,
  exception in getFormDataContentDisposition, MAX_FILES_TO_INSPECT limit);
  add tryBlock tests (non-blocking, blocking with brf, verifies
  tryCommitBlockingResponse + effectivelyBlocked, null brf)
- MultipartHelperTest (RESTEasy): add rawFilenameFromContentDisposition
  tests (absent/empty/non-empty); add same four tryBlock tests
…STEasy helpers

- tryBlock: create BlockingException before calling effectivelyBlocked() so the
  exception object exists before the span is marked; aligns with the canonical
  ordering documented for Servlet-based blocking paths
- readContent (Jersey 2/3): wrap getEntityAs stream in try-with-resources for
  correctness, even though BodyPartEntity streams are in-memory
- readContent (RESTEasy): use try-with-resources so file-backed InputPart streams
  are closed after reading, avoiding potential file descriptor leaks
@jandro996 jandro996 force-pushed the alejandro.gonzalez/APPSEC-61875-files-content-jersey-resteasy branch from 1765cbe to 499a7bf Compare April 29, 2026 11:00
…Easy advices

The requestFilesContent callback apply() was incorrectly gated on t == null,
meaning it would not fire if a prior callback (body or filenames) had already
triggered a blocking action. The three callbacks must always dispatch data to
the WAF; only tryCommitBlockingResponse should be gated on t == null.
…ipart helper

Covers: non-empty filename includes content, empty filename (security fix -
content yes, filenames no), absent filename attribute skips part, and
MAX_FILES_TO_INSPECT limit. Uses MultivaluedMapImpl for getHeaders() stubs
so the reflection-based GET_HEADERS.invoke() call returns the expected type.
@pr-commenter
Copy link
Copy Markdown

pr-commenter Bot commented Apr 29, 2026

Benchmarks

Startup

Parameters

Baseline Candidate
baseline_or_candidate baseline candidate
git_branch master alejandro.gonzalez/APPSEC-61875-files-content-jersey-resteasy
git_commit_date 1777379592 1777465931
git_commit_sha 9d73760 58954d0
release_version 1.62.0-SNAPSHOT~9d737609c4 1.62.0-SNAPSHOT~58954d0769
See matching parameters
Baseline Candidate
application insecure-bank insecure-bank
ci_job_date 1777467698 1777467698
ci_job_id 1641935394 1641935394
ci_pipeline_id 110412871 110412871
cpu_model Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz
kernel_version Linux runner-zfyrx7zua-project-304-concurrent-1-xa9m4gtj 6.8.0-1031-aws #33~22.04.1-Ubuntu SMP Thu Jun 26 14:22:30 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux Linux runner-zfyrx7zua-project-304-concurrent-1-xa9m4gtj 6.8.0-1031-aws #33~22.04.1-Ubuntu SMP Thu Jun 26 14:22:30 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
module Agent Agent
parent None None

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 62 metrics, 9 unstable metrics.

Startup time reports for petclinic
gantt
    title petclinic - global startup overhead: candidate=1.62.0-SNAPSHOT~58954d0769, baseline=1.62.0-SNAPSHOT~9d737609c4

    dateFormat X
    axisFormat %s
section tracing
Agent [baseline] (1.061 s) : 0, 1061059
Total [baseline] (11.095 s) : 0, 11094590
Agent [candidate] (1.065 s) : 0, 1064569
Total [candidate] (11.12 s) : 0, 11120364
section appsec
Agent [baseline] (1.27 s) : 0, 1270111
Total [baseline] (11.129 s) : 0, 11128559
Agent [candidate] (1.268 s) : 0, 1267741
Total [candidate] (11.119 s) : 0, 11118873
section iast
Agent [baseline] (1.246 s) : 0, 1246431
Total [baseline] (11.257 s) : 0, 11257406
Agent [candidate] (1.247 s) : 0, 1246994
Total [candidate] (11.363 s) : 0, 11363378
section profiling
Agent [baseline] (1.196 s) : 0, 1196297
Total [baseline] (11.113 s) : 0, 11113470
Agent [candidate] (1.189 s) : 0, 1188828
Total [candidate] (11.011 s) : 0, 11011194
Loading
  • baseline results
Module Variant Duration Δ tracing
Agent tracing 1.061 s -
Agent appsec 1.27 s 209.052 ms (19.7%)
Agent iast 1.246 s 185.371 ms (17.5%)
Agent profiling 1.196 s 135.238 ms (12.7%)
Total tracing 11.095 s -
Total appsec 11.129 s 33.97 ms (0.3%)
Total iast 11.257 s 162.817 ms (1.5%)
Total profiling 11.113 s 18.881 ms (0.2%)
  • candidate results
Module Variant Duration Δ tracing
Agent tracing 1.065 s -
Agent appsec 1.268 s 203.172 ms (19.1%)
Agent iast 1.247 s 182.425 ms (17.1%)
Agent profiling 1.189 s 124.259 ms (11.7%)
Total tracing 11.12 s -
Total appsec 11.119 s -1.492 ms (-0.0%)
Total iast 11.363 s 243.013 ms (2.2%)
Total profiling 11.011 s -109.17 ms (-1.0%)
gantt
    title petclinic - break down per module: candidate=1.62.0-SNAPSHOT~58954d0769, baseline=1.62.0-SNAPSHOT~9d737609c4

    dateFormat X
    axisFormat %s
section tracing
crashtracking [baseline] (1.241 ms) : 0, 1241
crashtracking [candidate] (1.244 ms) : 0, 1244
BytebuddyAgent [baseline] (635.276 ms) : 0, 635276
BytebuddyAgent [candidate] (635.965 ms) : 0, 635965
AgentMeter [baseline] (29.481 ms) : 0, 29481
AgentMeter [candidate] (29.471 ms) : 0, 29471
GlobalTracer [baseline] (248.386 ms) : 0, 248386
GlobalTracer [candidate] (249.036 ms) : 0, 249036
AppSec [baseline] (32.571 ms) : 0, 32571
AppSec [candidate] (32.717 ms) : 0, 32717
Debugger [baseline] (60.195 ms) : 0, 60195
Debugger [candidate] (60.647 ms) : 0, 60647
Remote Config [baseline] (584.582 µs) : 0, 585
Remote Config [candidate] (598.084 µs) : 0, 598
Telemetry [baseline] (9.139 ms) : 0, 9139
Telemetry [candidate] (9.945 ms) : 0, 9945
Flare Poller [baseline] (8.195 ms) : 0, 8195
Flare Poller [candidate] (8.882 ms) : 0, 8882
section appsec
crashtracking [baseline] (1.222 ms) : 0, 1222
crashtracking [candidate] (1.22 ms) : 0, 1220
BytebuddyAgent [baseline] (678.336 ms) : 0, 678336
BytebuddyAgent [candidate] (676.223 ms) : 0, 676223
AgentMeter [baseline] (12.3 ms) : 0, 12300
AgentMeter [candidate] (12.229 ms) : 0, 12229
GlobalTracer [baseline] (249.904 ms) : 0, 249904
GlobalTracer [candidate] (249.646 ms) : 0, 249646
IAST [baseline] (24.751 ms) : 0, 24751
IAST [candidate] (24.642 ms) : 0, 24642
AppSec [baseline] (185.332 ms) : 0, 185332
AppSec [candidate] (185.558 ms) : 0, 185558
Debugger [baseline] (65.058 ms) : 0, 65058
Debugger [candidate] (64.7 ms) : 0, 64700
Remote Config [baseline] (572.959 µs) : 0, 573
Remote Config [candidate] (559.601 µs) : 0, 560
Telemetry [baseline] (7.906 ms) : 0, 7906
Telemetry [candidate] (7.777 ms) : 0, 7777
Flare Poller [baseline] (6.316 ms) : 0, 6316
Flare Poller [candidate] (8.563 ms) : 0, 8563
section iast
crashtracking [baseline] (1.225 ms) : 0, 1225
crashtracking [candidate] (1.24 ms) : 0, 1240
BytebuddyAgent [baseline] (824.343 ms) : 0, 824343
BytebuddyAgent [candidate] (825.115 ms) : 0, 825115
AgentMeter [baseline] (11.334 ms) : 0, 11334
AgentMeter [candidate] (11.325 ms) : 0, 11325
GlobalTracer [baseline] (238.553 ms) : 0, 238553
GlobalTracer [candidate] (238.36 ms) : 0, 238360
IAST [baseline] (25.751 ms) : 0, 25751
IAST [candidate] (27.435 ms) : 0, 27435
AppSec [baseline] (33.99 ms) : 0, 33990
AppSec [candidate] (32.227 ms) : 0, 32227
Debugger [baseline] (63.283 ms) : 0, 63283
Debugger [candidate] (63.178 ms) : 0, 63178
Remote Config [baseline] (515.958 µs) : 0, 516
Remote Config [candidate] (520.625 µs) : 0, 521
Telemetry [baseline] (7.917 ms) : 0, 7917
Telemetry [candidate] (8.008 ms) : 0, 8008
Flare Poller [baseline] (3.42 ms) : 0, 3420
Flare Poller [candidate] (3.489 ms) : 0, 3489
section profiling
crashtracking [baseline] (1.186 ms) : 0, 1186
crashtracking [candidate] (1.183 ms) : 0, 1183
BytebuddyAgent [baseline] (696.903 ms) : 0, 696903
BytebuddyAgent [candidate] (694.048 ms) : 0, 694048
AgentMeter [baseline] (8.994 ms) : 0, 8994
AgentMeter [candidate] (8.955 ms) : 0, 8955
GlobalTracer [baseline] (209.722 ms) : 0, 209722
GlobalTracer [candidate] (208.338 ms) : 0, 208338
AppSec [baseline] (33.339 ms) : 0, 33339
AppSec [candidate] (32.755 ms) : 0, 32755
Debugger [baseline] (66.535 ms) : 0, 66535
Debugger [candidate] (65.827 ms) : 0, 65827
Remote Config [baseline] (579.032 µs) : 0, 579
Remote Config [candidate] (575.504 µs) : 0, 576
Telemetry [baseline] (8.174 ms) : 0, 8174
Telemetry [candidate] (8.093 ms) : 0, 8093
Flare Poller [baseline] (3.59 ms) : 0, 3590
Flare Poller [candidate] (3.615 ms) : 0, 3615
ProfilingAgent [baseline] (95.463 ms) : 0, 95463
ProfilingAgent [candidate] (94.053 ms) : 0, 94053
Profiling [baseline] (96.023 ms) : 0, 96023
Profiling [candidate] (94.603 ms) : 0, 94603
Loading
Startup time reports for insecure-bank
gantt
    title insecure-bank - global startup overhead: candidate=1.62.0-SNAPSHOT~58954d0769, baseline=1.62.0-SNAPSHOT~9d737609c4

    dateFormat X
    axisFormat %s
section tracing
Agent [baseline] (1.065 s) : 0, 1064963
Total [baseline] (8.845 s) : 0, 8845326
Agent [candidate] (1.062 s) : 0, 1062075
Total [candidate] (8.845 s) : 0, 8845431
section iast
Agent [baseline] (1.245 s) : 0, 1244866
Total [baseline] (9.552 s) : 0, 9551511
Agent [candidate] (1.247 s) : 0, 1246687
Total [candidate] (9.505 s) : 0, 9505130
Loading
  • baseline results
Module Variant Duration Δ tracing
Agent tracing 1.065 s -
Agent iast 1.245 s 179.904 ms (16.9%)
Total tracing 8.845 s -
Total iast 9.552 s 706.184 ms (8.0%)
  • candidate results
Module Variant Duration Δ tracing
Agent tracing 1.062 s -
Agent iast 1.247 s 184.612 ms (17.4%)
Total tracing 8.845 s -
Total iast 9.505 s 659.698 ms (7.5%)
gantt
    title insecure-bank - break down per module: candidate=1.62.0-SNAPSHOT~58954d0769, baseline=1.62.0-SNAPSHOT~9d737609c4

    dateFormat X
    axisFormat %s
section tracing
crashtracking [baseline] (1.226 ms) : 0, 1226
crashtracking [candidate] (1.212 ms) : 0, 1212
BytebuddyAgent [baseline] (636.838 ms) : 0, 636838
BytebuddyAgent [candidate] (634.805 ms) : 0, 634805
AgentMeter [baseline] (29.466 ms) : 0, 29466
AgentMeter [candidate] (29.472 ms) : 0, 29472
GlobalTracer [baseline] (249.166 ms) : 0, 249166
GlobalTracer [candidate] (248.885 ms) : 0, 248885
AppSec [baseline] (32.845 ms) : 0, 32845
AppSec [candidate] (32.783 ms) : 0, 32783
Debugger [baseline] (59.809 ms) : 0, 59809
Debugger [candidate] (59.459 ms) : 0, 59459
Remote Config [baseline] (601.589 µs) : 0, 602
Remote Config [candidate] (592.903 µs) : 0, 593
Telemetry [baseline] (9.919 ms) : 0, 9919
Telemetry [candidate] (9.116 ms) : 0, 9116
Flare Poller [baseline] (9.123 ms) : 0, 9123
Flare Poller [candidate] (9.861 ms) : 0, 9861
section iast
crashtracking [baseline] (1.224 ms) : 0, 1224
crashtracking [candidate] (1.228 ms) : 0, 1228
BytebuddyAgent [baseline] (824.168 ms) : 0, 824168
BytebuddyAgent [candidate] (825.809 ms) : 0, 825809
AgentMeter [baseline] (11.3 ms) : 0, 11300
AgentMeter [candidate] (11.298 ms) : 0, 11298
GlobalTracer [baseline] (238.724 ms) : 0, 238724
GlobalTracer [candidate] (238.429 ms) : 0, 238429
AppSec [baseline] (31.687 ms) : 0, 31687
AppSec [candidate] (32.317 ms) : 0, 32317
Debugger [baseline] (63.393 ms) : 0, 63393
Debugger [candidate] (62.295 ms) : 0, 62295
Remote Config [baseline] (518.699 µs) : 0, 519
Remote Config [candidate] (526.822 µs) : 0, 527
Telemetry [baseline] (7.952 ms) : 0, 7952
Telemetry [candidate] (7.887 ms) : 0, 7887
Flare Poller [baseline] (3.363 ms) : 0, 3363
Flare Poller [candidate] (3.327 ms) : 0, 3327
IAST [baseline] (26.551 ms) : 0, 26551
IAST [candidate] (27.515 ms) : 0, 27515
Loading

Load

Parameters

Baseline Candidate
baseline_or_candidate baseline candidate
git_branch master alejandro.gonzalez/APPSEC-61875-files-content-jersey-resteasy
git_commit_date 1777379592 1777465931
git_commit_sha 9d73760 58954d0
release_version 1.62.0-SNAPSHOT~9d737609c4 1.62.0-SNAPSHOT~58954d0769
See matching parameters
Baseline Candidate
application insecure-bank insecure-bank
ci_job_date 1777468082 1777468082
ci_job_id 1641935395 1641935395
ci_pipeline_id 110412871 110412871
cpu_model Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz
kernel_version Linux runner-zfyrx7zua-project-304-concurrent-1-bwi2zxx9 6.8.0-1031-aws #33~22.04.1-Ubuntu SMP Thu Jun 26 14:22:30 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux Linux runner-zfyrx7zua-project-304-concurrent-1-bwi2zxx9 6.8.0-1031-aws #33~22.04.1-Ubuntu SMP Thu Jun 26 14:22:30 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux

Summary

Found 1 performance improvements and 0 performance regressions! Performance is the same for 18 metrics, 17 unstable metrics.

scenario Δ mean agg_http_req_duration_p50 Δ mean agg_http_req_duration_p95 Δ mean throughput candidate mean agg_http_req_duration_p50 candidate mean agg_http_req_duration_p95 candidate mean throughput baseline mean agg_http_req_duration_p50 baseline mean agg_http_req_duration_p95 baseline mean throughput
scenario:load:insecure-bank:iast_FULL:high_load better
[-316.108µs; -110.202µs] or [-5.950%; -2.074%]
unsure
[-917.398µs; -135.329µs] or [-7.247%; -1.069%]
unstable
[-61.232op/s; +110.544op/s] or [-7.917%; +14.293%]
5.100ms 12.133ms 798.094op/s 5.313ms 12.659ms 773.438op/s
Request duration reports for petclinic
gantt
    title petclinic - request duration [CI 0.99] : candidate=1.62.0-SNAPSHOT~58954d0769, baseline=1.62.0-SNAPSHOT~9d737609c4
    dateFormat X
    axisFormat %s
section baseline
no_agent (18.361 ms) : 18173, 18549
.   : milestone, 18361,
appsec (18.923 ms) : 18729, 19117
.   : milestone, 18923,
code_origins (17.849 ms) : 17672, 18027
.   : milestone, 17849,
iast (18.021 ms) : 17843, 18199
.   : milestone, 18021,
profiling (18.818 ms) : 18631, 19004
.   : milestone, 18818,
tracing (17.532 ms) : 17359, 17705
.   : milestone, 17532,
section candidate
no_agent (18.605 ms) : 18415, 18794
.   : milestone, 18605,
appsec (19.218 ms) : 19025, 19410
.   : milestone, 19218,
code_origins (17.776 ms) : 17601, 17950
.   : milestone, 17776,
iast (18.011 ms) : 17830, 18192
.   : milestone, 18011,
profiling (18.559 ms) : 18376, 18742
.   : milestone, 18559,
tracing (17.897 ms) : 17718, 18075
.   : milestone, 17897,
Loading
  • baseline results
Variant Request duration [CI 0.99] Δ no_agent
no_agent 18.361 ms [18.173 ms, 18.549 ms] -
appsec 18.923 ms [18.729 ms, 19.117 ms] 561.954 µs (3.1%)
code_origins 17.849 ms [17.672 ms, 18.027 ms] -512.141 µs (-2.8%)
iast 18.021 ms [17.843 ms, 18.199 ms] -340.296 µs (-1.9%)
profiling 18.818 ms [18.631 ms, 19.004 ms] 456.42 µs (2.5%)
tracing 17.532 ms [17.359 ms, 17.705 ms] -829.706 µs (-4.5%)
  • candidate results
Variant Request duration [CI 0.99] Δ no_agent
no_agent 18.605 ms [18.415 ms, 18.794 ms] -
appsec 19.218 ms [19.025 ms, 19.41 ms] 613.297 µs (3.3%)
code_origins 17.776 ms [17.601 ms, 17.95 ms] -828.863 µs (-4.5%)
iast 18.011 ms [17.83 ms, 18.192 ms] -593.758 µs (-3.2%)
profiling 18.559 ms [18.376 ms, 18.742 ms] -45.991 µs (-0.2%)
tracing 17.897 ms [17.718 ms, 18.075 ms] -707.734 µs (-3.8%)
Request duration reports for insecure-bank
gantt
    title insecure-bank - request duration [CI 0.99] : candidate=1.62.0-SNAPSHOT~58954d0769, baseline=1.62.0-SNAPSHOT~9d737609c4
    dateFormat X
    axisFormat %s
section baseline
no_agent (1.249 ms) : 1236, 1261
.   : milestone, 1249,
iast (3.294 ms) : 3248, 3340
.   : milestone, 3294,
iast_FULL (5.979 ms) : 5918, 6041
.   : milestone, 5979,
iast_GLOBAL (3.675 ms) : 3614, 3737
.   : milestone, 3675,
profiling (2.169 ms) : 2148, 2190
.   : milestone, 2169,
tracing (1.952 ms) : 1935, 1969
.   : milestone, 1952,
section candidate
no_agent (1.255 ms) : 1243, 1267
.   : milestone, 1255,
iast (3.353 ms) : 3298, 3409
.   : milestone, 3353,
iast_FULL (5.793 ms) : 5735, 5851
.   : milestone, 5793,
iast_GLOBAL (3.676 ms) : 3616, 3736
.   : milestone, 3676,
profiling (2.118 ms) : 2099, 2136
.   : milestone, 2118,
tracing (1.837 ms) : 1823, 1852
.   : milestone, 1837,
Loading
  • baseline results
Variant Request duration [CI 0.99] Δ no_agent
no_agent 1.249 ms [1.236 ms, 1.261 ms] -
iast 3.294 ms [3.248 ms, 3.34 ms] 2.045 ms (163.8%)
iast_FULL 5.979 ms [5.918 ms, 6.041 ms] 4.731 ms (378.9%)
iast_GLOBAL 3.675 ms [3.614 ms, 3.737 ms] 2.427 ms (194.4%)
profiling 2.169 ms [2.148 ms, 2.19 ms] 920.309 µs (73.7%)
tracing 1.952 ms [1.935 ms, 1.969 ms] 703.092 µs (56.3%)
  • candidate results
Variant Request duration [CI 0.99] Δ no_agent
no_agent 1.255 ms [1.243 ms, 1.267 ms] -
iast 3.353 ms [3.298 ms, 3.409 ms] 2.098 ms (167.1%)
iast_FULL 5.793 ms [5.735 ms, 5.851 ms] 4.537 ms (361.5%)
iast_GLOBAL 3.676 ms [3.616 ms, 3.736 ms] 2.421 ms (192.8%)
profiling 2.118 ms [2.099 ms, 2.136 ms] 862.426 µs (68.7%)
tracing 1.837 ms [1.823 ms, 1.852 ms] 581.962 µs (46.4%)

Dacapo

Parameters

Baseline Candidate
baseline_or_candidate baseline candidate
git_branch master alejandro.gonzalez/APPSEC-61875-files-content-jersey-resteasy
git_commit_date 1777379592 1777465931
git_commit_sha 9d73760 58954d0
release_version 1.62.0-SNAPSHOT~9d737609c4 1.62.0-SNAPSHOT~58954d0769
See matching parameters
Baseline Candidate
application biojava biojava
ci_job_date 1777467876 1777467876
ci_job_id 1641935396 1641935396
ci_pipeline_id 110412871 110412871
cpu_model Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz
kernel_version Linux runner-zfyrx7zua-project-304-concurrent-2-qkv2ds7b 6.8.0-1031-aws #33~22.04.1-Ubuntu SMP Thu Jun 26 14:22:30 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux Linux runner-zfyrx7zua-project-304-concurrent-2-qkv2ds7b 6.8.0-1031-aws #33~22.04.1-Ubuntu SMP Thu Jun 26 14:22:30 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 10 metrics, 2 unstable metrics.

Execution time for biojava
gantt
    title biojava - execution time [CI 0.99] : candidate=1.62.0-SNAPSHOT~58954d0769, baseline=1.62.0-SNAPSHOT~9d737609c4
    dateFormat X
    axisFormat %s
section baseline
no_agent (15.548 s) : 15548000, 15548000
.   : milestone, 15548000,
appsec (14.858 s) : 14858000, 14858000
.   : milestone, 14858000,
iast (18.569 s) : 18569000, 18569000
.   : milestone, 18569000,
iast_GLOBAL (18.005 s) : 18005000, 18005000
.   : milestone, 18005000,
profiling (15.087 s) : 15087000, 15087000
.   : milestone, 15087000,
tracing (14.809 s) : 14809000, 14809000
.   : milestone, 14809000,
section candidate
no_agent (14.873 s) : 14873000, 14873000
.   : milestone, 14873000,
appsec (14.888 s) : 14888000, 14888000
.   : milestone, 14888000,
iast (18.358 s) : 18358000, 18358000
.   : milestone, 18358000,
iast_GLOBAL (18.059 s) : 18059000, 18059000
.   : milestone, 18059000,
profiling (14.867 s) : 14867000, 14867000
.   : milestone, 14867000,
tracing (14.895 s) : 14895000, 14895000
.   : milestone, 14895000,
Loading
  • baseline results
Variant Execution Time [CI 0.99] Δ no_agent
no_agent 15.548 s [15.548 s, 15.548 s] -
appsec 14.858 s [14.858 s, 14.858 s] -690.0 ms (-4.4%)
iast 18.569 s [18.569 s, 18.569 s] 3.021 s (19.4%)
iast_GLOBAL 18.005 s [18.005 s, 18.005 s] 2.457 s (15.8%)
profiling 15.087 s [15.087 s, 15.087 s] -461.0 ms (-3.0%)
tracing 14.809 s [14.809 s, 14.809 s] -739.0 ms (-4.8%)
  • candidate results
Variant Execution Time [CI 0.99] Δ no_agent
no_agent 14.873 s [14.873 s, 14.873 s] -
appsec 14.888 s [14.888 s, 14.888 s] 15.0 ms (0.1%)
iast 18.358 s [18.358 s, 18.358 s] 3.485 s (23.4%)
iast_GLOBAL 18.059 s [18.059 s, 18.059 s] 3.186 s (21.4%)
profiling 14.867 s [14.867 s, 14.867 s] -6.0 ms (-0.0%)
tracing 14.895 s [14.895 s, 14.895 s] 22.0 ms (0.1%)
Execution time for tomcat
gantt
    title tomcat - execution time [CI 0.99] : candidate=1.62.0-SNAPSHOT~58954d0769, baseline=1.62.0-SNAPSHOT~9d737609c4
    dateFormat X
    axisFormat %s
section baseline
no_agent (1.489 ms) : 1477, 1500
.   : milestone, 1489,
appsec (2.559 ms) : 2503, 2614
.   : milestone, 2559,
iast (2.283 ms) : 2213, 2353
.   : milestone, 2283,
iast_GLOBAL (2.337 ms) : 2267, 2407
.   : milestone, 2337,
profiling (2.538 ms) : 2373, 2704
.   : milestone, 2538,
tracing (2.084 ms) : 2031, 2138
.   : milestone, 2084,
section candidate
no_agent (1.493 ms) : 1481, 1504
.   : milestone, 1493,
appsec (3.854 ms) : 3632, 4076
.   : milestone, 3854,
iast (2.299 ms) : 2228, 2369
.   : milestone, 2299,
iast_GLOBAL (2.331 ms) : 2260, 2401
.   : milestone, 2331,
profiling (2.117 ms) : 2062, 2173
.   : milestone, 2117,
tracing (2.093 ms) : 2039, 2147
.   : milestone, 2093,
Loading
  • baseline results
Variant Execution Time [CI 0.99] Δ no_agent
no_agent 1.489 ms [1.477 ms, 1.5 ms] -
appsec 2.559 ms [2.503 ms, 2.614 ms] 1.07 ms (71.8%)
iast 2.283 ms [2.213 ms, 2.353 ms] 793.706 µs (53.3%)
iast_GLOBAL 2.337 ms [2.267 ms, 2.407 ms] 848.167 µs (57.0%)
profiling 2.538 ms [2.373 ms, 2.704 ms] 1.049 ms (70.5%)
tracing 2.084 ms [2.031 ms, 2.138 ms] 595.569 µs (40.0%)
  • candidate results
Variant Execution Time [CI 0.99] Δ no_agent
no_agent 1.493 ms [1.481 ms, 1.504 ms] -
appsec 3.854 ms [3.632 ms, 4.076 ms] 2.361 ms (158.2%)
iast 2.299 ms [2.228 ms, 2.369 ms] 806.204 µs (54.0%)
iast_GLOBAL 2.331 ms [2.26 ms, 2.401 ms] 837.936 µs (56.1%)
profiling 2.117 ms [2.062 ms, 2.173 ms] 624.697 µs (41.9%)
tracing 2.093 ms [2.039 ms, 2.147 ms] 600.436 µs (40.2%)

…rom Jersey tests

java.io.* is auto-imported in Groovy; the explicit import triggers CodeNarc
UnnecessaryGroovyImport violation.
@jandro996
Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

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

Base automatically changed from alejandro.gonzalez/APPSEC-61875-files-content-tomcat-netty to master April 30, 2026 13:58
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) type: enhancement Enhancements and improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant