mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 20:42:43 +00:00
Every workflow action is pinned to a commit SHA, dependabot auto-merge is limited to patch and minor updates behind the now-required status checks on main, and the audit, Trivy and ESLint gates block instead of warning. The published image finally carries its build SHA and build timestamp so the version endpoint can prove which commit is running. The API-token HMAC key fails closed under 32 characters, compose pins the database minor and denies privilege escalation, and the changelog drops working-note references in favour of neutral wording.
51 lines
1.5 KiB
TypeScript
51 lines
1.5 KiB
TypeScript
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
|
|
/**
|
|
* Verify HMAC-SHA256 signature for external ingest.
|
|
* Signature format: "sha256=<hex>"
|
|
* The signature is computed over the raw request body using the API token as the key.
|
|
*/
|
|
export function verifyHmacSignature(
|
|
body: string,
|
|
signature: string,
|
|
secret: string,
|
|
): boolean {
|
|
const prefix = "sha256=";
|
|
if (!signature.startsWith(prefix)) return false;
|
|
|
|
const receivedHex = signature.slice(prefix.length);
|
|
const expectedHex = createHmac("sha256", secret).update(body).digest("hex");
|
|
|
|
try {
|
|
return timingSafeEqual(
|
|
Buffer.from(receivedHex, "hex"),
|
|
Buffer.from(expectedHex, "hex"),
|
|
);
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Hash an API token for storage (SHA-256).
|
|
* Requires API_TOKEN_HMAC_KEY env var to be set and at least 32
|
|
* characters long. Fail-closed like the encryption-key loader in
|
|
* `src/lib/crypto.ts`: a weak key throws instead of silently keying
|
|
* every Bearer-token hash off guessable material.
|
|
*/
|
|
const MIN_HMAC_KEY_LENGTH = 32;
|
|
|
|
export function hashToken(token: string): string {
|
|
const key = process.env.API_TOKEN_HMAC_KEY;
|
|
if (!key) {
|
|
throw new Error("API_TOKEN_HMAC_KEY env var must be set");
|
|
}
|
|
if (key.length < MIN_HMAC_KEY_LENGTH) {
|
|
throw new Error(
|
|
`API_TOKEN_HMAC_KEY must be at least ${MIN_HMAC_KEY_LENGTH} characters, got ${key.length}. ` +
|
|
"Generate a strong key with `openssl rand -hex 32` and update the environment before restarting.",
|
|
);
|
|
}
|
|
return createHmac("sha256", key).update(token).digest("hex");
|
|
}
|