Skip to content

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

Draft
jandro996 wants to merge 21 commits intomasterfrom
alejandro.gonzalez/APPSEC-61873-3
Draft

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

Conversation

@jandro996
Copy link
Copy Markdown
Member

@jandro996 jandro996 commented Mar 27, 2026

What Does This Do

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

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

Both paths are instrumented to fire requestFilesFilenames. Guards on internal state fields (_contentParameters, _multiParts, _multiPartInputStream) prevent double-firing.

Module Why modified / added
jetty-appsec-7.0 Added GetFilenamesAdvice for getParts(). No extractContentParameters in 7.x so only one path exists.
jetty-appsec-8.1.3 Added both advice classes. Servlet 2.x has no getSubmittedFileName() so filenames are parsed from the Content-Disposition header. Logic extracted to MultipartHelper with unit tests.
jetty-appsec-9.2 Added both advice classes. Uses Part.getSubmittedFileName() (Servlet 3.1). Logic extracted to MultipartHelper with unit tests.
jetty-appsec-9.3 Narrowed from [9.3, 12) to [9.3, 9.4). Removed reflection (getDeclaredField / Method.invoke) by restricting scope to only 9.3.x, where _multiPartInputStream is the correct field. MultipartHelper added with unit tests.
jetty-appsec-9.4 (new) Covers [9.4, 11.0) — javax.servlet, uses _multiParts field (introduced in 9.4). Previously handled by 9.3 via reflection. MultipartHelper with unit tests.
jetty-appsec-11.0 (new) Covers [11.0, 12.0) — jakarta.servlet (first Jetty version to drop javax). Previously handled by 9.3 via reflection. MultipartHelper with unit tests.
  • Server test modules (jetty-server-9.3/9.4.21/10.0/11.0/12.0) updated to reference the correct appsec module per Jetty version range.

Motivation

Additional Notes

Depends on #10973 (merged).
Part of Jira ticket: APPSEC-61873server.request.body.filenames implementation across server frameworks.

Contributor Checklist

@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 1775810809 1775813520
git_commit_sha 067d0d2 b9f5a74
release_version 1.62.0-SNAPSHOT~067d0d2c4b 1.61.0-SNAPSHOT~b9f5a74c5a
See matching parameters
Baseline Candidate
application insecure-bank insecure-bank
ci_job_date 1775815319 1775815319
ci_job_id 1584605732 1584605732
ci_pipeline_id 107049550 107049550
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-exxgs98z 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-exxgs98z 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 57 metrics, 14 unstable metrics.

Startup time reports for insecure-bank
gantt
    title insecure-bank - global startup overhead: candidate=1.61.0-SNAPSHOT~b9f5a74c5a, baseline=1.62.0-SNAPSHOT~067d0d2c4b

    dateFormat X
    axisFormat %s
section tracing
Agent [baseline] (1.056 s) : 0, 1056249
Total [baseline] (8.827 s) : 0, 8826556
Agent [candidate] (1.054 s) : 0, 1054469
Total [candidate] (8.845 s) : 0, 8844511
section iast
Agent [baseline] (1.228 s) : 0, 1227866
Total [baseline] (9.578 s) : 0, 9577849
Agent [candidate] (1.229 s) : 0, 1228766
Total [candidate] (9.571 s) : 0, 9571078
Loading
  • baseline results
Module Variant Duration Δ tracing
Agent tracing 1.056 s -
Agent iast 1.228 s 171.617 ms (16.2%)
Total tracing 8.827 s -
Total iast 9.578 s 751.293 ms (8.5%)
  • candidate results
Module Variant Duration Δ tracing
Agent tracing 1.054 s -
Agent iast 1.229 s 174.296 ms (16.5%)
Total tracing 8.845 s -
Total iast 9.571 s 726.568 ms (8.2%)
gantt
    title insecure-bank - break down per module: candidate=1.61.0-SNAPSHOT~b9f5a74c5a, baseline=1.62.0-SNAPSHOT~067d0d2c4b

    dateFormat X
    axisFormat %s
