feat: harden auth, security headers, SVG sanitization, and pipeline ownership

- Add password strength validation (8+ chars, uppercase, lowercase, number)
- Add username validation rules
- Optimize API key lookup with SHA-256 prefix (O(1) vs O(n) scan)
- Require password change on default admin first login
- Revoke API keys on password change
- Add session cleanup cron (hourly expired session purge)
- Add Permissions-Policy, HSTS, and CSP security headers in production
- Strengthen SVG sanitizer: block XInclude, foreignObject, processing
  instructions, javascript/data/file URI schemes
- Add userId ownership to pipelines with authorization checks
- Add keyPrefix column to api_keys table
- Update integration tests for new auth behavior
This commit is contained in:
Siddharth Kumar Sah
2026-03-24 21:38:06 +08:00
parent 75f38a9fe2
commit 432cc92471
13 changed files with 570 additions and 52 deletions
+3 -1
View File
@@ -9,7 +9,7 @@ import { randomBytes, randomUUID } from "node:crypto";
import type { FastifyInstance, FastifyRequest, FastifyReply } from "fastify";
import { eq, and } from "drizzle-orm";
import { db, schema } from "../db/index.js";
import { hashPassword, requireAuth } from "../plugins/auth.js";
import { hashPassword, computeKeyPrefix, requireAuth } from "../plugins/auth.js";
export async function apiKeyRoutes(app: FastifyInstance): Promise<void> {
// POST /api/v1/api-keys — Generate a new API key
@@ -32,6 +32,7 @@ export async function apiKeyRoutes(app: FastifyInstance): Promise<void> {
// Generate a raw API key: "si_" prefix + 48 random bytes as hex
const rawKey = `si_${randomBytes(48).toString("hex")}`;
const keyHash = await hashPassword(rawKey);
const keyPrefix = computeKeyPrefix(rawKey);
const id = randomUUID();
db.insert(schema.apiKeys)
@@ -39,6 +40,7 @@ export async function apiKeyRoutes(app: FastifyInstance): Promise<void> {
id,
userId: user.id,
keyHash,
keyPrefix,
name,
})
.run();