chore: upgrade Node.js runtime to v24 across codebase #419

Merged
jason.woltje merged 438 commits from fix/auth-frontend-remediation into main 2026-02-17 01:04:47 +00:00
2 changed files with 101 additions and 2 deletions
Showing only changes of commit 05ee6303c2 - Show all commits

View File

@@ -609,5 +609,94 @@ describe("AuthService", () => {
await expect(service.verifySession("any-token")).rejects.toThrow("Database connection lost");
});
it("should redact Bearer tokens from logged error messages", async () => {
const auth = service.getAuth();
const errorWithToken = new Error(
"Request failed: Bearer eyJhbGciOiJIUzI1NiJ9.secret-payload in header"
);
const mockGetSession = vi.fn().mockRejectedValue(errorWithToken);
auth.api = { getSession: mockGetSession } as any;
const loggerError = vi.spyOn(service["logger"], "error");
await expect(service.verifySession("any-token")).rejects.toThrow();
expect(loggerError).toHaveBeenCalledWith(
"Session verification failed due to unexpected error",
expect.stringContaining("Bearer [REDACTED]")
);
expect(loggerError).toHaveBeenCalledWith(
"Session verification failed due to unexpected error",
expect.not.stringContaining("eyJhbGciOiJIUzI1NiJ9")
);
});
it("should redact Bearer tokens from error stack traces", async () => {
const auth = service.getAuth();
const errorWithToken = new Error("Something went wrong");
errorWithToken.stack =
"Error: Something went wrong\n at fetch (Bearer abc123-secret-token)\n at verifySession";
const mockGetSession = vi.fn().mockRejectedValue(errorWithToken);
auth.api = { getSession: mockGetSession } as any;
const loggerError = vi.spyOn(service["logger"], "error");
await expect(service.verifySession("any-token")).rejects.toThrow();
expect(loggerError).toHaveBeenCalledWith(
"Session verification failed due to unexpected error",
expect.stringContaining("Bearer [REDACTED]")
);
expect(loggerError).toHaveBeenCalledWith(
"Session verification failed due to unexpected error",
expect.not.stringContaining("abc123-secret-token")
);
});
it("should warn when a non-Error string value is thrown", async () => {
const auth = service.getAuth();
const mockGetSession = vi.fn().mockRejectedValue("string-error");
auth.api = { getSession: mockGetSession } as any;
const loggerWarn = vi.spyOn(service["logger"], "warn");
const result = await service.verifySession("any-token");
expect(result).toBeNull();
expect(loggerWarn).toHaveBeenCalledWith(
"Session verification received non-Error thrown value",
"string-error"
);
});
it("should warn with JSON when a non-Error object is thrown", async () => {
const auth = service.getAuth();
const mockGetSession = vi.fn().mockRejectedValue({ code: "ERR_UNKNOWN" });
auth.api = { getSession: mockGetSession } as any;
const loggerWarn = vi.spyOn(service["logger"], "warn");
const result = await service.verifySession("any-token");
expect(result).toBeNull();
expect(loggerWarn).toHaveBeenCalledWith(
"Session verification received non-Error thrown value",
JSON.stringify({ code: "ERR_UNKNOWN" })
);
});
it("should not warn for expected auth errors (Error instances)", async () => {
const auth = service.getAuth();
const mockGetSession = vi.fn().mockRejectedValue(new Error("Invalid token provided"));
auth.api = { getSession: mockGetSession } as any;
const loggerWarn = vi.spyOn(service["logger"], "warn");
const result = await service.verifySession("bad-token");
expect(result).toBeNull();
expect(loggerWarn).not.toHaveBeenCalled();
});
});
});

View File

@@ -139,14 +139,24 @@ export class AuthService {
if (!isExpectedAuthError) {
// Infrastructure or unexpected — propagate as 500
const safeMessage = (error.stack ?? error.message).replace(
/Bearer\s+\S+/gi,
"Bearer [REDACTED]"
);
this.logger.error(
"Session verification failed due to unexpected error",
error.stack ?? error.message
safeMessage
);
throw error;
}
}
// Non-Error thrown values or expected auth errors
// Non-Error thrown values — log for observability, treat as auth failure
if (!(error instanceof Error)) {
this.logger.warn(
"Session verification received non-Error thrown value",
typeof error === "object" ? JSON.stringify(error) : String(error),
);
}
return null;
}
}