section tracing
crashtracking [baseline] (1.237 ms) : 0, 1237
crashtracking [candidate] (1.233 ms) : 0, 1233
BytebuddyAgent [baseline] (632.192 ms) : 0, 632192
BytebuddyAgent [candidate] (634.08 ms) : 0, 634080
AgentMeter [baseline] (29.386 ms) : 0, 29386
AgentMeter [candidate] (29.351 ms) : 0, 29351
GlobalTracer [baseline] (248.438 ms) : 0, 248438
GlobalTracer [candidate] (248.43 ms) : 0, 248430
AppSec [baseline] (32.031 ms) : 0, 32031
AppSec [candidate] (31.954 ms) : 0, 31954
Debugger [baseline] (59.055 ms) : 0, 59055
Debugger [candidate] (58.92 ms) : 0, 58920
Remote Config [baseline] (592.423 µs) : 0, 592
Remote Config [candidate] (583.77 µs) : 0, 584
Telemetry [baseline] (8.09 ms) : 0, 8090
Telemetry [candidate] (8.041 ms) : 0, 8041
Flare Poller [baseline] (9.131 ms) : 0, 9131
Flare Poller [candidate] (5.805 ms) : 0, 5805
section iast
crashtracking [baseline] (1.228 ms) : 0, 1228
crashtracking [candidate] (1.222 ms) : 0, 1222
BytebuddyAgent [baseline] (804.439 ms) : 0, 804439
BytebuddyAgent [candidate] (805.14 ms) : 0, 805140
AgentMeter [baseline] (11.442 ms) : 0, 11442
AgentMeter [candidate] (11.479 ms) : 0, 11479
GlobalTracer [baseline] (239.759 ms) : 0, 239759
GlobalTracer [candidate] (238.948 ms) : 0, 238948
AppSec [baseline] (30.354 ms) : 0, 30354
AppSec [candidate] (31.134 ms) : 0, 31134
Debugger [baseline] (61.456 ms) : 0, 61456
Debugger [candidate] (64.683 ms) : 0, 64683
Remote Config [baseline] (530.623 µs) : 0, 531
Remote Config [candidate] (557.205 µs) : 0, 557
Telemetry [baseline] (11.999 ms) : 0, 11999
Telemetry [candidate] (10.111 ms) : 0, 10111
Flare Poller [baseline] (3.81 ms) : 0, 3810
Flare Poller [candidate] (3.502 ms) : 0, 3502
IAST [baseline] (26.577 ms) : 0, 26577
IAST [candidate] (25.781 ms) : 0, 25781
Loading
Startup time reports for petclinic
gantt
    title petclinic - global startup overhead: candidate=1.61.0-SNAPSHOT~b9f5a74c5a, baseline=1.62.0-SNAPSHOT~067d0d2c4b

    dateFormat X
    axisFormat %s
section tracing
Agent [baseline] (1.061 s) : 0, 1061137
Total [baseline] (11.104 s) : 0, 11103947
Agent [candidate] (1.062 s) : 0, 1061536
Total [candidate] (11.041 s) : 0, 11041488
section appsec
Agent [baseline] (1.248 s) : 0, 1247769
Total [baseline] (11.132 s) : 0, 11132443
Agent [candidate] (1.249 s) : 0, 1249499
Total [candidate] (11.123 s) : 0, 11122887
section iast
Agent [baseline] (1.224 s) : 0, 1223611
Total [baseline] (11.258 s) : 0, 11257761
Agent [candidate] (1.23 s) : 0, 1230251
Total [candidate] (11.284 s) : 0, 11283532
section profiling
Agent [baseline] (1.187 s) : 0, 1186511
Total [baseline] (11.144 s) : 0, 11143516
Agent [candidate] (1.183 s) : 0, 1182710
Total [candidate] (11.024 s) : 0, 11024256
Loading
  • baseline results
Module Variant Duration Δ tracing
Agent tracing 1.061 s -
Agent appsec 1.248 s 186.632 ms (17.6%)
Agent iast 1.224 s 162.474 ms (15.3%)
Agent profiling 1.187 s 125.375 ms (11.8%)
Total tracing 11.104 s -
Total appsec 11.132 s 28.497 ms (0.3%)
Total iast 11.258 s 153.815 ms (1.4%)
Total profiling 11.144 s 39.569 ms (0.4%)
  • candidate results
Module Variant Duration Δ tracing
Agent tracing 1.062 s -
Agent appsec 1.249 s 187.963 ms (17.7%)
Agent iast 1.23 s 168.715 ms (15.9%)
Agent profiling 1.183 s 121.173 ms (11.4%)
Total tracing 11.041 s -
Total appsec 11.123 s 81.399 ms (0.7%)
Total iast 11.284 s 242.044 ms (2.2%)
Total profiling 11.024 s -17.232 ms (-0.2%)
gantt
    title petclinic - break down per module: candidate=1.61.0-SNAPSHOT~b9f5a74c5a, baseline=1.62.0-SNAPSHOT~067d0d2c4b

    dateFormat X
    axisFormat %s
section tracing
crashtracking [baseline] (1.232 ms) : 0, 1232
crashtracking [candidate] (1.222 ms) : 0, 1222
BytebuddyAgent [baseline] (633.247 ms) : 0, 633247
BytebuddyAgent [candidate] (633.779 ms) : 0, 633779
AgentMeter [baseline] (29.422 ms) : 0, 29422
AgentMeter [candidate] (29.321 ms) : 0, 29321
GlobalTracer [baseline] (249.131 ms) : 0, 249131
GlobalTracer [candidate] (249.62 ms) : 0, 249620
AppSec [baseline] (32.089 ms) : 0, 32089
AppSec [candidate] (32.3 ms) : 0, 32300
Debugger [baseline] (60.249 ms) : 0, 60249
Debugger [candidate] (60.43 ms) : 0, 60430
Remote Config [baseline] (595.124 µs) : 0, 595
Remote Config [candidate] (599.51 µs) : 0, 600
Telemetry [baseline] (8.176 ms) : 0, 8176
Telemetry [candidate] (9.006 ms) : 0, 9006
Flare Poller [baseline] (10.753 ms) : 0, 10753
Flare Poller [candidate] (9.123 ms) : 0, 9123
section appsec
crashtracking [baseline] (1.22 ms) : 0, 1220
crashtracking [candidate] (1.215 ms) : 0, 1215
BytebuddyAgent [baseline] (661.841 ms) : 0, 661841
BytebuddyAgent [candidate] (663.652 ms) : 0, 663652
AgentMeter [baseline] (12.076 ms) : 0, 12076
AgentMeter [candidate] (12.073 ms) : 0, 12073
GlobalTracer [baseline] (249.099 ms) : 0, 249099
GlobalTracer [candidate] (249.289 ms) : 0, 249289
AppSec [baseline] (184.061 ms) : 0, 184061
AppSec [candidate] (184.044 ms) : 0, 184044
Debugger [baseline] (65.76 ms) : 0, 65760
Debugger [candidate] (65.674 ms) : 0, 65674
Remote Config [baseline] (608.541 µs) : 0, 609
Remote Config [candidate] (603.549 µs) : 0, 604
Telemetry [baseline] (8.69 ms) : 0, 8690
Telemetry [candidate] (8.491 ms) : 0, 8491
Flare Poller [baseline] (3.556 ms) : 0, 3556
Flare Poller [candidate] (3.556 ms) : 0, 3556
IAST [baseline] (24.514 ms) : 0, 24514
IAST [candidate] (24.529 ms) : 0, 24529
section iast
crashtracking [baseline] (1.211 ms) : 0, 1211
crashtracking [candidate] (1.223 ms) : 0, 1223
BytebuddyAgent [baseline] (801.072 ms) : 0, 801072
BytebuddyAgent [candidate] (807.255 ms) : 0, 807255
AgentMeter [baseline] (11.358 ms) : 0, 11358
AgentMeter [candidate] (11.613 ms) : 0, 11613
GlobalTracer [baseline] (239.103 ms) : 0, 239103
GlobalTracer [candidate] (239.121 ms) : 0, 239121
AppSec [baseline] (29.395 ms) : 0, 29395
AppSec [candidate] (32.353 ms) : 0, 32353
Debugger [baseline] (61.645 ms) : 0, 61645
Debugger [candidate] (62.693 ms) : 0, 62693
Remote Config [baseline] (1.726 ms) : 0, 1726
Remote Config [candidate] (551.719 µs) : 0, 552
Telemetry [baseline] (12.768 ms) : 0, 12768
Telemetry [candidate] (9.926 ms) : 0, 9926
Flare Poller [baseline] (3.581 ms) : 0, 3581
Flare Poller [candidate] (3.461 ms) : 0, 3461
IAST [baseline] (25.71 ms) : 0, 25710
IAST [candidate] (25.769 ms) : 0, 25769
section profiling
crashtracking [baseline] (1.178 ms) : 0, 1178
crashtracking [candidate] (1.195 ms) : 0, 1195
BytebuddyAgent [baseline] (692.519 ms) : 0, 692519
BytebuddyAgent [candidate] (690.867 ms) : 0, 690867
AgentMeter [baseline] (9.15 ms) : 0, 9150
AgentMeter [candidate] (9.067 ms) : 0, 9067
GlobalTracer [baseline] (207.324 ms) : 0, 207324
GlobalTracer [candidate] (206.831 ms) : 0, 206831
AppSec [baseline] (32.596 ms) : 0, 32596
AppSec [candidate] (32.462 ms) : 0, 32462
Debugger [baseline] (65.024 ms) : 0, 65024
Debugger [candidate] (65.434 ms) : 0, 65434
Remote Config [baseline] (578.309 µs) : 0, 578
Remote Config [candidate] (572.838 µs) : 0, 573
Telemetry [baseline] (8.709 ms) : 0, 8709
Telemetry [candidate] (7.835 ms) : 0, 7835
Flare Poller [baseline] (3.639 ms) : 0, 3639
Flare Poller [candidate] (3.546 ms) : 0, 3546
ProfilingAgent [baseline] (94.432 ms) : 0, 94432
ProfilingAgent [candidate] (93.772 ms) : 0, 93772
Profiling [baseline] (95.018 ms) : 0, 95018
Profiling [candidate] (94.354 ms) : 0, 94354
Loading

