-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Java: add more Spring RestTemplate request forgery sinks #20930
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| --- | ||
| category: minorAnalysis | ||
| --- | ||
| * URI template variables of all Spring `RestTemplate` methods are now considered as request forgery sinks. Previously only the `getForObject` method was considered. This may lead to more alerts for the query `java/ssrf`. |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -31,50 +31,74 @@ class SpringWebClient extends Interface { | |||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /** The method `getForObject` on `org.springframework.web.reactive.function.client.RestTemplate`. */ | ||||||||||
| class SpringRestTemplateGetForObjectMethod extends Method { | ||||||||||
| SpringRestTemplateGetForObjectMethod() { | ||||||||||
| /** | ||||||||||
| * A method on `org.springframework.web.reactive.function.client.RestTemplate` | ||||||||||
| * which has a parameter `uriVariables` (which can have type `Object..` or | ||||||||||
| * `Map<String, ?>`) which contains variables to be expanded into the URL | ||||||||||
| * template in parameter 0. | ||||||||||
| */ | ||||||||||
| private class SpringRestTemplateMethodWithUriVariablesParameter extends Method { | ||||||||||
| int pos; | ||||||||||
|
|
||||||||||
| SpringRestTemplateMethodWithUriVariablesParameter() { | ||||||||||
| this.getDeclaringType() instanceof SpringRestTemplate and | ||||||||||
| this.hasName("getForObject") | ||||||||||
| ( | ||||||||||
| this.hasName("delete") and pos = 1 | ||||||||||
| or | ||||||||||
| this.hasName("exchange") and pos = 4 | ||||||||||
| or | ||||||||||
| this.hasName("execute") and pos = 4 | ||||||||||
| or | ||||||||||
| this.hasName("getForEntity") and pos = 2 | ||||||||||
| or | ||||||||||
| this.hasName("getForObject") and pos = 2 | ||||||||||
| or | ||||||||||
| this.hasName("headForHeaders") and pos = 1 | ||||||||||
| or | ||||||||||
| this.hasName("optionsForAllow") and pos = 1 | ||||||||||
| or | ||||||||||
| this.hasName("patchForObject") and pos = 3 | ||||||||||
| or | ||||||||||
| this.hasName("postForEntity") and pos = 3 | ||||||||||
| or | ||||||||||
| this.hasName("postForLocation") and pos = 2 | ||||||||||
| or | ||||||||||
| this.hasName("postForObject") and pos = 3 | ||||||||||
| or | ||||||||||
| this.hasName("put") and pos = 2 | ||||||||||
| ) | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /** A call to the method `getForObject` on `org.springframework.web.reactive.function.client.RestTemplate`. */ | ||||||||||
| class SpringRestTemplateGetForObjectMethodCall extends MethodCall { | ||||||||||
| SpringRestTemplateGetForObjectMethodCall() { | ||||||||||
| this.getMethod() instanceof SpringRestTemplateGetForObjectMethod | ||||||||||
| } | ||||||||||
| int getUriVariablesPosition() { result = pos } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| /** Gets the first argument, if it is a compile time constant. */ | ||||||||||
| CompileTimeConstantExpr getConstantUrl() { result = this.getArgument(0) } | ||||||||||
| /** Gets the first argument, if it is a compile time constant. */ | ||||||||||
| pragma[inline] | ||||||||||
| private CompileTimeConstantExpr getConstantUrl(MethodCall mc) { result = mc.getArgument(0) } | ||||||||||
|
|
||||||||||
| /** | ||||||||||
| * Holds if the first argument is a compile time constant and it has a | ||||||||||
| * placeholder at offset `offset`, and there are `idx` placeholders that | ||||||||||
| * appear before it. | ||||||||||
| */ | ||||||||||
| predicate urlHasPlaceholderAtOffset(int idx, int offset) { | ||||||||||
| exists( | ||||||||||
| this.getConstantUrl() | ||||||||||
| .getStringValue() | ||||||||||
| .replaceAll("\\{", " ") | ||||||||||
| .replaceAll("\\}", " ") | ||||||||||
| .regexpFind("\\{[^}]*\\}", idx, offset) | ||||||||||
| ) | ||||||||||
| } | ||||||||||
| pragma[inline] | ||||||||||
| private predicate urlHasPlaceholderAtOffset(MethodCall mc, int idx, int offset) { | ||||||||||
| exists( | ||||||||||
| getConstantUrl(mc) | ||||||||||
| .getStringValue() | ||||||||||
| .replaceAll("\\{", " ") | ||||||||||
| .replaceAll("\\}", " ") | ||||||||||
| .regexpFind("\\{[^}]*\\}", idx, offset) | ||||||||||
| ) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| private class SpringWebClientRestTemplateGetForObject extends RequestForgerySink { | ||||||||||
| SpringWebClientRestTemplateGetForObject() { | ||||||||||
|
||||||||||
| private class SpringWebClientRestTemplateGetForObject extends RequestForgerySink { | |
| SpringWebClientRestTemplateGetForObject() { | |
| private class SpringWebClientRestTemplateUriVariables extends RequestForgerySink { | |
| SpringWebClientRestTemplateUriVariables() { |
Outdated
Copilot
AI
Nov 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment "arguments beyond the first two" is inaccurate for some methods. For example, delete has uriVariables at position 1, making it "arguments beyond the first", and headForHeaders/optionsForAllow also have uriVariables at position 1. Consider updating to "arguments beyond the URL parameter" or a similar generic description.
| // separately. This model is for arguments beyond the first two. There | |
| // separately. This model is for arguments beyond the URL parameter (i.e., those corresponding to `uriVariables`). There |
Uh oh!
There was an error while loading. Please reload this page.