Skip to content

Add server.request.body.filenames support for Jetty#10988

Open
jandro996 wants to merge 43 commits intomasterfrom
alejandro.gonzalez/APPSEC-61873-3
Open

Add server.request.body.filenames support for Jetty#10988
jandro996 wants to merge 43 commits intomasterfrom
alejandro.gonzalez/APPSEC-61873-3

Conversation

@jandro996
Copy link
Copy Markdown
Member

@jandro996 jandro996 commented Mar 27, 2026

What Does This Do

Instruments Jetty's multipart request handling to fire both requestFilesFilenames and requestBodyProcessed AppSec gateway events, enabling WAF rules that act on uploaded filenames and multipart form-field values.

Jetty parses multipart bodies through two code paths depending on how the application accesses the request:

  • getParameterMap()extractContentParameters() → internal getParts(MultiMap)
  • Direct getParts() / getPart(String) call from user code

Both paths are instrumented where they exist. Guards on internal state fields (_contentParameters, _multiParts, _multiPartInputStream) prevent double-firing when the same method is called more than once per request.

Module coverage

Module Status Servlet API Coverage Notes
jetty-appsec-7.0 unchanged javax ≤ 8.1.2 getParts() does not exist in Jetty 7.x
jetty-appsec-8.1.3 rewritten javax (3.0) [8.1.3, 9.2.0.RC0) See below
jetty-appsec-9.2 unchanged javax [9.2, 9.3) Already fires requestBodyProcessed; no filename support needed at this range
jetty-appsec-9.3 modified javax [9.3, 9.4.10) Narrowed from [9.3, 12). Added GetFilenamesAdvice + GetFilenamesFromMultiPartAdvice. Double-fire guard uses _multiPartInputStream.
jetty-appsec-9.4 new javax [9.4.10, 11.0) Covers Jetty 9.4.10–10.x. OR-muzzle reference handles _multiParts: MultiParts (9.4.10+, 10.0.10+) and _multiParts: MultiPartFormInputStream (10.0.0–10.0.9). Bytecode discriminator: _dispatcherType: Ljavax/servlet/DispatcherType;.
jetty-appsec-11.0 new jakarta [11.0, 12.0) Jakarta Servlet. Muzzle discriminator: _dispatcherType: Ljakarta/servlet/DispatcherType; in Request.class bytecode — checking classpath presence of jakarta.servlet was unreliable when both javax and jakarta were present simultaneously.

jetty-appsec-8.1.3 details

Replaced brittle ASM bytecode injection (GetPartsMethodVisitor) with clean exit advice:

  • GetFilenamesAdvice on getParts() — fires requestBodyProcessed (form fields) + requestFilesFilenames
  • GetPartAdvice on getPart(String) — same, for single-part uploads that never call getParts(); in Jetty 8.x getPart(String) calls _multiPartInputStream.getPart() directly
  • _multiPartInputStream == null guard prevents re-firing on repeated getParts() calls
  • Classloader matcher uses ASM to inspect Request.class bytecode at agent startup, detecting the getParameters() call inside getParts() that is unique to Jetty 8.x

PartHelper (replacing ParameterCollector):

  • filenameFromPart(): quote-aware Content-Disposition parser; Part.getSubmittedFileName() is Servlet 3.1+ and unavailable here
  • extractFormFields(): reads form-field body values, skips file-upload parts
  • fireBodyProcessedEvent() / fireFilenamesEvent(): encapsulate the full IG callback + blocking-commit logic, returning BlockingException|null for use with @Advice.Thrown(readOnly=false)

Helpers and tests

  • PartHelper (8.1.3) and MultipartHelper (9.3/9.4/11.0) are unit-tested independently in PartHelperTest / MultipartHelperTest
  • Integration tests in jetty-server-7.6, jetty-server-9.3, jetty-server-9.4.21, jetty-server-10.0, jetty-server-11.0 cover both the getParts() and getParameterMap() code paths; a dedicated Jetty10EarlyDepForkedTest covers Jetty 10.0.0–10.0.9

Motivation

Part of APPSEC-61873server.request.body.filenames implementation across server frameworks.

Additional Notes

Bytecode discriminator rationale (9.4 vs 11.0): checking for jakarta.servlet.http.Part on the classpath was unreliable when a Jetty 9.4/10 app ships both javax and jakarta on the classpath (common with Spring Boot 3 migration tooling). The _dispatcherType field descriptor inside Request.class bytecode is unambiguous regardless of classpath contents.

GetFilenamesFromMultiPartAdvice vs GetFilenamesAdvice: in all 9.3/9.4/11.0 modules, extractContentParameters() sets _contentParameters before calling getParts(MultiMap), so the _contentParameters != null guard in GetFilenamesAdvice correctly prevents double-firing when the getParameterMap() path is used.

Part.getSubmittedFileName() availability: Servlet 3.1+ (Jetty 9.1+). For Jetty 8.x (Servlet 3.0), PartHelper.filenameFromPart() parses the Content-Disposition header manually with a quote-aware parser to handle filenames like filename="shell;evil.php" correctly.

Depends on #10973 (merged)

Contributor Checklist

Jira ticket: APPSEC-61873

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.

@jandro996 jandro996 added comp: asm waf Application Security Management (WAF) type: enhancement Enhancements and improvements labels Mar 27, 2026
@pr-commenter
Copy link
Copy Markdown

pr-commenter Bot commented Mar 27, 2026

Benchmarks

Startup

Parameters

Baseline Candidate
baseline_or_candidate baseline candidate
git_branch master alejandro.gonzalez/APPSEC-61873-3
git_commit_date 1777032987 1777032361
git_commit_sha d1c44d515b 24e4849
release_version 1.62.0-SNAPSHOT~0d1c44d515b 1.62.0-SNAPSHOT~24e48491cd
See matching parameters
Baseline Candidate
application insecure-bank insecure-bank
ci_job_date 1777034172 1777034172
ci_job_id 1627907921 1627907921
ci_pipeline_id 109525449 109525449
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-0-lahju3uv 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-0-lahju3uv 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 63 metrics, 8 unstable metrics.

Startup time reports for petclinic
gantt
    title petclinic - global startup overhead: candidate=1.62.0-SNAPSHOT~24e48491cd, baseline=1.62.0-SNAPSHOT~0d1c44d515b

    dateFormat X
    axisFormat %s
section tracing
Agent [baseline] (1.056 s) : 0, 1055506
Total [baseline] (11.116 s) : 0, 11115994
Agent [candidate] (1.072 s) : 0, 1071993
Total [candidate] (11.17 s) : 0, 11170313
section appsec
Agent [baseline] (1.267 s) : 0, 1266927
Total [baseline] (11.071 s) : 0, 11070808
Agent [candidate] (1.266 s) : 0, 1266035
Total [candidate] (4.42 s) : 0, 4419518
section iast
Agent [baseline] (1.24 s) : 0, 1240466
Total [baseline] (11.32 s) : 0, 11319829
Agent [candidate] (1.242 s) : 0, 1241627
Total [candidate] (11.367 s) : 0, 11367170
section profiling
Agent [baseline] (1.185 s) : 0, 1184880
Total [baseline] (11.027 s) : 0, 11026589
Agent [candidate] (1.186 s) : 0, 1185729
Total [candidate] (11.101 s) : 0, 11100718
Loading
  • baseline results
Module Variant Duration Δ tracing
Agent tracing 1.056 s -
Agent appsec 1.267 s 211.421 ms (20.0%)
Agent iast 1.24 s 184.959 ms (17.5%)
Agent profiling 1.185 s 129.374 ms (12.3%)
Total tracing 11.116 s -
Total appsec 11.071 s -45.185 ms (-0.4%)
Total iast 11.32 s 203.835 ms (1.8%)
Total profiling 11.027 s -89.405 ms (-0.8%)
  • candidate results
Module Variant Duration Δ tracing
Agent tracing 1.072 s -
Agent appsec 1.266 s 194.042 ms (18.1%)
Agent iast 1.242 s 169.634 ms (15.8%)
Agent profiling 1.186 s 113.736 ms (10.6%)
Total tracing 11.17 s -
Total appsec 4.42 s -6.751 s (-60.4%)
Total iast 11.367 s 196.857 ms (1.8%)
Total profiling 11.101 s -69.594 ms (-0.6%)
gantt
    title petclinic - break down per module: candidate=1.62.0-SNAPSHOT~24e48491cd, baseline=1.62.0-SNAPSHOT~0d1c44d515b

    dateFormat X
    axisFormat %s
section tracing
crashtracking [baseline] (1.215 ms) : 0, 1215
crashtracking [candidate] (1.234 ms) : 0, 1234
BytebuddyAgent [baseline] (634.844 ms) : 0, 634844
BytebuddyAgent [candidate] (644.432 ms) : 0, 644432
AgentMeter [baseline] (29.254 ms) : 0, 29254
AgentMeter [candidate] (29.594 ms) : 0, 29594
GlobalTracer [baseline] (248.682 ms) : 0, 248682
GlobalTracer [candidate] (250.77 ms) : 0, 250770
AppSec [baseline] (32.244 ms) : 0, 32244
AppSec [candidate] (32.631 ms) : 0, 32631
Debugger [baseline] (60.239 ms) : 0, 60239
Debugger [candidate] (61.406 ms) : 0, 61406
Remote Config [baseline] (594.898 µs) : 0, 595
Remote Config [candidate] (605.481 µs) : 0, 605
Telemetry [baseline] (8.029 ms) : 0, 8029
Telemetry [candidate] (8.211 ms) : 0, 8211
Flare Poller [baseline] (4.285 ms) : 0, 4285
Flare Poller [candidate] (6.632 ms) : 0, 6632
section appsec
crashtracking [baseline] (1.224 ms) : 0, 1224
crashtracking [candidate] (1.23 ms) : 0, 1230
BytebuddyAgent [baseline] (679.205 ms) : 0, 679205
BytebuddyAgent [candidate] (678.221 ms) : 0, 678221
AgentMeter [baseline] (12.31 ms) : 0, 12310
AgentMeter [candidate] (12.229 ms) : 0, 12229
GlobalTracer [baseline] (249.226 ms) : 0, 249226
GlobalTracer [candidate] (249.444 ms) : 0, 249444
IAST [baseline] (24.193 ms) : 0, 24193
IAST [candidate] (24.351 ms) : 0, 24351
AppSec [baseline] (188.03 ms) : 0, 188030
AppSec [candidate] (186.166 ms) : 0, 186166
Debugger [baseline] (64.373 ms) : 0, 64373
Debugger [candidate] (66.099 ms) : 0, 66099
Remote Config [baseline] (590.224 µs) : 0, 590
Remote Config [candidate] (557.79 µs) : 0, 558
Telemetry [baseline] (7.801 ms) : 0, 7801
Telemetry [candidate] (7.837 ms) : 0, 7837
Flare Poller [baseline] (3.423 ms) : 0, 3423
Flare Poller [candidate] (3.443 ms) : 0, 3443
section iast
crashtracking [baseline] (1.224 ms) : 0, 1224
crashtracking [candidate] (1.228 ms) : 0, 1228
BytebuddyAgent [baseline] (816.329 ms) : 0, 816329
BytebuddyAgent [candidate] (815.985 ms) : 0, 815985
AgentMeter [baseline] (11.421 ms) : 0, 11421
AgentMeter [candidate] (11.475 ms) : 0, 11475
GlobalTracer [baseline] (239.919 ms) : 0, 239919
GlobalTracer [candidate] (240.259 ms) : 0, 240259
IAST [baseline] (28.386 ms) : 0, 28386
IAST [candidate] (29.515 ms) : 0, 29515
AppSec [baseline] (28.71 ms) : 0, 28710
AppSec [candidate] (27.777 ms) : 0, 27777
Debugger [baseline] (66.47 ms) : 0, 66470
Debugger [candidate] (67.147 ms) : 0, 67147
Remote Config [baseline] (539.682 µs) : 0, 540
Remote Config [candidate] (546.423 µs) : 0, 546
Telemetry [baseline] (7.836 ms) : 0, 7836
Telemetry [candidate] (7.834 ms) : 0, 7834
Flare Poller [baseline] (3.528 ms) : 0, 3528
Flare Poller [candidate] (3.492 ms) : 0, 3492
section profiling
crashtracking [baseline] (1.181 ms) : 0, 1181
crashtracking [candidate] (1.189 ms) : 0, 1189
BytebuddyAgent [baseline] (691.48 ms) : 0, 691480
BytebuddyAgent [candidate] (693.421 ms) : 0, 693421
AgentMeter [baseline] (8.972 ms) : 0, 8972
AgentMeter [candidate] (8.978 ms) : 0, 8978
GlobalTracer [baseline] (207.707 ms) : 0, 207707
GlobalTracer [candidate] (207.521 ms) : 0, 207521
AppSec [baseline] (32.558 ms) : 0, 32558
AppSec [candidate] (32.668 ms) : 0, 32668
Debugger [baseline] (65.56 ms) : 0, 65560
Debugger [candidate] (65.124 ms) : 0, 65124
Remote Config [baseline] (566.631 µs) : 0, 567
Remote Config [candidate] (575.478 µs) : 0, 575
Telemetry [baseline] (7.807 ms) : 0, 7807
Telemetry [candidate] (7.762 ms) : 0, 7762
Flare Poller [baseline] (3.464 ms) : 0, 3464
Flare Poller [candidate] (3.531 ms) : 0, 3531
ProfilingAgent [baseline] (94.019 ms) : 0, 94019
ProfilingAgent [candidate] (93.386 ms) : 0, 93386
Profiling [baseline] (94.586 ms) : 0, 94586
Profiling [candidate] (93.943 ms) : 0, 93943
Loading
Startup time reports for insecure-bank
gantt
    title insecure-bank - global startup overhead: candidate=1.62.0-SNAPSHOT~24e48491cd, baseline=1.62.0-SNAPSHOT~0d1c44d515b

    dateFormat X
    axisFormat %s