Load

Parameters

Baseline Candidate
baseline_or_candidate baseline candidate
git_branch master alejandro.gonzalez/APPSEC-61873-3
git_commit_date 1775810809 1775813520
git_commit_sha 067d0d2 b9f5a74
release_version 1.62.0-SNAPSHOT~067d0d2c4b 1.61.0-SNAPSHOT~b9f5a74c5a
See matching parameters
Baseline Candidate
application insecure-bank insecure-bank
ci_job_date 1775815799 1775815799
ci_job_id 1584605737 1584605737
ci_pipeline_id 107049550 107049550
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-u7zrmrfc 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-u7zrmrfc 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 0 performance regressions! Performance is the same for 18 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:tracing:high_load better
[-1.468ms; -0.733ms] or [-7.957%; -3.972%]
better
[-2.203ms; -0.633ms] or [-7.384%; -2.122%]
unstable
[-13.841op/s; +42.903op/s] or [-5.569%; +17.263%]
17.348ms 28.413ms 263.062op/s 18.448ms 29.831ms 248.531op/s
Request duration reports for petclinic
gantt
    title petclinic - request duration [CI 0.99] : candidate=1.61.0-SNAPSHOT~b9f5a74c5a, baseline=1.62.0-SNAPSHOT~067d0d2c4b
    dateFormat X
    axisFormat %s
section baseline
no_agent (18.378 ms) : 18189, 18567
.   : milestone, 18378,
appsec (19.363 ms) : 19168, 19558
.   : milestone, 19363,
code_origins (17.803 ms) : 17628, 17979
.   : milestone, 17803,
iast (17.85 ms) : 17675, 18025
.   : milestone, 17850,
profiling (18.24 ms) : 18060, 18421
.   : milestone, 18240,
tracing (18.782 ms) : 18595, 18968
.   : milestone, 18782,
section candidate
no_agent (19.319 ms) : 19125, 19514
.   : milestone, 19319,
appsec (18.717 ms) : 18525, 18909
.   : milestone, 18717,
code_origins (18.031 ms) : 17854, 18207
.   : milestone, 18031,
iast (17.793 ms) : 17618, 17967
.   : milestone, 17793,
profiling (18.312 ms) : 18131, 18493
.   : milestone, 18312,
tracing (17.736 ms) : 17560, 17912
.   : milestone, 17736,
Loading
  • baseline results
