Repository navigation
fix(security): match cookie domains by suffix, not substring (CodeQL #860/#861) - #11429
Merged
diegosouzapw merged 1 commit intoAug 24, 2026
Merged
Conversation
CodeQL js/incomplete-url-substring-sanitization, alerts #860 and #861: volcengineConsoleAutoLogin accepted any cookie whose `domain` merely *contained* "volcengine.com". That check is an authorization decision, not a string test. The console auto-login harvests `digest`, `AccountID`, `csrfToken` and `userInfo` out of the Playwright context and persists them as the operator's Volcengine credentials, so a cookie set by `volcengine.com.attacker.tld` — or `notvolcengine.com` — was captured and stored as a provider connection. Add `matchesCookieDomain()` (open-sse/utils/cookieDomain.ts): exact host or dot-boundary suffix, leading dots and case normalized on both sides, failing closed on an empty expected domain. Same shape as the existing `isAdobeCookieDomain` in adobeFireflyBrowserLogin.ts, which already got this right. While sweeping the class, inAppLoginService's cookie capture had the identical weakness — `c.domain.includes(domain.replace(/^\./, ""))` — with the identical consequence: a look-alike host's cookie stored as the operator's credential. CodeQL did not flag it because the expected domain comes from TOKEN_EXTRACTION_CONFIGS rather than a literal. Both callsites now share the helper. tests/unit/volcengine-cookie-domain-suffix.test.ts — 5 tests, red before the fix, covering the real domains, seven look-alikes, empty/missing input, and the config-supplied path.
This was referenced Aug 24, 2026
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…uzapw#11429) CodeQL js/incomplete-url-substring-sanitization, alerts diegosouzapw#860 and diegosouzapw#861: volcengineConsoleAutoLogin accepted any cookie whose `domain` merely *contained* "volcengine.com". That check is an authorization decision, not a string test. The console auto-login harvests `digest`, `AccountID`, `csrfToken` and `userInfo` out of the Playwright context and persists them as the operator's Volcengine credentials, so a cookie set by `volcengine.com.attacker.tld` — or `notvolcengine.com` — was captured and stored as a provider connection. Add `matchesCookieDomain()` (open-sse/utils/cookieDomain.ts): exact host or dot-boundary suffix, leading dots and case normalized on both sides, failing closed on an empty expected domain. Same shape as the existing `isAdobeCookieDomain` in adobeFireflyBrowserLogin.ts, which already got this right. While sweeping the class, inAppLoginService's cookie capture had the identical weakness — `c.domain.includes(domain.replace(/^\./, ""))` — with the identical consequence: a look-alike host's cookie stored as the operator's credential. CodeQL did not flag it because the expected domain comes from TOKEN_EXTRACTION_CONFIGS rather than a literal. Both callsites now share the helper. tests/unit/volcengine-cookie-domain-suffix.test.ts — 5 tests, red before the fix, covering the real domains, seven look-alikes, empty/missing input, and the config-supplied path. Co-authored-by: Xiangzhe <bakryun0718@proton.me>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes CodeQL #860 and #861 (
js/incomplete-url-substring-sanitization, High) inopen-sse/services/volcengineConsoleAutoLogin.ts.Not a false positive
Unlike the
js/insufficient-password-hashalerts this repo routinely dismisses, CodeQL is describing exactly what the code does:That check is an authorization decision, not a string test. The console auto-login harvests
digest,AccountID,csrfTokenanduserInfoout of the Playwright context and persists them as the operator's Volcengine credentials. A cookie set byvolcengine.com.attacker.tld— ornotvolcengine.com, ormyvolcengine.com— passed that filter and was stored as a provider connection.Both flagged lines (621 and 766) are the same predicate: the capture loop and the timeout diagnostics.
Fix
New
matchesCookieDomain()inopen-sse/utils/cookieDomain.ts: exact host or dot-boundary suffix, leading dots (the RFC 6265 spelling) and case normalized on both sides, failing closed on an empty expected domain.This is not a new idea in the codebase —
isAdobeCookieDomain()inadobeFireflyBrowserLogin.tsalready does exactly this for the Adobe login flow. The helper generalizes that shape so the next browser-login service does not have to rediscover it.One finding CodeQL did not report
Sweeping the class turned up the identical weakness in
inAppLoginService.ts:Same code path (Playwright cookie capture → stored operator credential), same consequence. CodeQL missed it because the expected domain comes from
TOKEN_EXTRACTION_CONFIGSinstead of a literal, so the query's constant-string heuristic never fired. Both callsites now share the helper.Flagging it explicitly because it widens the diff past the two alerts you asked about — it is one file and one line, and leaving the same hole open next door after fixing this one seemed worse than the extra scope.
Validation
tests/unit/volcengine-cookie-domain-suffix.test.ts— 5 tests, red before the fix:volcengine.com,.volcengine.com,console.volcengine.com, uppercase, whitespace-padded)volcengine.com.attacker.tld,notvolcengine.com,volcengine.company,volcengine.com.br, …)undefineddomain rejected instead of throwingmatchesCookieDomaindirectly), including failing closed when the expected domain is missing or just"."Sibling sweep and gates, hermetic (
env -u OMNIROUTE_API_KEY):tests/unit/services/volcengine-console-auto-login.test.ts+tests/unit/tokenExtractionConfig.test.ts— 46/46tests/unit/in-app-login-service.test.ts— 2/2typecheck:core— exit 0, no outputprettier --check— clean;eslint— the only two errors are the pre-existingno-explicit-anypair already frozen ineslint-suppressions.json(count: 2, unchanged — the diff adds and removes noany)check:cycles,check:tracked-artifacts— PASS