Fix CRITICAL auth bypass: exact match for login/signup paths
Some checks failed
CI — P2 Drift (Go + Node) / agent (push) Successful in 45s
CI — P2 Drift (Go + Node) / saas (push) Successful in 28s
CI — P3 Alert / test (push) Successful in 24s
CI — P4 Portal / test (push) Successful in 27s
CI — P5 Cost / test (push) Successful in 26s
CI — P6 Run / saas (push) Successful in 25s
CI — P2 Drift (Go + Node) / build-push (push) Failing after 46s
CI — P3 Alert / build-push (push) Failing after 38s
CI — P4 Portal / build-push (push) Failing after 50s
CI — P5 Cost / build-push (push) Failing after 22s
CI — P6 Run / build-push (push) Failing after 1m3s

startsWith('/api/v1/auth/login') allowed any path with that prefix
to bypass authentication (e.g. /api/v1/auth/login-anything).
Changed to exact path match with query string stripping.
Fixed across all 5 products + shared/auth.ts.
This commit is contained in:
2026-03-02 20:35:28 +00:00
parent dac6376fb2
commit be3f37cfdd
6 changed files with 12 additions and 6 deletions

View File

@@ -27,7 +27,8 @@ export function registerAuth(app: FastifyInstance, jwtSecret: string, pool: Pool
if (req.url === '/health' || req.url === '/version') return; if (req.url === '/health' || req.url === '/version') return;
if (req.url.startsWith('/webhooks/')) return; if (req.url.startsWith('/webhooks/')) return;
if (req.url.startsWith('/slack/')) return; if (req.url.startsWith('/slack/')) return;
if (req.url.startsWith('/api/v1/auth/login') || req.url.startsWith('/api/v1/auth/signup')) return; const path = req.url.split('?')[0];
if (path === '/api/v1/auth/login' || path === '/api/v1/auth/signup') return;
const apiKey = req.headers['x-api-key'] as string | undefined; const apiKey = req.headers['x-api-key'] as string | undefined;
const authHeader = req.headers['authorization']; const authHeader = req.headers['authorization'];

View File

@@ -27,7 +27,8 @@ export function registerAuth(app: FastifyInstance, jwtSecret: string, pool: Pool
if (req.url === '/health' || req.url === '/version') return; if (req.url === '/health' || req.url === '/version') return;
if (req.url.startsWith('/webhooks/')) return; if (req.url.startsWith('/webhooks/')) return;
if (req.url.startsWith('/slack/')) return; if (req.url.startsWith('/slack/')) return;
if (req.url.startsWith('/api/v1/auth/login') || req.url.startsWith('/api/v1/auth/signup')) return; const path = req.url.split('?')[0];
if (path === '/api/v1/auth/login' || path === '/api/v1/auth/signup') return;
const apiKey = req.headers['x-api-key'] as string | undefined; const apiKey = req.headers['x-api-key'] as string | undefined;
const authHeader = req.headers['authorization']; const authHeader = req.headers['authorization'];

View File

@@ -27,7 +27,8 @@ export function registerAuth(app: FastifyInstance, jwtSecret: string, pool: Pool
if (req.url === '/health' || req.url === '/version') return; if (req.url === '/health' || req.url === '/version') return;
if (req.url.startsWith('/webhooks/')) return; if (req.url.startsWith('/webhooks/')) return;
if (req.url.startsWith('/slack/')) return; if (req.url.startsWith('/slack/')) return;
if (req.url.startsWith('/api/v1/auth/login') || req.url.startsWith('/api/v1/auth/signup')) return; const path = req.url.split('?')[0];
if (path === '/api/v1/auth/login' || path === '/api/v1/auth/signup') return;
const apiKey = req.headers['x-api-key'] as string | undefined; const apiKey = req.headers['x-api-key'] as string | undefined;
const authHeader = req.headers['authorization']; const authHeader = req.headers['authorization'];

View File

@@ -27,7 +27,8 @@ export function registerAuth(app: FastifyInstance, jwtSecret: string, pool: Pool
if (req.url === '/health' || req.url === '/version') return; if (req.url === '/health' || req.url === '/version') return;
if (req.url.startsWith('/webhooks/')) return; if (req.url.startsWith('/webhooks/')) return;
if (req.url.startsWith('/slack/')) return; if (req.url.startsWith('/slack/')) return;
if (req.url.startsWith('/api/v1/auth/login') || req.url.startsWith('/api/v1/auth/signup')) return; const path = req.url.split('?')[0];
if (path === '/api/v1/auth/login' || path === '/api/v1/auth/signup') return;
const apiKey = req.headers['x-api-key'] as string | undefined; const apiKey = req.headers['x-api-key'] as string | undefined;
const authHeader = req.headers['authorization']; const authHeader = req.headers['authorization'];

View File

@@ -27,7 +27,8 @@ export function registerAuth(app: FastifyInstance, jwtSecret: string, pool: Pool
if (req.url === '/health' || req.url === '/version') return; if (req.url === '/health' || req.url === '/version') return;
if (req.url.startsWith('/webhooks/')) return; if (req.url.startsWith('/webhooks/')) return;
if (req.url.startsWith('/slack/')) return; if (req.url.startsWith('/slack/')) return;
if (req.url.startsWith('/api/v1/auth/login') || req.url.startsWith('/api/v1/auth/signup')) return; const path = req.url.split('?')[0];
if (path === '/api/v1/auth/login' || path === '/api/v1/auth/signup') return;
const apiKey = req.headers['x-api-key'] as string | undefined; const apiKey = req.headers['x-api-key'] as string | undefined;
const authHeader = req.headers['authorization']; const authHeader = req.headers['authorization'];

View File

@@ -27,7 +27,8 @@ export function registerAuth(app: FastifyInstance, jwtSecret: string, pool: Pool
if (req.url === '/health') return; if (req.url === '/health') return;
if (req.url.startsWith('/webhooks/')) return; if (req.url.startsWith('/webhooks/')) return;
if (req.url.startsWith('/slack/')) return; if (req.url.startsWith('/slack/')) return;
if (req.url.startsWith('/api/v1/auth/login') || req.url.startsWith('/api/v1/auth/signup')) return; const path = req.url.split('?')[0];
if (path === '/api/v1/auth/login' || path === '/api/v1/auth/signup') return;
const apiKey = req.headers['x-api-key'] as string | undefined; const apiKey = req.headers['x-api-key'] as string | undefined;
const authHeader = req.headers['authorization']; const authHeader = req.headers['authorization'];