Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions java/ql/lib/change-notes/2026-02-27-micronaut.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added modeling for the Micronaut framework, including HTTP controllers, WebSocket endpoints, configuration injection, data access, security annotations, and HTTP client sinks.
7 changes: 7 additions & 0 deletions java/ql/lib/ext/io.micronaut.context.annotation.model.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: sourceModel
data:
- ["io.micronaut.context.annotation", "Property", True, "", "", "Annotated", "", "environment", "manual"]
- ["io.micronaut.context.annotation", "Value", True, "", "", "Annotated", "", "environment", "manual"]
35 changes: 35 additions & 0 deletions java/ql/lib/ext/io.micronaut.http.client.model.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: sinkModel
data:
- ["io.micronaut.http.client", "BlockingHttpClient", True, "exchange", "(HttpRequest)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "BlockingHttpClient", True, "exchange", "(HttpRequest,Argument)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "BlockingHttpClient", True, "exchange", "(HttpRequest,Argument,Argument)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "BlockingHttpClient", True, "exchange", "(HttpRequest,Class)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "BlockingHttpClient", True, "exchange", "(String)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "BlockingHttpClient", True, "exchange", "(String,Class)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "BlockingHttpClient", True, "exchange", "(String,Class,Class)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "BlockingHttpClient", True, "retrieve", "(HttpRequest)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "BlockingHttpClient", True, "retrieve", "(HttpRequest,Argument)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "BlockingHttpClient", True, "retrieve", "(HttpRequest,Argument,Argument)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "BlockingHttpClient", True, "retrieve", "(HttpRequest,Class)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "BlockingHttpClient", True, "retrieve", "(String)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "BlockingHttpClient", True, "retrieve", "(String,Class)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "BlockingHttpClient", True, "retrieve", "(String,Class,Class)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "HttpClient", True, "exchange", "(HttpRequest)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "HttpClient", True, "exchange", "(HttpRequest,Argument)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "HttpClient", True, "exchange", "(HttpRequest,Argument,Argument)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "HttpClient", True, "exchange", "(HttpRequest,Class)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "HttpClient", True, "exchange", "(String)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "HttpClient", True, "exchange", "(String,Class)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "HttpClient", True, "retrieve", "(HttpRequest)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "HttpClient", True, "retrieve", "(HttpRequest,Argument)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "HttpClient", True, "retrieve", "(HttpRequest,Argument,Argument)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "HttpClient", True, "retrieve", "(HttpRequest,Class)", "", "Argument[0]", "request-forgery", "manual"]
- ["io.micronaut.http.client", "HttpClient", True, "retrieve", "(String)", "", "Argument[0]", "request-forgery", "manual"]
- addsTo:
pack: codeql/java-all
extensible: summaryModel
data:
- ["io.micronaut.http.client", "HttpClient", True, "toBlocking", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
59 changes: 59 additions & 0 deletions java/ql/lib/ext/io.micronaut.http.model.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: sourceModel
data:
- ["io.micronaut.http", "HttpRequest", True, "getBody", "", "", "ReturnValue", "remote", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "getContentLength", "", "", "ReturnValue", "remote", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "getContentType", "", "", "ReturnValue", "remote", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "getCookies", "", "", "ReturnValue", "remote", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "getHeaders", "", "", "ReturnValue", "remote", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "getMethodName", "", "", "ReturnValue", "remote", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "getParameters", "", "", "ReturnValue", "remote", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "getPath", "", "", "ReturnValue", "remote", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "getUri", "", "", "ReturnValue", "remote", "manual"]
- addsTo:
pack: codeql/java-all
extensible: summaryModel
data:
- ["io.micronaut.core.convert.value", "ConvertibleMultiValues", True, "get", "", "", "Argument[this].Element.MapValue", "ReturnValue", "taint", "manual"]
- ["io.micronaut.core.convert.value", "ConvertibleMultiValues", True, "getAll", "", "", "Argument[this].Element.MapValue", "ReturnValue", "value", "manual"]
- ["io.micronaut.core.convert.value", "ConvertibleMultiValues", True, "getFirst", "", "", "Argument[this].Element.MapValue", "ReturnValue", "taint", "manual"]
- ["io.micronaut.core.convert.value", "ConvertibleValues", True, "asMap", "", "", "Argument[this].Element.MapValue", "ReturnValue.MapValue", "taint", "manual"]
- ["io.micronaut.core.convert.value", "ConvertibleValues", True, "asProperties", "", "", "Argument[this].Element.MapValue", "ReturnValue.MapValue", "taint", "manual"]
- ["io.micronaut.core.convert.value", "ConvertibleValues", True, "getValue", "", "", "Argument[this].Element.MapValue", "ReturnValue", "taint", "manual"]
- ["io.micronaut.core.convert.value", "ConvertibleValues", True, "subMap", "", "", "Argument[this].Element.MapValue", "ReturnValue.MapValue", "taint", "manual"]
- ["io.micronaut.core.convert.value", "ConvertibleValues", True, "values", "", "", "Argument[this].Element.MapValue", "ReturnValue.Element", "taint", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "DELETE", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "DELETE", "(String,Object)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "DELETE", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "DELETE", "(URI,Object)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "GET", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "GET", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "HEAD", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "HEAD", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "OPTIONS", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "OPTIONS", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "PATCH", "(String,Object)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "PATCH", "(URI,Object)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "POST", "(String,Object)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "POST", "(URI,Object)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "PUT", "(String,Object)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http", "HttpRequest", True, "PUT", "(URI,Object)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http.cookie", "Cookie", True, "getDomain", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http.cookie", "Cookie", True, "getName", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http.cookie", "Cookie", True, "getPath", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http.cookie", "Cookie", True, "getValue", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http.cookie", "Cookies", True, "findCookie", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http.cookie", "Cookies", True, "get", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http.cookie", "Cookies", True, "getAll", "", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- addsTo:
pack: codeql/java-all
extensible: sinkModel
data:
- ["io.micronaut.http", "HttpResponse", True, "permanentRedirect", "(URI)", "", "Argument[0]", "url-redirection", "manual"]
- ["io.micronaut.http", "HttpResponse", True, "redirect", "(URI)", "", "Argument[0]", "url-redirection", "manual"]

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.

I believe that the following might also be sinks for url-redirection: permanentRedirect, seeOther, temporaryRedirect.

- ["io.micronaut.http", "HttpResponse", True, "seeOther", "(URI)", "", "Argument[0]", "url-redirection", "manual"]
- ["io.micronaut.http", "HttpResponse", True, "temporaryRedirect", "(URI)", "", "Argument[0]", "url-redirection", "manual"]
- ["io.micronaut.http", "MutableHttpResponse", True, "header", "(CharSequence,CharSequence)", "", "Argument[1]", "response-splitting", "manual"]
- ["io.micronaut.http", "MutableHttpResponse", True, "headers", "(Map)", "", "Argument[0]", "response-splitting", "manual"]
10 changes: 10 additions & 0 deletions java/ql/lib/ext/io.micronaut.http.multipart.model.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: sourceModel
data:
- ["io.micronaut.http.multipart", "CompletedFileUpload", True, "getBytes", "", "", "ReturnValue", "remote", "manual"]
- ["io.micronaut.http.multipart", "CompletedFileUpload", True, "getInputStream", "", "", "ReturnValue", "remote", "manual"]
- ["io.micronaut.http.multipart", "CompletedFileUpload", True, "getFilename", "", "", "ReturnValue", "remote", "manual"]
- ["io.micronaut.http.multipart", "CompletedFileUpload", True, "getContentType", "", "", "ReturnValue", "remote", "manual"]
- ["io.micronaut.http.multipart", "CompletedFileUpload", True, "getSize", "", "", "ReturnValue", "remote", "manual"]
28 changes: 28 additions & 0 deletions java/ql/lib/ext/io.micronaut.http.uri.model.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: summaryModel
data:
- ["io.micronaut.http.uri", "UriBuilder", True, "build", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "expand", "(Map)", "", "Argument[0].MapValue", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "expand", "(Map)", "", "Argument[this]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "fragment", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "fragment", "(String)", "", "Argument[this]", "ReturnValue", "value", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "host", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "host", "(String)", "", "Argument[this]", "ReturnValue", "value", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "of", "(CharSequence)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "of", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "path", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "path", "(String)", "", "Argument[this]", "ReturnValue", "value", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "queryParam", "(String,Object[])", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "queryParam", "(String,Object[])", "", "Argument[1].ArrayElement", "Argument[this]", "taint", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "queryParam", "(String,Object[])", "", "Argument[this]", "ReturnValue", "value", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "replacePath", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "replacePath", "(String)", "", "Argument[this]", "ReturnValue", "value", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "replaceQueryParam", "(String,Object[])", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "replaceQueryParam", "(String,Object[])", "", "Argument[1].ArrayElement", "Argument[this]", "taint", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "replaceQueryParam", "(String,Object[])", "", "Argument[this]", "ReturnValue", "value", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "scheme", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "scheme", "(String)", "", "Argument[this]", "ReturnValue", "value", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "userInfo", "(String)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
- ["io.micronaut.http.uri", "UriBuilder", True, "userInfo", "(String)", "", "Argument[this]", "ReturnValue", "value", "manual"]
24 changes: 24 additions & 0 deletions java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import semmle.code.java.frameworks.Guice
import semmle.code.java.frameworks.struts.StrutsActions
import semmle.code.java.frameworks.Thrift
import semmle.code.java.frameworks.javaee.jsf.JSFRenderer
import semmle.code.java.frameworks.micronaut.MicronautController
import semmle.code.java.frameworks.micronaut.MicronautWebSocket
private import semmle.code.java.dataflow.ExternalFlow
private import codeql.threatmodels.ThreatModels

Expand Down Expand Up @@ -187,6 +189,28 @@ private class AndroidExternalStorageSource extends RemoteFlowSource {
override string getSourceType() { result = "Android external storage" }
}

private class MicronautHttpInputParameterSource extends RemoteFlowSource {
MicronautHttpInputParameterSource() {
this.asParameter() = any(MicronautRequestMappingParameter mrmp | mrmp.isTaintedInput())
}

override string getSourceType() { result = "Micronaut HTTP input parameter" }
}

private class MicronautWebSocketParameterSource extends RemoteFlowSource {
MicronautWebSocketParameterSource() { this.asParameter() instanceof MicronautWebSocketParameter }

override string getSourceType() { result = "Micronaut WebSocket parameter" }
}

private class MicronautErrorHandlerSource extends RemoteFlowSource {
MicronautErrorHandlerSource() {
this.asParameter() = any(MicronautErrorHandler h).getARemoteParameter()
}

override string getSourceType() { result = "Micronaut error handler parameter" }
}

/** Class for `tainted` user input. */
abstract class UserInput extends SourceNode { }

Expand Down
Loading
Loading