Skip to content
Merged
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 cpp/ql/lib/change-notes/2026-03-31-http-flow-sources.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added `HttpReceiveHttpRequest`, `HttpReceiveRequestEntityBody`, and `HttpReceiveClientCertificate` from Win32's `http.h` as remote flow sources.
3 changes: 3 additions & 0 deletions cpp/ql/lib/ext/Windows.model.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ extensions:
- ["", "", False, "WinHttpQueryHeadersEx", "", "", "Argument[*5]", "remote", "manual"]
- ["", "", False, "WinHttpQueryHeadersEx", "", "", "Argument[*6]", "remote", "manual"]
- ["", "", False, "WinHttpQueryHeadersEx", "", "", "Argument[**8]", "remote", "manual"]
- ["", "", False, "HttpReceiveHttpRequest", "", "", "Argument[*3]", "remote", "manual"]
- ["", "", False, "HttpReceiveRequestEntityBody", "", "", "Argument[*3]", "remote", "manual"]
- ["", "", False, "HttpReceiveClientCertificate", "", "", "Argument[*3]", "remote", "manual"]
- addsTo:
pack: codeql/cpp-all
extensible: summaryModel
Expand Down
1 change: 1 addition & 0 deletions cpp/ql/lib/semmle/code/cpp/models/Models.qll
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,4 @@ private import implementations.CAtlFileMapping
private import implementations.CAtlTemporaryFile
private import implementations.CRegKey
private import implementations.WinHttp
private import implementations.Http
193 changes: 193 additions & 0 deletions cpp/ql/lib/semmle/code/cpp/models/implementations/Http.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
private import cpp
private import semmle.code.cpp.ir.dataflow.FlowSteps
private import semmle.code.cpp.dataflow.new.DataFlow

private class HttpRequest extends Class {
HttpRequest() { this.hasGlobalName("_HTTP_REQUEST_V1") }
}

private class HttpRequestInheritingContent extends TaintInheritingContent, DataFlow::FieldContent {
HttpRequestInheritingContent() {
this.getAField().getDeclaringType() instanceof HttpRequest and
(
this.getAField().hasName("pRawUrl") and
this.getIndirectionIndex() = 2
or
this.getAField().hasName("CookedUrl") and
this.getIndirectionIndex() = 1
or
this.getAField().hasName("Headers") and
this.getIndirectionIndex() = 1
or
this.getAField().hasName("pEntityChunks") and
this.getIndirectionIndex() = 2
or
this.getAField().hasName("pSslInfo") and
this.getIndirectionIndex() = 2
)
}
}

private class HttpCookedUrl extends Class {
HttpCookedUrl() { this.hasGlobalName("_HTTP_COOKED_URL") }
}

private class HttpCookedUrlInheritingContent extends TaintInheritingContent, DataFlow::FieldContent {
HttpCookedUrlInheritingContent() {
this.getAField().getDeclaringType() instanceof HttpCookedUrl and
this.getAField().hasName(["pFullUrl", "pHost", "pAbsPath", "pQueryString"]) and
this.getIndirectionIndex() = 2
}
}

private class HttpRequestHeaders extends Class {
HttpRequestHeaders() { this.hasGlobalName("_HTTP_REQUEST_HEADERS") }
}

private class HttpRequestHeadersInheritingContent extends TaintInheritingContent,
DataFlow::FieldContent
{
HttpRequestHeadersInheritingContent() {
this.getAField().getDeclaringType() instanceof HttpRequestHeaders and
(
this.getAField().hasName("KnownHeaders") and
this.getIndirectionIndex() = 1
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.

Should this one also be updated?

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.

You're too fast for me 😅 The TLDR is 'no'. I've explained why here

or
this.getAField().hasName("pUnknownHeaders") and
this.getIndirectionIndex() = 2
)
}
}

private class HttpKnownHeader extends Class {
HttpKnownHeader() { this.hasGlobalName("_HTTP_KNOWN_HEADER") }
}

private class HttpKnownHeaderInheritingContent extends TaintInheritingContent,
DataFlow::FieldContent
{
HttpKnownHeaderInheritingContent() {
this.getAField().getDeclaringType() instanceof HttpKnownHeader and
this.getAField().hasName("pRawValue") and
this.getIndirectionIndex() = 2
}
}

