Skip to content

Java: Model Spring reactive WebClient.uri as a request forgery sink#22132

Merged
owen-mc merged 3 commits into
github:mainfrom
joshimar:java/spring-webclient-uri-ssrf-sink
Jul 7, 2026
Merged

Java: Model Spring reactive WebClient.uri as a request forgery sink#22132
owen-mc merged 3 commits into
github:mainfrom
joshimar:java/spring-webclient-uri-ssrf-sink

Conversation

@joshimar

@joshimar joshimar commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Spring WebFlux's reactive WebClient sends a request to the URL passed to the per-request uri(...) method (for example webClient.get().uri(url)), declared on WebClient.UriSpec. The request-forgery model covers WebClient.create(url) and WebClient.builder().baseUrl(url). It does not yet cover the per-request uri(...) method, which is the usual way to set a request URL, so a URL built from untrusted input and sent through uri(...) is a java/ssrf sink that is currently unmodeled.

Change

Adds WebClient$UriSpec.uri as a request-forgery sink:

- ["org.springframework.web.reactive.function.client", "WebClient$UriSpec", True, "uri", "", "", "Argument[0]", "request-forgery", "manual"]
  • subtypes is True so the row also applies to RequestHeadersUriSpec and RequestBodyUriSpec, the receiver types returned by get(), post() and similar methods.
  • The signature is left blank to cover all URL-bearing overloads: uri(URI), uri(String, Object...) and uri(String, Map).

Testing

Validated at three levels.

Query tests. ReactiveWebClientSSRF.java adds tainted flows into uri(String) and uri(URI), and RequestForgery.expected is regenerated. The CWE-918 tests pass.

True positives (full-build database). Compiled against the Spring WebFlux library, the sink reports untrusted input reaching the request URL:

  • directly, via uri(String);
  • as a URI template, via uri(String, Object...);
  • via a UriComponentsBuilder whose host is attacker-controlled (fromUriString, host).

Multi-repository variant analysis.

  • Dataset: 34 popular public Java projects (Spring and WebFlux based), using the CodeQL databases GitHub publishes for them, fetched through the code scanning API. The full list is below:
Repositories analyzed (34)
  • Coverage check: the sink resolves and matches WebClient.uri call sites across the dataset, confirming the run exercises the new model.
  • Result: no alerts, confirming no false positives on the dataset.

Overload coverage

The blank signature also matches the uri(Function<UriBuilder, URI>) overload, whose Argument[0] is a builder callback. This matches how other fluent URL setters are modeled. The row can be restricted to the String and URI overloads if preferred.

@joshimar joshimar requested a review from a team as a code owner July 7, 2026 20:41
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

⚠️ The head of this PR and the base branch were compared for differences in the framework coverage reports. The generated reports are available in the artifacts of this workflow run. The differences will be picked up by the nightly job after the PR gets merged.

Click to show differences in coverage

java

Generated file changes for java

  • Changes to framework-coverage-java.rst:
-    `Spring <https://spring.io/>`_,``org.springframework.*``,46,494,143,26,,28,14,,35
+    `Spring <https://spring.io/>`_,``org.springframework.*``,46,494,144,26,,28,14,,36
-    Totals,,382,26411,2707,421,16,137,33,1,415
+    Totals,,382,26411,2708,421,16,137,33,1,416
  • Changes to framework-coverage-java.csv:
- org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,
+ org.springframework.web.reactive.function.client,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,,,,,,,,,,,,

@owen-mc owen-mc requested a review from Copilot July 7, 2026 23:00
Comment thread java/ql/lib/change-notes/2026-06-30-spring-webclient-uri-ssrf.md Outdated
Comment thread java/ql/lib/ext/org.springframework.web.reactive.function.client.model.yml Outdated
@owen-mc

owen-mc commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Thanks for this contribution. It looks pretty much all correct. The copyright notice will need to be removed though.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR extends the Java request-forgery (SSRF) sink modeling for Spring WebFlux by treating WebClient.UriSpec.uri(...) as a request-forgery sink, closing a common modeling gap where URLs are set per-request rather than at client construction time.

Changes:

  • Add a request-forgery sink model for org.springframework.web.reactive.function.client.WebClient$UriSpec.uri (with subtypes=True) to cover typical fluent usages like webClient.get().uri(...).
  • Extend the Spring WebClient test stub to include the uri(URI) overload needed by the new query-test cases.
  • Add new CWE-918 query-test coverage for .uri(String) (via varargs overload) and .uri(URI), updating the expected results and documenting the behavior change in release notes.
Show a summary per file
File Description
java/ql/lib/ext/org.springframework.web.reactive.function.client.model.yml Adds the new SSRF sink model for WebClient$UriSpec.uri(...).
java/ql/test/stubs/springframework-5.8.x/org/springframework/web/reactive/function/client/WebClient.java Updates stub API surface to include uri(java.net.URI) for compilation/type resolution.
java/ql/test/query-tests/security/CWE-918/ReactiveWebClientSSRF.java Adds new query-test flows into WebClient.uri(...) overloads.
java/ql/test/query-tests/security/CWE-918/RequestForgery.expected Regenerates expected results to include the new sink detections.
java/ql/lib/change-notes/2026-06-30-spring-webclient-uri-ssrf.md Documents the new sink modeling as a minor analysis change.

Review details

  • Files reviewed: 4/5 changed files
  • Comments generated: 1
  • Review effort level: Low

Comment on lines 1 to 2
# Copyright © 2026 Apple Inc.
extensions:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed per @owen-mc suggested change (thanks!)

joshimar and others added 2 commits July 7, 2026 16:10
Removing Apple Inc notice per feedback provided by GitHub

Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
Update change note to be more technically accurate

Co-authored-by: Owen Mansel-Chan <62447351+owen-mc@users.noreply.github.com>
@owen-mc owen-mc merged commit 8363d2d into github:main Jul 7, 2026
16 of 19 checks passed
@joshimar joshimar deleted the java/spring-webclient-uri-ssrf-sink branch July 8, 2026 00:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants