Skip to content

fix: Replace SHA-1 with SHA-256 in getHash() (SDL compliance, CWE-327) - #140

Merged
ag-ramachandran merged 2 commits into
mainfrom
copilot/sm04514-remove-sha1-hashing
Mar 31, 2026
Merged

fix: Replace SHA-1 with SHA-256 in getHash() (SDL compliance, CWE-327)#140
ag-ramachandran merged 2 commits into
mainfrom
copilot/sm04514-remove-sha1-hashing

Conversation

Copilot AI commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

SHA-1 is cryptographically broken and banned by Microsoft SDL standards. getHash() in src/extension/utils.ts used createHash('sha1') to generate AppInsights connection identifiers, triggering security finding SM04514 (js/weak-hashes).

Change

  • src/extension/utils.ts — swap algorithm identifier from sha1 to sha256:
 export function getHash(value: string) {
-    return createHash('sha1').update(value).digest('hex');
+    return createHash('sha256').update(value).digest('hex');
 }

Compatibility

The sole consumer (appInsights/index.ts) uses the hash as an internal string key — stored in VS Code Memento and SecretStorage, compared with ===, used as a Map key. No length constraints exist anywhere in the call chain (SHA-256 output is 64 hex chars vs. SHA-1's 40).

Existing AppInsights connections stored with SHA-1-based IDs will become orphaned after this change; users will need to re-add them once. The existing error path ('Failed to load secrets from saved information') handles this gracefully.

Original prompt

Security Bug: [SM04514] Weak Hashes — SHA-1 usage violates Microsoft SDL standards

Vulnerability Details

  • Query Id: js/weak-hashes (version: 0.1.470)
  • Severity: Important
  • Precision: High
  • CWE: CWE-327 (Use of a Broken or Risky Cryptographic Algorithm)
  • File: src/extension/utils.ts, Line 136, Column 23-29
  • Commit: aef3614bd9ef8b38fdcb864f481e72274e3c07b0

Root Cause

The getHash() function in src/extension/utils.ts at line 136 uses createHash('sha1') from Node.js's crypto module. SHA-1 is cryptographically broken and explicitly unapproved by Microsoft SDL standards.

// Current vulnerable code (src/extension/utils.ts line 135-137)
export function getHash(value: string) {
    return createHash('sha1').update(value).digest('hex');
}

Impact Analysis — Where getHash() is called

The function is imported and used in exactly one consumer file:

File: src/extension/kusto/connections/appInsights/index.ts (line 2 & 31)

import { getHash } from '../../../utils';
// ...
const id = getHash(`${connection.appId}:${connection.appKey}`);

It hashes AppInsights credentials (appId + appKey) to generate a connection identifier (id field of AppInsightsConnectionInfo).

How the id is used downstream (critical for regression analysis)

  1. AppInsightsConnectionInfo.id — A readonly string field (defined in src/extension/kusto/connections/types.ts line 12). The id type is string — there are NO length constraints anywhere.

  2. storage.ts — Connection cache storage (src/extension/kusto/connections/storage.ts):

    • updateConnectionCache() (line 60-86): Uses info.id as a Map key via connectionsToSave.set(item.id, item) and connectionsToSave.delete(options.info.id) — works with any string length.
    • getCachedConnections() (line 52): Returns IConnectionInfo[] from memento — no length constraints on id.
  3. storage.ts — Secret storage (src/extension/kusto/connections/storage.ts):

    • getConnectionSecret(key: string) (line 41): Calls secretStorage.get(key) — VS Code SecretStorage accepts any string key.
    • addConnectionSecret(key: string, secret: string) (line 45): Calls secretStorage.store(key, secret) — no length constraints.
    • removeConnectionSecret(key: string) (line 48): Calls secretStorage.delete(key) — no length constraints.
  4. baseConnection.ts — Schema cache (src/extension/kusto/connections/baseConnection.ts):

    • schemaCacheId (line 48-49): Uses this.info.id.toLowerCase() — works with any string.
    • getSchema() (line 54): Same pattern — no length constraints.
  5. appInsights/index.ts — Connection lookup (line 27):

    • getCachedConnections().find((item) => item.id === info.appInsightsId) — exact string equality, works regardless of hash length.
  6. types.ts — Display info (line 36-48):

    • getDisplayInfo() uses info.displayName || info.id — fallback display, works with any string.

Regression Risk Assessment

  • Hash length change: SHA-1 produces 40 hex chars, SHA-256 produces 64 hex chars. All downstream consumers use the id as a generic string key — no truncation, no fixed-length fields, no database columns.
  • Existing stored connections: When the hash algorithm changes, previously saved AppInsights connections (stored with SHA-1 based ids in VS Code's SecretStorage and Memento) will not match the new SHA-256 based ids. However, looking at the flow, the id is recomputed from appId:appKey each time connectionInfofrom() is called. When a user reconnects, a new id will be generated. Old orphaned entries in storage will be harmless (never looked up again).
  • No persistence across sessions that depends on hash stability: The getCachedConnections().find((item) => item.id === info.appInsightsId) lookup on line 27 only works if the id was previously saved with the same algorithm. After the fix, users will need to re-add AppInsights connections (a one-time action). This is an acceptable trade-off for a security fix.
  • No external API contracts: The hash is purely internal to the extension — not exposed to any external APIs, file formats, or network protocols.

Required Fix

Replace 'sha1' with 'sha256' in the getHash() function in src/extension/utils.ts:

export function getHash(value: string) {
    return createHash('sha256').update(value).digest('hex');
}

This is a single-line change. The createHash API from Node.js crypto module supports 'sha256' as a drop-in replacement — same interface, same return type (Hash), same .update().digest('hex') chain.

Corner Cases Verified

Corner Case SHA-1 → SHA-256 Impact Production Risk
Hash output length (40 → 64 hex chars) All consumers use string type, no fixed-width checks anywhere ✅ Zero risk
Existing stored connections (old SHA-1 ids in ...

This pull request was created from Copilot chat.

Copilot AI changed the title [WIP] Fix weak hashes by removing SHA-1 usage fix: Replace SHA-1 with SHA-256 in getHash() (SDL compliance, CWE-327) Mar 31, 2026
Copilot AI requested a review from tanmaya-panda1 March 31, 2026 07:27
@tanmaya-panda1
tanmaya-panda1 marked this pull request as ready for review March 31, 2026 07:34
@ag-ramachandran
ag-ramachandran merged commit 5278d4e into main Mar 31, 2026
3 checks passed
@ag-ramachandran
ag-ramachandran deleted the copilot/sm04514-remove-sha1-hashing branch March 31, 2026 08:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants