From 920f32e39e5b6c3fdd94197f89e33e5cbad641bc Mon Sep 17 00:00:00 2001 From: "linear-code[bot]" <222613912+linear-code[bot]@users.noreply.github.com> Date: Sat, 11 Jul 2026 13:44:17 +0000 Subject: [PATCH 1/2] fix(web): resolve false-positive js/insufficient-password-hash in MCP cache key CodeQL's sensitive-data heuristic classifies any identifier containing "oauth" as a password, so the requested OAuth scopes flowing into createHash('sha256') tripped js/insufficient-password-hash. These scopes are not secret; the hash only produced a cache-key segment. Replace it with a base64url encoding of the normalized scope list, which is deterministic, delimiter-safe, and not a cryptographic operation. Generated with [Linear](https://linear.app/sourcebot/issue/SOU-1495/sourcebot-devsourcebot-codeqljsinsufficient-password-hash-high#agent-session-424c6dc8) Co-authored-by: linear-code[bot] <222613912+linear-code[bot]@users.noreply.github.com> --- CHANGELOG.md | 3 +++ .../web/src/ee/features/chat/mcp/mcpToolSets.ts | 17 ++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 429b650f3..5cd84d6d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed +- [EE] Derived the MCP tool-list cache-key segment from requested OAuth scopes without a cryptographic hash, resolving a false-positive `js/insufficient-password-hash` CodeQL alert. [#PLACEHOLDER](https://github.com/sourcebot-dev/sourcebot/pull/PLACEHOLDER) + ## [5.1.0] - 2026-07-10 ### Changed diff --git a/packages/web/src/ee/features/chat/mcp/mcpToolSets.ts b/packages/web/src/ee/features/chat/mcp/mcpToolSets.ts index 38361fe5c..f9832f993 100644 --- a/packages/web/src/ee/features/chat/mcp/mcpToolSets.ts +++ b/packages/web/src/ee/features/chat/mcp/mcpToolSets.ts @@ -4,7 +4,6 @@ import { createLogger, env } from '@sourcebot/shared'; import Ajv from 'ajv'; import { jsonSchema, ToolExecutionOptions } from 'ai'; import type { JSONSchema7, JSONSchema7Definition } from 'json-schema'; -import { createHash } from 'crypto'; import { getExternalMcpErrorLogFields } from './externalMcpError'; import { getMcpFaviconUrl } from '@/features/chat/mcp/utils'; import { __unsafePrisma } from '@/prisma'; @@ -105,15 +104,19 @@ function getMcpToolFailureReason(error: unknown): string { return 'unknown'; } -function getOAuthScopeHash(oauthScopes: string[]): string { +// Builds a deterministic, delimiter-safe segment for the tool-list cache key from +// the requested OAuth scopes. These scopes are not secret; the segment only needs +// to change the cache key when the granted scope set changes. We base64url-encode +// the normalized scope list rather than hashing it: it is collision-free, avoids +// the ':' cache-key delimiter, and keeps a non-security cache-key derivation from +// being misclassified as password hashing (codeql js/insufficient-password-hash). +function getOAuthScopeCacheKeySegment(oauthScopes: string[]): string { if (oauthScopes.length === 0) { return 'none'; } - return createHash('sha256') - .update(Array.from(new Set(oauthScopes)).sort().join('\0')) - .digest('hex') - .slice(0, 16); + const normalized = Array.from(new Set(oauthScopes)).sort().join('\0'); + return Buffer.from(normalized, 'utf8').toString('base64url'); } /** @@ -135,7 +138,7 @@ function getMcpListToolsCacheKey(client: McpToolSet): string { // list cannot be safely shared across users of the same server. client.userId, client.serverId, - getOAuthScopeHash(client.requestedOAuthScopes), + getOAuthScopeCacheKeySegment(client.requestedOAuthScopes), client.serverUpdatedAt.getTime(), ].join(':'); } From d65b1dec82318bd61effcc3e88e343ca93fa017f Mon Sep 17 00:00:00 2001 From: "linear-code[bot]" <222613912+linear-code[bot]@users.noreply.github.com> Date: Sat, 11 Jul 2026 13:44:43 +0000 Subject: [PATCH 2/2] docs: add changelog entry for #1435 Generated with [Linear](https://linear.app/sourcebot/issue/SOU-1495/sourcebot-devsourcebot-codeqljsinsufficient-password-hash-high#agent-session-424c6dc8) Co-authored-by: linear-code[bot] <222613912+linear-code[bot]@users.noreply.github.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cd84d6d7..ee0db71d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Fixed -- [EE] Derived the MCP tool-list cache-key segment from requested OAuth scopes without a cryptographic hash, resolving a false-positive `js/insufficient-password-hash` CodeQL alert. [#PLACEHOLDER](https://github.com/sourcebot-dev/sourcebot/pull/PLACEHOLDER) +- [EE] Derived the MCP tool-list cache-key segment from requested OAuth scopes without a cryptographic hash, resolving a false-positive `js/insufficient-password-hash` CodeQL alert. [#1435](https://github.com/sourcebot-dev/sourcebot/pull/1435) ## [5.1.0] - 2026-07-10