section tracing
Agent [baseline] (1.056 s) : 0, 1056224
Total [baseline] (8.852 s) : 0, 8852151
Agent [candidate] (1.062 s) : 0, 1062237
Total [candidate] (8.883 s) : 0, 8882842
section iast
Agent [baseline] (1.232 s) : 0, 1231982
Total [baseline] (9.579 s) : 0, 9578795
Agent [candidate] (1.234 s) : 0, 1234108
Total [candidate] (9.536 s) : 0, 9535941
Loading
  • baseline results
Module Variant Duration Δ tracing
Agent tracing 1.056 s -
Agent iast 1.232 s 175.757 ms (16.6%)
Total tracing 8.852 s -
Total iast 9.579 s 726.644 ms (8.2%)
  • candidate results
Module Variant Duration Δ tracing
Agent tracing 1.062 s -
Agent iast 1.234 s 171.872 ms (16.2%)
Total tracing 8.883 s -
Total iast 9.536 s 653.099 ms (7.4%)
gantt
    title insecure-bank - break down per module: candidate=1.62.0-SNAPSHOT~24e48491cd, baseline=1.62.0-SNAPSHOT~0d1c44d515b

    dateFormat X
    axisFormat %s
section tracing
crashtracking [baseline] (1.227 ms) : 0, 1227
crashtracking [candidate] (1.229 ms) : 0, 1229
BytebuddyAgent [baseline] (636.35 ms) : 0, 636350
BytebuddyAgent [candidate] (640.171 ms) : 0, 640171
AgentMeter [baseline] (29.359 ms) : 0, 29359
AgentMeter [candidate] (29.617 ms) : 0, 29617
GlobalTracer [baseline] (248.832 ms) : 0, 248832
GlobalTracer [candidate] (249.153 ms) : 0, 249153
AppSec [baseline] (32.199 ms) : 0, 32199
AppSec [candidate] (32.296 ms) : 0, 32296
Debugger [baseline] (59.243 ms) : 0, 59243
Debugger [candidate] (59.668 ms) : 0, 59668
Remote Config [baseline] (590.726 µs) : 0, 591
Remote Config [candidate] (595.392 µs) : 0, 595
Telemetry [baseline] (8.742 ms) : 0, 8742
Telemetry [candidate] (8.809 ms) : 0, 8809
Flare Poller [baseline] (3.508 ms) : 0, 3508
Flare Poller [candidate] (4.374 ms) : 0, 4374
section iast
crashtracking [baseline] (1.216 ms) : 0, 1216
crashtracking [candidate] (1.235 ms) : 0, 1235
BytebuddyAgent [baseline] (810.616 ms) : 0, 810616
BytebuddyAgent [candidate] (813.175 ms) : 0, 813175
AgentMeter [baseline] (11.395 ms) : 0, 11395
AgentMeter [candidate] (11.366 ms) : 0, 11366
GlobalTracer [baseline] (239.1 ms) : 0, 239100
GlobalTracer [candidate] (239.429 ms) : 0, 239429
AppSec [baseline] (28.413 ms) : 0, 28413
AppSec [candidate] (26.169 ms) : 0, 26169
Debugger [baseline] (62.88 ms) : 0, 62880
Debugger [candidate] (62.853 ms) : 0, 62853
Remote Config [baseline] (520.83 µs) : 0, 521
Remote Config [candidate] (523.942 µs) : 0, 524
Telemetry [baseline] (7.785 ms) : 0, 7785
Telemetry [candidate] (7.601 ms) : 0, 7601
Flare Poller [baseline] (3.401 ms) : 0, 3401
Flare Poller [candidate] (3.365 ms) : 0, 3365
IAST [baseline] (30.597 ms) : 0, 30597
IAST [candidate] (32.393 ms) : 0, 32393
Loading

