48 lines
2.1 KiB
TypeScript
48 lines
2.1 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { readFileSync } from "node:fs";
|
|
import { resolve } from "node:path";
|
|
|
|
/**
|
|
* PII-protection regression test for AuthService.
|
|
*
|
|
* Verifies that no `console.*` call remains in the file (those would
|
|
* bypass the redact-paths Pino pipeline) and that we do not log
|
|
* raw email / password / token / sessionToken fields through webLogger.
|
|
*/
|
|
describe("AuthService PII discipline", () => {
|
|
const SOURCE = readFileSync(resolve(__dirname, "AuthService.ts"), "utf8");
|
|
|
|
it("contains no live console.* call sites", () => {
|
|
const liveConsole = SOURCE.split("\n").filter((line, idx, all) => {
|
|
if (!/console\.(log|error|warn|info|debug)\s*\(/.test(line)) return false;
|
|
const trimmed = line.trimStart();
|
|
if (trimmed.startsWith("//") || trimmed.startsWith("*")) return false;
|
|
const prev = idx > 0 ? all[idx - 1].trim() : "";
|
|
if (/eslint-disable-next-line[^\n]*no-console/.test(prev)) return false;
|
|
if (/eslint-disable-line[^\n]*no-console/.test(line)) return false;
|
|
return true;
|
|
});
|
|
expect(liveConsole).toEqual([]);
|
|
});
|
|
|
|
it("never passes plaintext email / password / token / sessionToken as authLogger fields", () => {
|
|
// Scan property KEYS only (not values like `Boolean(token)` inside helpers).
|
|
const pattern = /authLogger\.(info|warn|error|debug)\s*\(\s*\{([\s\S]*?)\}/g;
|
|
const forbiddenKeys = ["email", "password", "sessionToken", "token", "passwordHash", "rawPassword"];
|
|
const offenders: string[] = [];
|
|
let match: RegExpExecArray | null;
|
|
while ((match = pattern.exec(SOURCE)) !== null) {
|
|
const objContent = match[2];
|
|
for (const key of forbiddenKeys) {
|
|
const keyRe = new RegExp(`(^|[\\s,{])${key}\\s*:`, "m");
|
|
if (keyRe.test(objContent)) offenders.push(`key "${key}" in ${match[0].slice(0, 80)}...`);
|
|
}
|
|
}
|
|
expect(offenders, `authLogger must not log PII fields: ${offenders.join("; ")}`).toEqual([]);
|
|
});
|
|
|
|
it("uses createScopedLogger('auth') for structured logging", () => {
|
|
expect(SOURCE).toMatch(/createScopedLogger\(\s*["']auth["']\s*\)/);
|
|
});
|
|
});
|