False negative in go/email-injection for password reset links built from Forwarded / X-Forwarded-Host
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 45/100
Research direction
Start at go/email-injection and trace how its source-to-sink flow handles values moved through custom structs, event fields, and notification helpers. Compare this with the described Forwarded/X-Forwarded-Host to password-reset-link path; done means the query covers the indirect flow and avoids the reported false negative.
Written by the indexing model from the issue text.
Description
Hi team,
I think I found a false negative in go/email-injection.
I ran into this while looking at ZITADEL's CVE-2025-64101 / GHSA-mwmh-7px9-4c23. The vulnerable flow is:
- host data comes from
Forwarded/X-Forwarded-Host - it is stored in a request/domain context object
- that value is later carried through an event / notification path
- and eventually used to build a password reset link that gets emailed to the user
Very roughly, it looks like this:
hostFromHeader = r.Header.Get(header)
if host == "" {
host = hostFromHeader
}
TriggeredAtOrigin: http.DomainContext(ctx).Origin()
url = login.InitPasswordLink(http_utils.DomainContext(ctx).Origin(), user.ID, code, user.ResourceOwner, authRequestID)
The upstream fix sanitizes the host before storing it in the domain context, so this seems like a real missed case, not just a noisy benchmark result.
My guess is that the source side is already covered well enough, since net/http.Request.Header is modeled as remote input. The gap seems to be later in the flow, once the value moves through custom structs / event fields / notification helpers before it becomes part of email content.
I think this pattern is fairly common in real Go code. Password reset and verification links are often built indirectly through app-specific context and mailer abstractions, not directly inside a modeled mail API call.
For comparison, Semgrep did flag this codebase, but only with a broader rule about request-derived origin/host usage. It was not precise, but the general idea may still be useful here: request-header-derived host/origin values that later become user-facing links in emails probably deserve better coverage.
A reasonable fix might be improving go/email-injection so flow is preserved better through custom carrier objects and “build link first, send email later” patterns.
- Dominant language
- CodeQL
- Stars
- 10.1k
- Forks
- 2.1k
- Avg merge
- 2d 16h
- Merged PRs (30d)
- 143
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from github/codeql
-
agentic-workflows
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
-
false-positive javascript
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
C#: cs/simplifiable-boolean-expression false positive on Nullable<bool> compared with a literal Open
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
false-positive
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Similar issues
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
canonical/paas-charm#368 · 1 comment ·
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
palladius/rails8-app-on-gcp#142 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
StevenBlack/hosts#3256 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
corsairdev/corsair#1764 ·
-
oblt-aw/detector/security
Difficulty 2/5 1-3 hours Newbie friendliness 70/100