Load

Parameters

Baseline Candidate
baseline_or_candidate baseline candidate
git_branch master alejandro.gonzalez/APPSEC-61873-3
git_commit_date 1777032991 1777032361
git_commit_sha d1c44d515b 24e4849
release_version 1.62.0-SNAPSHOT~0d1c44d515b 1.62.0-SNAPSHOT~24e48491cd
See matching parameters
Baseline Candidate
application insecure-bank insecure-bank
ci_job_date 1777034763 1777034763
ci_job_id 1627907922 1627907922
ci_pipeline_id 109525449 109525449
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-0-s914puwn 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-0-s914puwn 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 2 performance improvements and 1 performance regressions! Performance is the same for 17 metrics, 16 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:petclinic:iast:high_load better
[-1.871ms; -1.111ms] or [-9.977%; -5.925%]
better
[-2.364ms; -1.042ms] or [-7.865%; -3.468%]
unstable
[-9.638op/s; +44.388op/s] or [-3.915%; +18.032%]
17.262ms 28.358ms 263.531op/s 18.753ms 30.061ms 246.156op/s
scenario:load:petclinic:no_agent:high_load worse
[+0.965ms; +2.355ms] or [+5.658%; +13.806%]
unstable
[+0.934ms; +4.041ms] or [+3.288%; +14.225%]
unstable
[-50.338op/s; +6.525op/s] or [-18.935%; +2.454%]
18.720ms 30.897ms 243.938op/s 17.060ms 28.409ms 265.844op/s
Request duration reports for insecure-bank
gantt
    title insecure-bank - request duration [CI 0.99] : candidate=1.62.0-SNAPSHOT~24e48491cd, baseline=1.62.0-SNAPSHOT~0d1c44d515b
    dateFormat X
    axisFormat %s
section baseline
no_agent (1.25 ms) : 1237, 1262
.   : milestone, 1250,
iast (3.396 ms) : 3346, 3447
.   : milestone, 3396,
iast_FULL (6.002 ms) : 5940, 6064
.   : milestone, 6002,
iast_GLOBAL (3.66 ms) : 3604, 3716
.   : milestone, 3660,
profiling (2.193 ms) : 2173, 2212
.   : milestone, 2193,
tracing (1.915 ms) : 1898, 1931
.   : milestone, 1915,
section candidate
no_agent (1.237 ms) : 1226, 1248
.   : milestone, 1237,
iast (3.409 ms) : 3361, 3456
.   : milestone, 3409,
iast_FULL (6.084 ms) : 6020, 6147
.   : milestone, 6084,
iast_GLOBAL (3.744 ms) : 3684, 3805
.   : milestone, 3744,
profiling (2.321 ms) : 2298, 2344
.   : milestone, 2321,
tracing (1.901 ms) : 1885, 1917
.   : milestone, 1901,
Loading
  • baseline results
Variant Request duration [CI 0.99] Δ no_agent
no_agent 1.25 ms [1.237 ms, 1.262 ms] -
iast 3.396 ms [3.346 ms, 3.447 ms] 2.147 ms (171.8%)
iast_FULL 6.002 ms [5.94 ms, 6.064 ms] 4.752 ms (380.3%)
iast_GLOBAL 3.66 ms [3.604 ms, 3.716 ms] 2.411 ms (192.9%)
profiling 2.193 ms [2.173 ms, 2.212 ms] 943.064 µs (75.5%)
tracing 1.915 ms [1.898 ms, 1.931 ms] 665.381 µs (53.2%)
  • candidate results
Variant Request duration [CI 0.99] Δ no_agent
no_agent 1.237 ms [1.226 ms, 1.248 ms] -
iast 3.409 ms [3.361 ms, 3.456 ms] 2.172 ms (175.6%)
iast_FULL 6.084 ms [6.02 ms, 6.147 ms] 4.847 ms (391.8%)
iast_GLOBAL 3.744 ms [3.684 ms, 3.805 ms] 2.507 ms (202.7%)
profiling 2.321 ms [2.298 ms, 2.344 ms] 1.084 ms (87.6%)
tracing 1.901 ms [1.885 ms, 1.917 ms] 664.056 µs (53.7%)
Request duration reports for petclinic
gantt
    title petclinic - request duration [CI 0.99] : candidate=1.62.0-SNAPSHOT~24e48491cd, baseline=1.62.0-SNAPSHOT~0d1c44d515b
    dateFormat X
    axisFormat %s
section baseline
no_agent (17.55 ms) : 17377, 17724
.   : milestone, 17550,
appsec (18.517 ms) : 18335, 18698
.   : milestone, 18517,
code_origins (18.749 ms) : 18564, 18935
.   : milestone, 18749,
iast (18.96 ms) : 18769, 19150
.   : milestone, 18960,
profiling (18.255 ms) : 18072, 18438
.   : milestone, 18255,
tracing (17.881 ms) : 17703, 18059
.   : milestone, 17881,
section candidate
no_agent (19.135 ms) : 18941, 19328
.   : milestone, 19135,
appsec (18.806 ms) : 18616, 18996
.   : milestone, 18806,
code_origins (18.064 ms) : 17883, 18245
.   : milestone, 18064,
iast (17.708 ms) : 17535, 17881
.   : milestone, 17708,
profiling (18.324 ms) : 18139, 18508
.   : milestone, 18324,
tracing (17.821 ms) : 17644, 17998
.   : milestone, 17821,
Loading
  • baseline results