private class HttpUnknownHeader extends Class {
HttpUnknownHeader() { this.hasGlobalName("_HTTP_UNKNOWN_HEADER") }
}

private class HttpUnknownHeaderInheritingContent extends TaintInheritingContent,
DataFlow::FieldContent
{
HttpUnknownHeaderInheritingContent() {
this.getAField().getDeclaringType() instanceof HttpUnknownHeader and
this.getAField().hasName(["pName", "pRawValue"]) and
this.getIndirectionIndex() = 2
}
}

private class HttpDataChunk extends Class {
HttpDataChunk() { this.hasGlobalName("_HTTP_DATA_CHUNK") }
}

private class HttpDataChunkInheritingContent extends TaintInheritingContent, DataFlow::FieldContent {
HttpDataChunkInheritingContent() {
this.getAField().getDeclaringType().(Union).getDeclaringType() instanceof HttpDataChunk and
(
this.getAField().hasName("FromMemory") and
this.getIndirectionIndex() = 1
or
this.getAField().hasName("FromFileHandle") and
this.getIndirectionIndex() = 1
or
this.getAField().hasName("FromFragmentCache") and
this.getIndirectionIndex() = 1
or
this.getAField().hasName("FromFragmentCacheEx") and
this.getIndirectionIndex() = 1
or
this.getAField().hasName("Trailers") and
this.getIndirectionIndex() = 1
)
}
}

private class FromMemory extends Class {
FromMemory() {
this.getDeclaringType().(Union).getDeclaringType() instanceof HttpDataChunk and
this.getAField().hasName("pBuffer")
}
}

private class FromMemoryInheritingContent extends TaintInheritingContent, DataFlow::FieldContent {
FromMemoryInheritingContent() {
this.getAField().getDeclaringType() instanceof FromMemory and
this.getAField().hasName("pBuffer") and
this.getIndirectionIndex() = 2
}
}

private class FromFileHandle extends Class {
FromFileHandle() {
this.getDeclaringType().(Union).getDeclaringType() instanceof HttpDataChunk and
this.getAField().hasName("FileHandle")
}
}

private class FromFileHandleInheritingContent extends TaintInheritingContent, DataFlow::FieldContent
{
FromFileHandleInheritingContent() {
this.getAField().getDeclaringType() instanceof FromFileHandle and
this.getIndirectionIndex() = 1 and
this.getAField().hasName("FileHandle")
}
}

private class FromFragmentCacheOrCacheEx extends Class {
FromFragmentCacheOrCacheEx() {
this.getDeclaringType().(Union).getDeclaringType() instanceof HttpDataChunk and
this.getAField().hasName("pFragmentName")
}
}

private class FromFragmentCacheInheritingContent extends TaintInheritingContent,
DataFlow::FieldContent
{
FromFragmentCacheInheritingContent() {
this.getAField().getDeclaringType() instanceof FromFragmentCacheOrCacheEx and
this.getIndirectionIndex() = 2 and
this.getAField().hasName("pFragmentName")
}
}

private class HttpSslInfo extends Class {
HttpSslInfo() { this.hasGlobalName("_HTTP_SSL_INFO") }
}

private class HttpSslInfoInheritingContent extends TaintInheritingContent, DataFlow::FieldContent {
HttpSslInfoInheritingContent() {
this.getAField().getDeclaringType() instanceof HttpSslInfo and
this.getAField().hasName(["pServerCertIssuer", "pServerCertSubject", "pClientCertInfo"]) and
this.getIndirectionIndex() = 2
}
}

private class HttpSslClientCertInfo extends Class {
HttpSslClientCertInfo() { this.hasGlobalName("_HTTP_SSL_CLIENT_CERT_INFO") }
}

private class HttpSslClientCertInfoInheritingContent extends TaintInheritingContent,
DataFlow::FieldContent
{
HttpSslClientCertInfoInheritingContent() {
this.getAField().getDeclaringType() instanceof HttpSslClientCertInfo and
(
this.getAField().hasName("pCertEncoded") and
this.getIndirectionIndex() = 2
or
this.getAField().hasName("Token") and
this.getIndirectionIndex() = 1
)
}
}
Loading
Loading