Add server.request.body.filenames support for Jetty#10988
Add server.request.body.filenames support for Jetty#10988
Conversation
BenchmarksStartupParameters
See matching parameters
SummaryFound 0 performance improvements and 0 performance regressions! Performance is the same for 61 metrics, 10 unstable metrics. Startup time reports for petclinicgantt
title petclinic - global startup overhead: candidate=1.61.0-SNAPSHOT~08f15a2f4c, baseline=1.62.0-SNAPSHOT~9f89a0b26cc
dateFormat X
axisFormat %s
section tracing
Agent [baseline] (1.065 s) : 0, 1065446
Total [baseline] (11.065 s) : 0, 11064813
Agent [candidate] (1.06 s) : 0, 1059572
Total [candidate] (11.02 s) : 0, 11020112
section appsec
Agent [baseline] (1.249 s) : 0, 1249227
Total [baseline] (11.138 s) : 0, 11138312
Agent [candidate] (1.248 s) : 0, 1247866
Total [candidate] (11.244 s) : 0, 11243764
section iast
Agent [baseline] (1.234 s) : 0, 1234040
Total [baseline] (11.319 s) : 0, 11318546
Agent [candidate] (1.227 s) : 0, 1226650
Total [candidate] (11.233 s) : 0, 11232771
section profiling
Agent [baseline] (1.188 s) : 0, 1188430
Total [baseline] (11.121 s) : 0, 11120621
Agent [candidate] (1.184 s) : 0, 1183632
Total [candidate] (11.119 s) : 0, 11118654
gantt
title petclinic - break down per module: candidate=1.61.0-SNAPSHOT~08f15a2f4c, baseline=1.62.0-SNAPSHOT~9f89a0b26cc
dateFormat X
axisFormat %s
section tracing
crashtracking [baseline] (1.231 ms) : 0, 1231
crashtracking [candidate] (1.213 ms) : 0, 1213
BytebuddyAgent [baseline] (636.776 ms) : 0, 636776
BytebuddyAgent [candidate] (636.415 ms) : 0, 636415
AgentMeter [baseline] (29.619 ms) : 0, 29619
AgentMeter [candidate] (29.541 ms) : 0, 29541
GlobalTracer [baseline] (250.535 ms) : 0, 250535
GlobalTracer [candidate] (250.21 ms) : 0, 250210
AppSec [baseline] (32.249 ms) : 0, 32249
AppSec [candidate] (32.153 ms) : 0, 32153
Debugger [baseline] (60.792 ms) : 0, 60792
Debugger [candidate] (60.004 ms) : 0, 60004
Remote Config [baseline] (610.292 µs) : 0, 610
Remote Config [candidate] (615.677 µs) : 0, 616
Telemetry [baseline] (8.219 ms) : 0, 8219
Telemetry [candidate] (8.136 ms) : 0, 8136
Flare Poller [baseline] (9.165 ms) : 0, 9165
Flare Poller [candidate] (5.106 ms) : 0, 5106
section appsec
crashtracking [baseline] (1.223 ms) : 0, 1223
crashtracking [candidate] (1.212 ms) : 0, 1212
BytebuddyAgent [baseline] (663.087 ms) : 0, 663087
BytebuddyAgent [candidate] (662.539 ms) : 0, 662539
AgentMeter [baseline] (12.079 ms) : 0, 12079
AgentMeter [candidate] (11.986 ms) : 0, 11986
GlobalTracer [baseline] (249.416 ms) : 0, 249416
GlobalTracer [candidate] (248.449 ms) : 0, 248449
IAST [baseline] (24.558 ms) : 0, 24558
IAST [candidate] (24.613 ms) : 0, 24613
AppSec [baseline] (183.911 ms) : 0, 183911
AppSec [candidate] (184.045 ms) : 0, 184045
Debugger [baseline] (65.835 ms) : 0, 65835
Debugger [candidate] (65.312 ms) : 0, 65312
Remote Config [baseline] (603.059 µs) : 0, 603
Remote Config [candidate] (598.926 µs) : 0, 599
Telemetry [baseline] (8.634 ms) : 0, 8634
Telemetry [candidate] (9.257 ms) : 0, 9257
Flare Poller [baseline] (3.535 ms) : 0, 3535
Flare Poller [candidate] (3.572 ms) : 0, 3572
section iast
crashtracking [baseline] (1.229 ms) : 0, 1229
crashtracking [candidate] (1.23 ms) : 0, 1230
BytebuddyAgent [baseline] (808.444 ms) : 0, 808444
BytebuddyAgent [candidate] (802.82 ms) : 0, 802820
AgentMeter [baseline] (11.476 ms) : 0, 11476
AgentMeter [candidate] (11.491 ms) : 0, 11491
GlobalTracer [baseline] (240.71 ms) : 0, 240710
GlobalTracer [candidate] (239.77 ms) : 0, 239770
IAST [baseline] (25.953 ms) : 0, 25953
IAST [candidate] (25.782 ms) : 0, 25782
AppSec [baseline] (31.12 ms) : 0, 31120
AppSec [candidate] (31.86 ms) : 0, 31860
Debugger [baseline] (60.554 ms) : 0, 60554
Debugger [candidate] (64.348 ms) : 0, 64348
Remote Config [baseline] (539.909 µs) : 0, 540
Remote Config [candidate] (536.807 µs) : 0, 537
Telemetry [baseline] (13.887 ms) : 0, 13887
Telemetry [candidate] (9.269 ms) : 0, 9269
Flare Poller [baseline] (3.51 ms) : 0, 3510
Flare Poller [candidate] (3.442 ms) : 0, 3442
section profiling
crashtracking [baseline] (1.195 ms) : 0, 1195
crashtracking [candidate] (1.171 ms) : 0, 1171
BytebuddyAgent [baseline] (695.645 ms) : 0, 695645
BytebuddyAgent [candidate] (692.383 ms) : 0, 692383
AgentMeter [baseline] (9.16 ms) : 0, 9160
AgentMeter [candidate] (9.102 ms) : 0, 9102
GlobalTracer [baseline] (207.784 ms) : 0, 207784
GlobalTracer [candidate] (206.543 ms) : 0, 206543
AppSec [baseline] (32.376 ms) : 0, 32376
AppSec [candidate] (32.437 ms) : 0, 32437
Debugger [baseline] (65.206 ms) : 0, 65206
Debugger [candidate] (65.448 ms) : 0, 65448
Remote Config [baseline] (564.615 µs) : 0, 565
Remote Config [candidate] (566.036 µs) : 0, 566
Telemetry [baseline] (7.864 ms) : 0, 7864
Telemetry [candidate] (7.842 ms) : 0, 7842
Flare Poller [baseline] (3.574 ms) : 0, 3574
Flare Poller [candidate] (3.552 ms) : 0, 3552
ProfilingAgent [baseline] (93.511 ms) : 0, 93511
ProfilingAgent [candidate] (93.515 ms) : 0, 93515
Profiling [baseline] (94.078 ms) : 0, 94078
Profiling [candidate] (94.078 ms) : 0, 94078
Startup time reports for insecure-bankgantt
title insecure-bank - global startup overhead: candidate=1.61.0-SNAPSHOT~08f15a2f4c, baseline=1.62.0-SNAPSHOT~9f89a0b26cc
dateFormat X
axisFormat %s
section tracing
Agent [baseline] (1.061 s) : 0, 1061185
Total [baseline] (8.877 s) : 0, 8876617
Agent [candidate] (1.057 s) : 0, 1057094
Total [candidate] (8.839 s) : 0, 8839098
section iast
Agent [baseline] (1.232 s) : 0, 1231826
Total [baseline] (9.608 s) : 0, 9608265
Agent [candidate] (1.22 s) : 0, 1219592
Total [candidate] (9.564 s) : 0, 9564451
gantt
title insecure-bank - break down per module: candidate=1.61.0-SNAPSHOT~08f15a2f4c, baseline=1.62.0-SNAPSHOT~9f89a0b26cc
dateFormat X
axisFormat %s
section tracing
crashtracking [baseline] (1.234 ms) : 0, 1234
crashtracking [candidate] (1.222 ms) : 0, 1222
BytebuddyAgent [baseline] (635.293 ms) : 0, 635293
BytebuddyAgent [candidate] (635.794 ms) : 0, 635794
AgentMeter [baseline] (29.553 ms) : 0, 29553
AgentMeter [candidate] (29.304 ms) : 0, 29304
GlobalTracer [baseline] (249.195 ms) : 0, 249195
GlobalTracer [candidate] (250.685 ms) : 0, 250685
AppSec [baseline] (32.005 ms) : 0, 32005
AppSec [candidate] (32.22 ms) : 0, 32220
Debugger [baseline] (59.077 ms) : 0, 59077
Debugger [candidate] (59.432 ms) : 0, 59432
Remote Config [baseline] (597.909 µs) : 0, 598
Remote Config [candidate] (605.25 µs) : 0, 605
Telemetry [baseline] (8.104 ms) : 0, 8104
Telemetry [candidate] (8.122 ms) : 0, 8122
Flare Poller [baseline] (9.907 ms) : 0, 9907
Flare Poller [candidate] (3.54 ms) : 0, 3540
section iast
crashtracking [baseline] (1.246 ms) : 0, 1246
crashtracking [candidate] (1.228 ms) : 0, 1228
BytebuddyAgent [baseline] (807.132 ms) : 0, 807132
BytebuddyAgent [candidate] (798.309 ms) : 0, 798309
AgentMeter [baseline] (11.394 ms) : 0, 11394
AgentMeter [candidate] (11.31 ms) : 0, 11310
GlobalTracer [baseline] (240.882 ms) : 0, 240882
GlobalTracer [candidate] (238.276 ms) : 0, 238276
IAST [baseline] (26.04 ms) : 0, 26040
IAST [candidate] (26.514 ms) : 0, 26514
AppSec [baseline] (31.21 ms) : 0, 31210
AppSec [candidate] (31.001 ms) : 0, 31001
Debugger [baseline] (60.584 ms) : 0, 60584
Debugger [candidate] (63.597 ms) : 0, 63597
Remote Config [baseline] (541.159 µs) : 0, 541
Remote Config [candidate] (534.129 µs) : 0, 534
Telemetry [baseline] (12.784 ms) : 0, 12784
Telemetry [candidate] (9.303 ms) : 0, 9303
Flare Poller [baseline] (3.558 ms) : 0, 3558
Flare Poller [candidate] (3.46 ms) : 0, 3460
LoadParameters
See matching parameters
SummaryFound 1 performance improvements and 2 performance regressions! Performance is the same for 18 metrics, 15 unstable metrics.
Request duration reports for petclinicgantt
title petclinic - request duration [CI 0.99] : candidate=1.61.0-SNAPSHOT~08f15a2f4c, baseline=1.62.0-SNAPSHOT~9f89a0b26cc
dateFormat X
axisFormat %s
section baseline
no_agent (17.87 ms) : 17693, 18048
. : milestone, 17870,
appsec (19.177 ms) : 18985, 19369
. : milestone, 19177,
code_origins (17.855 ms) : 17680, 18030
. : milestone, 17855,
iast (17.73 ms) : 17557, 17903
. : milestone, 17730,
profiling (18.497 ms) : 18313, 18681
. : milestone, 18497,
tracing (17.84 ms) : 17665, 18016
. : milestone, 17840,
section candidate
no_agent (17.91 ms) : 17728, 18092
. : milestone, 17910,
appsec (18.682 ms) : 18496, 18868
. : milestone, 18682,
code_origins (17.89 ms) : 17713, 18067
. : milestone, 17890,
iast (18.045 ms) : 17866, 18224
. : milestone, 18045,
profiling (18.439 ms) : 18255, 18622
. : milestone, 18439,
tracing (17.9 ms) : 17727, 18074
. : milestone, 17900,
Request duration reports for insecure-bankgantt
title insecure-bank - request duration [CI 0.99] : candidate=1.61.0-SNAPSHOT~08f15a2f4c, baseline=1.62.0-SNAPSHOT~9f89a0b26cc
dateFormat X
axisFormat %s
section baseline
no_agent (1.226 ms) : 1214, 1237
. : milestone, 1226,
iast (3.263 ms) : 3216, 3310
. : milestone, 3263,
iast_FULL (5.995 ms) : 5934, 6055
. : milestone, 5995,
iast_GLOBAL (3.612 ms) : 3552, 3673
. : milestone, 3612,
profiling (2.093 ms) : 2076, 2111
. : milestone, 2093,
tracing (1.924 ms) : 1905, 1942
. : milestone, 1924,
section candidate
no_agent (1.25 ms) : 1238, 1263
. : milestone, 1250,
iast (3.39 ms) : 3343, 3438
. : milestone, 3390,
iast_FULL (6.034 ms) : 5972, 6095
. : milestone, 6034,
iast_GLOBAL (3.805 ms) : 3744, 3865
. : milestone, 3805,
profiling (2.08 ms) : 2062, 2098
. : milestone, 2080,
tracing (1.865 ms) : 1850, 1879
. : milestone, 1865,
DacapoParameters
See matching parameters
SummaryFound 0 performance improvements and 0 performance regressions! Performance is the same for 11 metrics, 1 unstable metrics. Execution time for biojavagantt
title biojava - execution time [CI 0.99] : candidate=1.61.0-SNAPSHOT~08f15a2f4c, baseline=1.62.0-SNAPSHOT~9f89a0b26cc
dateFormat X
axisFormat %s
section baseline
no_agent (14.773 s) : 14773000, 14773000
. : milestone, 14773000,
appsec (14.941 s) : 14941000, 14941000
. : milestone, 14941000,
iast (18.616 s) : 18616000, 18616000
. : milestone, 18616000,
iast_GLOBAL (18.345 s) : 18345000, 18345000
. : milestone, 18345000,
profiling (15.1 s) : 15100000, 15100000
. : milestone, 15100000,
tracing (14.918 s) : 14918000, 14918000
. : milestone, 14918000,
section candidate
no_agent (15.479 s) : 15479000, 15479000
. : milestone, 15479000,
appsec (14.701 s) : 14701000, 14701000
. : milestone, 14701000,
iast (18.465 s) : 18465000, 18465000
. : milestone, 18465000,
iast_GLOBAL (18.029 s) : 18029000, 18029000
. : milestone, 18029000,
profiling (15.384 s) : 15384000, 15384000
. : milestone, 15384000,
tracing (14.852 s) : 14852000, 14852000
. : milestone, 14852000,
Execution time for tomcatgantt
title tomcat - execution time [CI 0.99] : candidate=1.61.0-SNAPSHOT~08f15a2f4c, baseline=1.62.0-SNAPSHOT~9f89a0b26cc
dateFormat X
axisFormat %s
section baseline
no_agent (1.495 ms) : 1483, 1506
. : milestone, 1495,
appsec (3.86 ms) : 3637, 4083
. : milestone, 3860,
iast (2.281 ms) : 2212, 2350
. : milestone, 2281,
iast_GLOBAL (2.324 ms) : 2255, 2394
. : milestone, 2324,
profiling (2.108 ms) : 2053, 2163
. : milestone, 2108,
tracing (2.088 ms) : 2035, 2142
. : milestone, 2088,
section candidate
no_agent (1.497 ms) : 1485, 1509
. : milestone, 1497,
appsec (3.743 ms) : 3529, 3957
. : milestone, 3743,
iast (2.286 ms) : 2216, 2355
. : milestone, 2286,
iast_GLOBAL (2.331 ms) : 2261, 2401
. : milestone, 2331,
profiling (2.106 ms) : 2051, 2161
. : milestone, 2106,
tracing (2.09 ms) : 2036, 2143
. : milestone, 2090,
|
e3d4073 to
e2d5ed0
Compare
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.
f2998c3 to
629f074
Compare
| } | ||
| } | ||
| // Fallback: parse filename from Content-Disposition header (Servlet 3.0) | ||
| if (name == null) { |
There was a problem hiding this comment.
Shouldn't this be outside of the main parts loop?
There was a problem hiding this comment.
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"); |
There was a problem hiding this comment.
Fixed. GetFilenamesAdvice now has a call-depth guard (CallDepthThreadLocalMap with Collection.class) to avoid double-firing when getParts() internally calls getParts(MultiMap)
There was a problem hiding this comment.
💡 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".
...va/datadog/trace/instrumentation/jetty92/RequestExtractContentParametersInstrumentation.java
Outdated
Show resolved
Hide resolved
...va/datadog/trace/instrumentation/jetty93/RequestExtractContentParametersInstrumentation.java
Outdated
Show resolved
Hide resolved
ecf65c5 to
eae08aa
Compare
…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
3ab9ff7 to
77ec572
Compare
2e72584 to
d37e03e
Compare
d37e03e to
d8a92f8
Compare
- 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.
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.
…–11.x
The _multiParts field type changes multiple times across Jetty versions,
making a single typed muzzle reference insufficient. Replace the ASM-based
classLoaderMatcher with clean module splits using typed muzzle references:
- jetty-appsec-9.4 [9.4.10, 10.0): _multiParts: MultiParts
_queryEncoding: String (excludes 10.x)
- jetty-appsec-10.0 [10.0, 10.0.10): _multiParts: MultiPartFormInputStream
- jetty-appsec-10.0.10 [10.0.10, 11.0): _multiParts: MultiParts
_queryEncoding: Charset (excludes 9.4.x)
- jetty-appsec-11.0 [11.0, 11.0.10): _multiParts: MultiPartFormInputStream
- jetty-appsec-11.0.10 [11.0.10, 12.0): _multiParts: MultiParts
All six modules pass muzzle with assertInverse = true.
What Does This Do
Jetty parses multipart bodies through two code paths depending on how the application accesses the request:
getParameterMap()→extractContentParameters()→ internalgetParts(MultiMap)getParts()call from user codeBoth paths are instrumented to fire
requestFilesFilenames. Guards on internal state fields (_contentParameters,_multiParts,_multiPartInputStream) prevent double-firing.jetty-appsec-7.0GetFilenamesAdviceforgetParts(). NoextractContentParametersin 7.x so only one path exists.jetty-appsec-8.1.3getSubmittedFileName()so filenames are parsed from theContent-Dispositionheader. Logic extracted toMultipartHelperwith unit tests.jetty-appsec-9.2Part.getSubmittedFileName()(Servlet 3.1). Logic extracted toMultipartHelperwith unit tests.jetty-appsec-9.3[9.3, 12)to[9.3, 9.4). Removed reflection (getDeclaredField/Method.invoke) by restricting scope to only 9.3.x, where_multiPartInputStreamis the correct field.MultipartHelperadded with unit tests.jetty-appsec-9.4(new)[9.4, 11.0)— javax.servlet, uses_multiPartsfield (introduced in 9.4). Previously handled by 9.3 via reflection.MultipartHelperwith unit tests.jetty-appsec-11.0(new)[11.0, 12.0)— jakarta.servlet (first Jetty version to drop javax). Previously handled by 9.3 via reflection.MultipartHelperwith unit tests.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-61873 —
server.request.body.filenamesimplementation across server frameworks.Contributor Checklist
type:and (comp:orinst:) labels in addition to any other useful labelsclose,fix, or any linking keywords when referencing an issueUse
solvesinstead, and assign the PR milestone to the issue