Lines 8-48javascript
8// password with SHA1/SHA256 to produce the handshake response. They are NOT
9// at-rest password storage, and the algorithms cannot be changed without breaking
10// authentication against a real MySQL server.
12// CodeQL's `js/insufficient-password-hash` query flags these as a false positive
13// (it cannot distinguish a protocol challenge-response from credential storage).
14// These alerts are dismissed ("won't fix") in code scanning. Note that neither
15// inline `// codeql[...]` comments (github/codeql#11427) nor a config `paths-ignore`
16// can suppress them in code: inline comments are not honored, and paths-ignore does
17// not exclude a file that is imported by analyzed code (wire.ts imports this module).
18// The js/insufficient-password-hash rule therefore stays active repo-wide, so it
19// still protects real password storage (e.g. the PBKDF2 hashing in
20// packages/core/src/services/user.service.ts) and any future insecure additions.
21import { createHash } from 'node:crypto';
23 * Compute mysql_native_password response:
24 * SHA1(password) XOR SHA1(seed + SHA1(SHA1(password)))
27export function nativePasswordHash(password, seed) {
28 const sha1 = (data) => createHash('sha1').update(data).digest();
29 const pw = Buffer.from(password, 'utf8');
30 const hash1 = sha1(pw); // SHA1(password)
LowWeak Crypto
Package source references weak cryptographic algorithms.
dist/database/mysql/auth-scramble.jsView on unpkg · L28 31 const hash2 = sha1(hash1); // SHA1(SHA1(password))
32 const combined = Buffer.concat([seed, hash2]); // seed + SHA1(SHA1(password))
33 const hash3 = sha1(combined); // SHA1(seed + SHA1(SHA1(password)))
34 // XOR hash1 with hash3
35 const result = Buffer.allocUnsafe(20);
36 for (let i = 0; i < 20; i++) {
37 result[i] = hash1[i] ^ hash3[i];
42 * Compute caching_sha2_password challenge response:
43 * XOR(SHA256(password), SHA256(SHA256(SHA256(password)) + seed))
45 * An empty password yields an empty (zero-length) response, matching the
46 * MySQL client protocol — the server treats an empty scramble as "no password".