Variant Request duration [CI 0.99] Δ no_agent
no_agent 18.378 ms [18.189 ms, 18.567 ms] -
appsec 19.363 ms [19.168 ms, 19.558 ms] 984.451 µs (5.4%)
code_origins 17.803 ms [17.628 ms, 17.979 ms] -575.101 µs (-3.1%)
iast 17.85 ms [17.675 ms, 18.025 ms] -528.454 µs (-2.9%)
profiling 18.24 ms [18.06 ms, 18.421 ms] -138.009 µs (-0.8%)
tracing 18.782 ms [18.595 ms, 18.968 ms] 403.129 µs (2.2%)
  • candidate results
Variant Request duration [CI 0.99] Δ no_agent
no_agent 19.319 ms [19.125 ms, 19.514 ms] -
appsec 18.717 ms [18.525 ms, 18.909 ms] -602.718 µs (-3.1%)
code_origins 18.031 ms [17.854 ms, 18.207 ms] -1.289 ms (-6.7%)
iast 17.793 ms [17.618 ms, 17.967 ms] -1.527 ms (-7.9%)
profiling 18.312 ms [18.131 ms, 18.493 ms] -1.007 ms (-5.2%)
tracing 17.736 ms [17.56 ms, 17.912 ms] -1.583 ms (-8.2%)
Request duration reports for insecure-bank
gantt
    title insecure-bank - request duration [CI 0.99] : candidate=1.61.0-SNAPSHOT~b9f5a74c5a, baseline=1.62.0-SNAPSHOT~067d0d2c4b
    dateFormat X
    axisFormat %s
section baseline
no_agent (1.244 ms) : 1232, 1256
.   : milestone, 1244,
iast (3.427 ms) : 3386, 3468
.   : milestone, 3427,
iast_FULL (5.957 ms) : 5897, 6017
.   : milestone, 5957,
iast_GLOBAL (3.744 ms) : 3676, 3812
.   : milestone, 3744,
profiling (2.214 ms) : 2194, 2234
.   : milestone, 2214,
tracing (1.911 ms) : 1895, 1927
.   : milestone, 1911,
section candidate
no_agent (1.253 ms) : 1241, 1265
.   : milestone, 1253,
iast (3.382 ms) : 3339, 3425
.   : milestone, 3382,
iast_FULL (6.088 ms) : 6025, 6151
.   : milestone, 6088,
iast_GLOBAL (3.58 ms) : 3527, 3633
.   : milestone, 3580,
profiling (2.309 ms) : 2287, 2331
.   : milestone, 2309,
tracing (1.923 ms) : 1907, 1939
.   : milestone, 1923,
Loading
  • baseline results
Variant Request duration [CI 0.99] Δ no_agent
no_agent 1.244 ms [1.232 ms, 1.256 ms] -
iast 3.427 ms [3.386 ms, 3.468 ms] 2.183 ms (175.5%)
iast_FULL 5.957 ms [5.897 ms, 6.017 ms] 4.713 ms (379.0%)
iast_GLOBAL 3.744 ms [3.676 ms, 3.812 ms] 2.5 ms (201.0%)
profiling 2.214 ms [2.194 ms, 2.234 ms] 970.447 µs (78.0%)
tracing 1.911 ms [1.895 ms, 1.927 ms] 667.461 µs (53.7%)
  • candidate results
Variant Request duration [CI 0.99] Δ no_agent
no_agent 1.253 ms [1.241 ms, 1.265 ms] -
iast 3.382 ms [3.339 ms, 3.425 ms] 2.129 ms (169.9%)
iast_FULL 6.088 ms [6.025 ms, 6.151 ms] 4.835 ms (385.8%)
iast_GLOBAL 3.58 ms [3.527 ms, 3.633 ms] 2.327 ms (185.7%)
profiling 2.309 ms [2.287 ms, 2.331 ms] 1.056 ms (84.3%)
tracing 1.923 ms [1.907 ms, 1.939 ms] 669.819 µs (53.4%)

Dacapo

Parameters