Variant Request duration [CI 0.99] Δ no_agent
no_agent 17.55 ms [17.377 ms, 17.724 ms] -
appsec 18.517 ms [18.335 ms, 18.698 ms] 966.251 µs (5.5%)
code_origins 18.749 ms [18.564 ms, 18.935 ms] 1.199 ms (6.8%)
iast 18.96 ms [18.769 ms, 19.15 ms] 1.41 ms (8.0%)
profiling 18.255 ms [18.072 ms, 18.438 ms] 704.797 µs (4.0%)
tracing 17.881 ms [17.703 ms, 18.059 ms] 330.105 µs (1.9%)
  • candidate results
Variant Request duration [CI 0.99] Δ no_agent
no_agent 19.135 ms [18.941 ms, 19.328 ms] -
appsec 18.806 ms [18.616 ms, 18.996 ms] -328.364 µs (-1.7%)
code_origins 18.064 ms [17.883 ms, 18.245 ms] -1.071 ms (-5.6%)
iast 17.708 ms [17.535 ms, 17.881 ms] -1.427 ms (-7.5%)
profiling 18.324 ms [18.139 ms, 18.508 ms] -810.785 µs (-4.2%)
tracing 17.821 ms [17.644 ms, 17.998 ms] -1.314 ms (-6.9%)

Dacapo

Parameters

Baseline Candidate
baseline_or_candidate baseline candidate
git_branch master alejandro.gonzalez/APPSEC-61873-3
git_commit_date 1777032987 1777032361
git_commit_sha d1c44d515b 24e4849
release_version 1.62.0-SNAPSHOT~0d1c44d515b 1.62.0-SNAPSHOT~24e48491cd
See matching parameters
Baseline Candidate
application biojava biojava
ci_job_date 1777034486 1777034486
ci_job_id 1627907923 1627907923
ci_pipeline_id 109525449 109525449
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-0-383i0awk 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-0-383i0awk 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 11 metrics, 1 unstable metrics.

Execution time for biojava
gantt
    title biojava - execution time [CI 0.99] : candidate=1.62.0-SNAPSHOT~24e48491cd, baseline=1.62.0-SNAPSHOT~0d1c44d515b
    dateFormat X
    axisFormat %s
section baseline
no_agent (14.797 s) : 14797000, 14797000
.   : milestone, 14797000,
appsec (15.151 s) : 15151000, 15151000
.   : milestone, 15151000,
iast (18.664 s) : 18664000, 18664000
.   : milestone, 18664000,
iast_GLOBAL (17.644 s) : 17644000, 17644000
.   : milestone, 17644000,
profiling (14.898 s) : 14898000, 14898000
.   : milestone, 14898000,
tracing (14.875 s) : 14875000, 14875000
.   : milestone, 14875000,
section candidate
no_agent (15.1 s) : 15100000, 15100000
.   : milestone, 15100000,
appsec (14.982 s) : 14982000, 14982000
.   : milestone, 14982000,
iast (18.171 s) : 18171000, 18171000
.   : milestone, 18171000,
iast_GLOBAL (18.099 s) : 18099000, 18099000
.   : milestone, 18099000,
profiling (15.459 s) : 15459000, 15459000
.   : milestone, 15459000,
tracing (14.992 s) : 14992000, 14992000
.   : milestone, 14992000,
Loading
  • baseline results
Variant Execution Time [CI 0.99] Δ no_agent
no_agent 14.797 s [14.797 s, 14.797 s] -
appsec 15.151 s [15.151 s, 15.151 s] 354.0 ms (2.4%)
iast 18.664 s [18.664 s, 18.664 s] 3.867 s (26.1%)
iast_GLOBAL 17.644 s [17.644 s, 17.644 s] 2.847 s (19.2%)
profiling 14.898 s [14.898 s, 14.898 s] 101.0 ms (0.7%)
tracing 14.875 s [14.875 s, 14.875 s] 78.0 ms (0.5%)
  • candidate results
Variant Execution Time [CI 0.99] Δ no_agent
no_agent 15.1 s [15.1 s, 15.1 s] -
appsec 14.982 s [14.982 s, 14.982 s] -118.0 ms (-0.8%)
iast 18.171 s [18.171 s, 18.171 s] 3.071 s (20.3%)
iast_GLOBAL 18.099 s [18.099 s, 18.099 s] 2.999 s (19.9%)
profiling 15.459 s [15.459 s, 15.459 s] 359.0 ms (2.4%)
tracing 14.992 s [14.992 s, 14.992 s] -108.0 ms (-0.7%)
Execution time for tomcat
gantt
    title tomcat - execution time [CI 0.99] : candidate=1.62.0-SNAPSHOT~24e48491cd, baseline=1.62.0-SNAPSHOT~0d1c44d515b
    dateFormat X
    axisFormat %s
section baseline
no_agent (1.489 ms) : 1477, 1501
.   : milestone, 1489,
appsec (3.845 ms) : 3622, 4069
.   : milestone, 3845,
iast (2.271 ms) : 2201, 2340
.   : milestone, 2271,
iast_GLOBAL (2.324 ms) : 2254, 2394
.   : milestone, 2324,
profiling (2.112 ms) : 2056, 2167
.   : milestone, 2112,
tracing (2.08 ms) : 2026, 2133
.   : milestone, 2080,
section candidate
no_agent (1.485 ms) : 1473, 1496
.   : milestone, 1485,
appsec (3.825 ms) : 3602, 4049
.   : milestone, 3825,
iast (2.285 ms) : 2216, 2355
.   : milestone, 2285,
iast_GLOBAL (2.314 ms) : 2244, 2384
.   : milestone, 2314,
profiling (2.097 ms) : 2042, 2152
.   : milestone, 2097,
tracing (2.081 ms) : 2027, 2134
.   : milestone, 2081,
Loading
  • baseline results