Baseline Candidate
baseline_or_candidate baseline candidate
git_branch master alejandro.gonzalez/APPSEC-61873-3
git_commit_date 1775810809 1775813520
git_commit_sha 067d0d2 b9f5a74
release_version 1.62.0-SNAPSHOT~067d0d2c4b 1.61.0-SNAPSHOT~b9f5a74c5a
See matching parameters
Baseline Candidate
application biojava biojava
ci_job_date 1775815496 1775815496
ci_job_id 1584605739 1584605739
ci_pipeline_id 107049550 107049550
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-j6zka7jr 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-j6zka7jr 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 10 metrics, 1 unstable metrics.

scenario Δ mean execution_time candidate mean execution_time baseline mean execution_time
scenario:dacapo:tomcat:appsec better
[-1.490ms; -1.142ms] or [-38.698%; -29.657%]
2.535ms 3.851ms
Execution time for biojava
gantt
    title biojava - execution time [CI 0.99] : candidate=1.61.0-SNAPSHOT~b9f5a74c5a, baseline=1.62.0-SNAPSHOT~067d0d2c4b
    dateFormat X
    axisFormat %s
section baseline
no_agent (15.593 s) : 15593000, 15593000
.   : milestone, 15593000,
appsec (14.86 s) : 14860000, 14860000
.   : milestone, 14860000,
iast (18.378 s) : 18378000, 18378000
.   : milestone, 18378000,
iast_GLOBAL (18.297 s) : 18297000, 18297000
.   : milestone, 18297000,
profiling (14.617 s) : 14617000, 14617000
.   : milestone, 14617000,
tracing (14.79 s) : 14790000, 14790000
.   : milestone, 14790000,
section candidate
no_agent (14.83 s) : 14830000, 14830000
.   : milestone, 14830000,
appsec (15.28 s) : 15280000, 15280000
.   : milestone, 15280000,
iast (18.49 s) : 18490000, 18490000
.   : milestone, 18490000,
iast_GLOBAL (17.859 s) : 17859000, 17859000
.   : milestone, 17859000,
profiling (14.958 s) : 14958000, 14958000
.   : milestone, 14958000,
tracing (14.936 s) : 14936000, 14936000
.   : milestone, 14936000,
Loading
  • baseline results
Variant Execution Time [CI 0.99] Δ no_agent
no_agent 15.593 s [15.593 s, 15.593 s] -
appsec 14.86 s [14.86 s, 14.86 s] -733.0 ms (-4.7%)
iast 18.378 s [18.378 s, 18.378 s] 2.785 s (17.9%)
iast_GLOBAL 18.297 s [18.297 s, 18.297 s] 2.704 s (17.3%)
profiling 14.617 s [14.617 s, 14.617 s] -976.0 ms (-6.3%)
tracing 14.79 s [14.79 s, 14.79 s] -803.0 ms (-5.1%)
  • candidate results
Variant Execution Time [CI 0.99] Δ no_agent
no_agent 14.83 s [14.83 s, 14.83 s] -
appsec 15.28 s [15.28 s, 15.28 s] 450.0 ms (3.0%)
iast 18.49 s [18.49 s, 18.49 s] 3.66 s (24.7%)
iast_GLOBAL 17.859 s [17.859 s, 17.859 s] 3.029 s (20.4%)
profiling 14.958 s [14.958 s, 14.958 s] 128.0 ms (0.9%)
tracing 14.936 s [14.936 s, 14.936 s] 106.0 ms (0.7%)
Execution time for tomcat
gantt
    title tomcat - execution time [CI 0.99] : candidate=1.61.0-SNAPSHOT~b9f5a74c5a, baseline=1.62.0-SNAPSHOT~067d0d2c4b
    dateFormat X
    axisFormat %s
section baseline
no_agent (1.489 ms) : 1477, 1500
.   : milestone, 1489,
appsec (3.851 ms) : 3629, 4073
.   : milestone, 3851,
iast (2.28 ms) : 2210, 2350
.   : milestone, 2280,
iast_GLOBAL (2.322 ms) : 2252, 2392
.   : milestone, 2322,
profiling (2.529 ms) : 2362, 2695
.   : milestone, 2529,
tracing (2.088 ms) : 2034, 2142
.   : milestone, 2088,
section candidate
no_agent (1.487 ms) : 1475, 1499
.   : milestone, 1487,
appsec (2.535 ms) : 2479, 2590
.   : milestone, 2535,
iast (2.286 ms) : 2216, 2356
.   : milestone, 2286,
iast_GLOBAL (2.317 ms) : 2247, 2388
.   : milestone, 2317,
profiling (2.1 ms) : 2045, 2155
.   : milestone, 2100,
tracing (2.094 ms) : 2040, 2149
.   : milestone, 2094,
Loading
  • baseline results
Variant Execution Time [CI 0.99] Δ no_agent
no_agent 1.489 ms [1.477 ms, 1.5 ms] -
appsec 3.851 ms [3.629 ms, 4.073 ms] 2.362 ms (158.7%)
iast 2.28 ms [2.21 ms, 2.35 ms] 791.54 µs (53.2%)
iast_GLOBAL 2.322 ms [2.252 ms, 2.392 ms] 832.906 µs (55.9%)
profiling 2.529 ms [2.362 ms, 2.695 ms] 1.04 ms (69.8%)
tracing 2.088 ms [2.034 ms, 2.142 ms] 599.287 µs (40.3%)
  • candidate results
Variant Execution Time [CI 0.99] Δ no_agent
no_agent 1.487 ms [1.475 ms, 1.499 ms] -
appsec 2.535 ms [2.479 ms, 2.59 ms] 1.048 ms (70.5%)
iast 2.286 ms [2.216 ms, 2.356 ms] 798.902 µs (53.7%)
iast_GLOBAL 2.317 ms [2.247 ms, 2.388 ms] 830.429 µs (55.8%)
profiling 2.1 ms [2.045 ms, 2.155 ms] 612.722 µs (41.2%)
tracing 2.094 ms [2.04 ms, 2.149 ms] 607.479 µs (40.9%)

@jandro996 jandro996 force-pushed the alejandro.gonzalez/APPSEC-61873-3 branch from e3d4073 to e2d5ed0 Compare April 6, 2026 08:02
Add GetFilenamesAdvice to all three Jetty AppSec modules to collect
uploaded file names from multipart requests and fire the
requestFilesFilenames() IG callback:

- jetty-appsec-8.1.3: intercepts getParts() return value; includes
  Content-Disposition header fallback for Servlet 3.0 (Jetty 9.0)
  where getSubmittedFileName() is not available
- jetty-appsec-9.2: intercepts no-arg getParts() for Servlet 3.1+
- jetty-appsec-9.3: same, applies to Jetty 9.3, 10, 11

Enable testBodyFilenames() in Jetty 9.x, 10 and 11 server tests.
@jandro996 jandro996 force-pushed the alejandro.gonzalez/APPSEC-61873-3 branch 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 2 times, most recently from ecf65c5 to eae08aa Compare April 6, 2026 14:13
…MultiMap) path

- jetty-appsec-9.3: add call-depth guard (Collection.class) to GetFilenamesAdvice
  to prevent double callback invocation when getParts() calls getParts(MultiMap) internally
- jetty-appsec-9.2: extend GetFilenamesAdvice matcher to all getParts overloads
  (not just no-arg) to cover getParameter*()/getParameterMap() code paths,
  guarded with same call-depth mechanism to avoid double-firing
@jandro996 jandro996 force-pushed the alejandro.gonzalez/APPSEC-61873-3 branch 2 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
- Add BODY_MULTIPART_REPEATED case to TestServlet3 (javax) so Jetty 9.x/10.x
  test modules can exercise the repeated getParts() scenario
- Enable testBodyFilenamesCalledOnce() for Jetty 9.0, 9.0.4, 9.3, 9.4.21, and 10.0
…vice path

- New BODY_MULTIPART_COMBINED endpoint: calls getParameterMap() first (triggers
  GetFilenamesFromMultiPartAdvice via extractContentParameters -> getParts(MultiMap)),
  then getParts() explicitly (GetFilenamesAdvice must not double-fire since
  _contentParameters is already set)
- New test 'file upload filenames called once via parameter map' verifies the
  callback fires exactly once across both advice paths
- Enabled in Jetty 9.0, 9.0.4, 9.3, 9.4.21, 10.0 and 11.0
…eplaces _contentParameters as the getParts() cache