Variant Execution Time [CI 0.99] Δ no_agent
no_agent 1.489 ms [1.477 ms, 1.501 ms] -
appsec 3.845 ms [3.622 ms, 4.069 ms] 2.356 ms (158.2%)
iast 2.271 ms [2.201 ms, 2.34 ms] 781.695 µs (52.5%)
iast_GLOBAL 2.324 ms [2.254 ms, 2.394 ms] 835.065 µs (56.1%)
profiling 2.112 ms [2.056 ms, 2.167 ms] 622.678 µs (41.8%)
tracing 2.08 ms [2.026 ms, 2.133 ms] 590.627 µs (39.7%)
  • candidate results
Variant Execution Time [CI 0.99] Δ no_agent
no_agent 1.485 ms [1.473 ms, 1.496 ms] -
appsec 3.825 ms [3.602 ms, 4.049 ms] 2.341 ms (157.6%)
iast 2.285 ms [2.216 ms, 2.355 ms] 800.496 µs (53.9%)
iast_GLOBAL 2.314 ms [2.244 ms, 2.384 ms] 829.033 µs (55.8%)
profiling 2.097 ms [2.042 ms, 2.152 ms] 612.109 µs (41.2%)
tracing 2.081 ms [2.027 ms, 2.134 ms] 595.645 µs (40.1%)