In Jetty 9.3, getParts(MultiMap) sets _contentParameters, so the map==null guard prevents
re-firing on repeated getParts() calls. In Jetty 9.4+, getParts() delegates to getParts(null)
and caches the result in _multiParts instead, leaving _contentParameters null on every call.
Add _multiParts==null as an additional guard (optional=true handles Jetty 9.3 where the
field does not exist).
In Jetty 8.x/9.0, _multiPartInputStream is null only on the first getParts() call.
Add OnMethodEnter guard to skip the WAF callback on subsequent calls which return
the cached multipart result.
@advice.FieldValue(optional=true) is not supported in ByteBuddy 1.11.22.
Replace it with @Advice.This + inline reflection to detect whether getParts()
has already been called on this request:

- Jetty 9.4+: checks _multiParts (set after first getParts() call)
- Jetty 9.3.x: falls back to _multiPartInputStream (the cache field in 9.3.x,
  where _multiParts does not exist and _contentParameters is only set by the
  getParameterMap() → extractContentParameters() path, not by getParts())

Covers all forkedTest and latestDepForkedTest suites for Jetty 9.0–11.
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).
…t 3.1+ branch

Jetty 8 implements only Servlet 3.0, so getSubmittedFileName() is never
present on the Part objects. The reflection probe (try { getMethod("getSubmittedFileName") })
and the Servlet 3.1+ code path were dead code. Remove them and always
parse filenames from the Content-Disposition header directly.
Type @Advice.Return as Collection<Part> so the loop variable
can be Part directly, eliminating the (Part) cast on each iteration.
Move the filename extraction logic from GetFilenamesAdvice into a
new MultipartHelper helper class so it can be unit tested in isolation.
Add 12 Spock test cases covering quoted/unquoted filenames, empty
values, whitespace, null input, and edge cases.
…unit tests

Move the getSubmittedFileName() loop from GetFilenamesAdvice into a new
MultipartHelper helper class (injected via helperClassNames) so it can be
unit tested in isolation. Add 8 Spock test cases covering null/empty
collections, null/empty filenames, multiple parts, and special characters.
Eliminates all reflection from the multipart filename instrumentation by
creating version-specific modules with compile-time type safety:

- jetty-appsec-9.3 [9.3,9.4): javax.servlet, uses _multiPartInputStream field
- jetty-appsec-9.4 [9.4,11.0): javax.servlet, uses _multiParts field
- jetty-appsec-11.0 [11.0,12.0): jakarta.servlet, uses _multiParts field

Each module uses muzzle references as version discriminators instead of
runtime reflection, and delegates filename extraction to a testable
MultipartHelper class with 8 Spock unit tests each.

Server test modules updated to reference the correct appsec module per
Jetty version range.
- Add Jetty8LatestDepForkedTest: runs against Jetty 8.x (latestDepForkedTest
  task) and enables testBodyMultipart/testBodyFilenames coverage. Gated by
  'test.dd.filenames' system property so it is skipped when running against
  Jetty 7.6.
- Add testCompileOnly dep on org.eclipse.jetty.orbit:javax.servlet so
  MultipartConfigElement compiles without pulling in the excluded
  javax.servlet:javax.servlet-api artifact.
- Fix ParameterCollector.put to accept (Object, Object) and cast internally:
  Jetty 8.x MultiMap.add uses (Object, Object) descriptor while Jetty 9.x
  uses (String, Object), so the ASM bytecode visitor was silently skipping
  all form field captures on Jetty 8.
- Update GetPartsMethodVisitor to match both (String,Object) and (Object,Object)
  MultiMap.add descriptors and emit the INVOKEINTERFACE with (Object, Object).
_multiPartInputStream was replaced by _multiParts in Jetty 9.4.10.v20180503.
Early 9.4.x versions (9.4.0–9.4.9) still use _multiPartInputStream like 9.3.x,
so extend jetty-appsec-9.3 to cover [9.3, 9.4.10) and narrow jetty-appsec-9.4
to [9.4.10, 11.0). The classLoaderMatcher in jetty-appsec-9.4 (checking for
_multiParts) now correctly matches only versions >= 9.4.10.
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