@jandro996 jandro996 force-pushed the alejandro.gonzalez/APPSEC-61873-3 branch 2 times, most recently from f2998c3 to 629f074 Compare April 6, 2026 10:50
@jandro996 jandro996 marked this pull request as ready for review April 6, 2026 13:08
@jandro996 jandro996 requested a review from a team as a code owner April 6, 2026 13:08
}
}
// Fallback: parse filename from Content-Disposition header (Servlet 3.0)
if (name == null) {
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.

Shouldn't this be outside of the main parts loop?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed. Restructured into two separate loops chosen once before iteration: if getSubmittedFileName != null (Servlet 3.1+) iterate using that method; otherwise iterate parsing the Content-Disposition header (Servlet 3.0 fallback). No per-part branching inside the loop.

transformer.applyAdvice(
named("extractContentParameters").and(takesArguments(0)).or(named("getParts")),
getClass().getName() + "$ExtractContentParametersAdvice");
transformer.applyAdvice(named("getParts"), getClass().getName() + "$GetFilenamesAdvice");
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.

Same as before

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed. GetFilenamesAdvice now has a call-depth guard (CallDepthThreadLocalMap with Collection.class) to avoid double-firing when getParts() internally calls getParts(MultiMap)

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c732823549

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

@jandro996 jandro996 force-pushed the alejandro.gonzalez/APPSEC-61873-3 branch 4 times, most recently from 3ab9ff7 to 77ec572 Compare April 7, 2026 07:33
@jandro996 jandro996 enabled auto-merge April 7, 2026 08:52
@jandro996 jandro996 force-pushed the alejandro.gonzalez/APPSEC-61873-3 branch from 2e72584 to d37e03e Compare April 7, 2026 09:23
@jandro996 jandro996 disabled auto-merge April 7, 2026 09:42
@jandro996 jandro996 marked this pull request as draft April 7, 2026 09:48
@jandro996 jandro996 force-pushed the alejandro.gonzalez/APPSEC-61873-3 branch from d37e03e to d8a92f8 Compare April 7, 2026 09:52
jandro996 added a commit to DataDog/system-tests that referenced this pull request Apr 9, 2026
Jetty multipart file upload instrumentation fixed in
DataDog/dd-trace-java#10988 (Jetty 8.1.3, 9.3–11).
@github-actions
Copy link
Copy Markdown
Contributor

Hi! 👋 Looks like you updated a Git Submodule.
If this was not intentional please make sure to:

3 similar comments
@github-actions
Copy link
Copy Markdown
Contributor

Hi! 👋 Looks like you updated a Git Submodule.
If this was not intentional please make sure to:

@github-actions
Copy link
Copy Markdown
Contributor

Hi! 👋 Looks like you updated a Git Submodule.
If this was not intentional please make sure to:

@github-actions
Copy link
Copy Markdown
Contributor

Hi! 👋 Looks like you updated a Git Submodule.
If this was not intentional please make sure to:

@jandro996 jandro996 marked this pull request as ready for review April 20, 2026 08:13
@jandro996 jandro996 requested review from a team as code owners April 20, 2026 08:13
jetty-appsec-8.1.3 (covers Jetty <9) and jetty-appsec-9.2 (covers Jetty
[9.2,9.3)) were reverted to master state: they report requestBodyProcessed
but not requestFilesFilenames. Jetty 9.0.x and 9.2.x therefore have no
active appsec module that fires the filenames event, so testBodyFilenames()
must stay false for those modules.
…jetty-appsec-9.3/9.4/11.0

In Armeria + Jetty 9.4.48 (and possibly other embedded/wrapped setups),
getParts() is the application entry point for multipart parsing — it internally
calls extractContentParameters(), which sets _contentParameters. Without the
matcher on getParts(), ExtractContentParametersAdvice.after() never fires in
that code path, so the requestBodyProcessed event (and request.body.converted
tag) is never reported.

The call-depth guard (Request.class key) already prevents double-firing when
both methods are instrumented: getParts() increments depth to 1 before
extractContentParameters() is entered, so the nested advice is a no-op.
…ty-appsec-9.4

Replace the JAVAX_PART_REFERENCE muzzle check (class presence on classpath)
with a field-level bytecode check on Request._dispatcherType descriptor:
- Ljavax/servlet/DispatcherType; in Jetty 9.4/10 (javax namespace)
- Ljakarta/servlet/DispatcherType; in Jetty 11+ (jakarta namespace)
This reliably excludes Jetty 11+ even when both javax and jakarta
servlet jars are on the test classpath simultaneously.

Also remove assertInverse from 9_series muzzle block to avoid conflict
with 10_series (both cover overlapping Jetty 10.0.x versions).

Fixes armeria-jetty-1.24:jetty11Test ClassCastException where
jetty94.MultipartHelper tried to cast jakarta.servlet.http.Part
to javax.servlet.http.Part.
…TP 500

jetty-appsec-8.1.3 muzzle range [8.1.3, 9.2.0.RC0) includes Jetty 9.0.x.
When applied, it calls ParameterCollector.put(String, String) which does
not exist in Jetty 9.0.x → HTTP 500 on multipart requests.

Override multipart() with assumeTrue(false) in jetty-server-9.0 and
jetty-server-9.0.4 test classes until the muzzle range is corrected.
…8.1.3 causes HTTP 500

Replace assumeTrue(false) with Spock's @ignore annotation — more reliable
for overriding void feature methods without Spock block labels.

jetty-appsec-8.1.3 muzzle range [8.1.3, 9.2.0.RC0) includes Jetty 9.0.x.
When applied, it calls ParameterCollector.put(String, String) which does
not exist in Jetty 9.0.x → HTTP 500 on multipart requests.
Spock AST-transforms feature methods, so @OverRide on a feature method
override triggers a compile error. Use a boolean hook instead:
- AppSecInactiveHttpServerTest.supportsMultipart() returns true by default
  and is guarded with assumeTrue() at the setup: block level
- Jetty9InactiveAppSecTest overrides to false in both jetty-server-9.0 and
  jetty-server-9.0.4, where jetty-appsec-8.1.3 range [8.1.3, 9.2.0.RC0)
  causes ParameterCollector.put(String, String) to fail → HTTP 500.

Verified locally: tests=8, skipped=3 (multipart correctly skipped), failures=0.
…t version to 10.0.10

- jetty-server-9.0 and jetty-server-9.0.4: set testBodyMultipart() = false.
  jetty-appsec-8.1.3 covers [8.1.3, 9.2.0.RC0) which includes Jetty 9.0.x;
  its extractContentParameters() calls ParameterCollector.put(String, String)
  which does not exist in Jetty 9.0.x, causing HTTP 500 on multipart requests.

- jetty-server-10.0: bump test dependency from 10.0.0 to 10.0.10.
  jetty-appsec-9.4 requires _multiParts: Lorg/eclipse/jetty/server/MultiParts;
  but that type was only introduced in 10.0.10 (previously MultiPartFormInputStream),
  so the muzzle check fails for Jetty 10.0.0-10.0.9, leaving tests uninstrumented.

- Revert accidental modification of agent-jmxfetch/integrations-core submodule
  back to its master pointer.
…ith exit-advice

Replace the brittle GetPartsMethodVisitor ASM bytecode injection (intercepting
MultiMap.add() calls inside getParts()) with a clean ByteBuddy exit-advice approach:

- Remove ParameterCollector, GetPartsAdvice, GetPartsVisitorWrapper, RequestClassVisitor,
  and GetPartsMethodVisitor; drop HasTypeAdvice from the instrumentation module.
- Add PartHelper with extractFormFields() (reads InputStream per part) and
  extractFilenames() (parses Content-Disposition manually, since
  Part.getSubmittedFileName() is Servlet 3.1+ and not available in Jetty 8.x).
- Add GetFilenamesAdvice (@RequiresRequestContext / @ActiveRequestContext) on
  getParts():Collection that fires requestBodyProcessed() with form fields and
  requestFilesFilenames() with upload filenames. Uses CallDepthThreadLocalMap to
  guard against reentrant calls.
- Jetty8LatestDepForkedTest: set testBodyFilenamesCalledOnce() and
  testBodyFilenamesCalledOnceCombined() to false because Jetty 8.x has no
  _multiParts / _contentParameters field guards to suppress duplicate firings.
…utStream

- jetty-appsec-9.4: extend muzzle to also cover Jetty 10.0.0–10.0.9, which were
  previously a gap. In those versions _multiParts is typed MultiPartFormInputStream
  (not MultiParts); the primary Reference spec matches 9.4.10+ and 10.0.10+, and an
  OrReference alternative matches 10.0.0–10.0.9. The GetFilenamesAdvice already uses
  typing=DYNAMIC so no advice changes are needed.

- jetty-appsec-8.1.3 PartHelper: wrap part.getInputStream() in try-with-resources to
  avoid leaking file descriptors on file-backed multipart form fields.
Splitting the header on ';' naively truncated filenames that contain
semicolons inside a quoted value, e.g. filename="shell;evil.php" would
produce "shell" instead of the full name. Replace the split() loop with
a quote-aware state-machine parser that skips semicolons inside quoted
strings and handles backslash-escaped characters. Add test cases for
semicolons in filenames, escaped quotes, and filename appearing before
other parameters.
…c-11.0

Replace the JAKARTA_PART_REFERENCE classpath check with a _dispatcherType
field descriptor check on Request.class bytecode, mirroring the approach
already used by jetty-appsec-9.4. The classpath check passes on any
Jetty 9.4/10 app that has jakarta.servlet-api as a dependency, causing
double-instrumentation of extractContentParameters. The bytecode check is
authoritative: in Jetty 11+ Request.class carries _dispatcherType as
Ljakarta/servlet/DispatcherType;, while 9.4/10 carry the javax descriptor.
…uploads

In Jetty 8.x, getPart(String name) calls _multiPartInputStream.getPart(String)
directly without delegating to getParts(). Applications that retrieve only one
file via getPart() without ever calling getParts() would have their filename
event missed. Add GetPartAdvice to cover this path.

The charset fix (AI comment 2) was investigated and is not applicable: HTML5
form submissions always use UTF-8 and browsers never include charset= on
individual part Content-Type headers, so the existing hardcoded UTF-8 is correct.
…ilename tests in async suite

1. Add _multiPartInputStream == null guard to GetFilenamesAdvice.before() so that
   repeated getParts() calls on the same request (which Jetty caches) do not
   re-fire requestFilesFilenames/requestBodyProcessed WAF callbacks. The field is
   null before the first multipart parse and non-null on all subsequent cached
   calls, matching the pattern used in the 9.4/11.0 advice (_multiParts guard).

2. JettyAsyncHandlerTest already disabled testBodyFilenames() but neglected to
   disable testBodyFilenamesCalledOnce() and testBodyFilenamesCalledOnceCombined(),
   which are now enabled in the Jetty11Test parent. Override both to false in the
   async handler suite to prevent spurious test failures.
…elper

filenameFromPart() was returning null for both 'no filename parameter' and
'filename=""', causing extractFormFields() to buffer the full body of file
inputs submitted with no file chosen (filename=""). An empty <input type=file>
is still a file part, not a form field. Return "" instead of null so that
callers using != null correctly skip those parts without reading their content.

Update tests to assert "" for empty-filename cases and add regression tests
for extractFormFields/extractFilenames with empty-filename parts.

Note: the second AI comment about getPart(String) double-firing was not
implemented. The bytecode shows the internal call is to
MultiPartInputStream.getParts() (not Request.getParts()), so GetFilenamesAdvice
(which instruments Request.getParts()) is never triggered during a getPart()
call. There is no double-firing.
The jetty-appsec-9.4 early_10_series muzzle pass covers [10.0.0, 10.0.10)
where _multiParts is MultiPartFormInputStream (before the type changed to
MultiParts in 10.0.10). The existing test suite used 10.0.10, leaving the
early versions untested.

Add earlyDep10ForkedTest (Jetty 10.0.9) to exercise the OR-muzzle reference
and verify that multipart filename events fire correctly on the old field type.
All three filename tests pass: filenames, filenames-called-once, filenames-combined.
…M API constant

Move duplicated IG-callback + blocking-commit blocks out of advice into
helper methods (MultipartHelper.fireFilenamesEvent / PartHelper.fireBodyProcessedEvent
+ fireFilenamesEvent) that return BlockingException|null, exploiting
@Advice.Thrown(readOnly=false) assignment behaviour.

Also replace hardcoded Opcodes.ASM9 with OpenedClassReader.ASM_API in
RequestGetPartsInstrumentation and fix extractFormFields to use
computeIfAbsent instead of get+put.
…() delegates to getParts()

In Jetty 9.0/9.1 (covered by jetty-appsec-8.1.3's [8.1.3,9.2.0.RC0) range),
Request.getPart(String) delegates to getParts() internally. Without this fix,
GetFilenamesAdvice fires for the full collection (via the internal getParts() call)
and then GetPartAdvice fires again for the returned singleton, because the two
advice classes use independent call-depth keys and cannot see each other.

Fix: peek at the Part.class call depth in GetFilenamesAdvice.before(). If > 1,
GetPartAdvice is active on the stack and will handle the event; skip to avoid
double-firing. In Jetty 8.x (where getPart() does not delegate), the peek is
always 1, so GetFilenamesAdvice continues to fire normally.
…== 1

CallDepthThreadLocalMap.incrementCallDepth() uses post-increment (depth++) so it returns
the depth BEFORE the increment. In the normal case (no GetPartAdvice active), Part.class
depth is 0 before the peek, making partPeek == 0. The previous guard checked partPeek == 1
which is true only when GetPartAdvice IS already on the stack — exactly backwards.
Result: GetFilenamesAdvice never fired for direct getParts() calls, breaking the filenames
event on Jetty 8.x.

Fix: use partPeek == 0 (proceed when GetPartAdvice is not active) so the condition is:
- partPeek == 0: normal direct getParts() → proceed (fire filenames event)
- partPeek == 1: getParts() called by getPart() in Jetty 9.0/9.1 → skip (GetPartAdvice handles it)
…st the singleton

When getPart("field") is the app's first multipart access, Jetty 8 parses the entire
multipart stream and caches all parts in _multiPartInputStream, but only returns the
one requested part. The previous advice forwarded just that singleton to AppSec, so any
co-uploaded file parts were invisible to requestFilesFilenames — a WAF bypass if the
app never called getParts() explicitly.

Fix: read all cached parts via MultiPartInputStream.getParts() (reflected, cached handle)
and fall back to the singleton only when reflection fails. Also remove the part==null
early return: even if the requested field was not found, other file parts may have parsed.

Add PartHelper.getAllParts(Object, Part) + FakeMpi unit tests.
The Part.class depth check only prevents re-entry within a single getPart() invocation;
after the call returns the depth is 0 again, so a second getPart("file") call on the
same request would re-fire requestBodyProcessed and requestFilesFilenames with the same
cached parts. Add the same _multiPartInputStream == null guard that GetFilenamesAdvice
already uses: once the field is set the multipart body was parsed and events were already
dispatched — skip.
@jandro996 jandro996 force-pushed the alejandro.gonzalez/APPSEC-61873-3 branch from 71d0ff9 to 711a52c Compare April 24, 2026 10:10
@jandro996
Copy link
Copy Markdown
Member Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 711a52c7df

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

…ields

Hard-coded UTF-8 in readPartContent() caused mojibake for fields with
Content-Type: text/plain; charset=ISO-8859-1 (or any non-UTF-8 charset).
Now parses the charset from the part's Content-Type header and falls
back to UTF-8 only when absent or unrecognised.
@jandro996
Copy link
Copy Markdown
Member Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 311e00ec81

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

…p10ForkedTest

The lockfile was out of sync: testCompileClasspath was locked to 10.0.0
instead of 10.0.10, and earlyDep10ForkedTest configurations were missing
entirely. Regenerated with --write-locks.

Also added a resolutionStrategy to force Jetty 10.0.9 for
earlyDep10ForkedTest: without it, Gradle picks 10.0.10 (inherited via
testImplementation), defeating the purpose of the suite which exercises
the MultiPartFormInputStream path present in [10.0.0, 10.0.10).
@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".

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.

2 participants