Owner bearer token was compared with === / !==, which short-circuits on the first differing byte and leaks token length+prefix via response timing (security-sweep-2026-06-01.md). New timingSafeStrEqual (crypto.timingSafeEqual with a length pre-check so it never throws on length mismatch); wired into both owner.js and agent_auth.js. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
20 lines
613 B
JavaScript
20 lines
613 B
JavaScript
import { timingSafeStrEqual } from './safe_compare.js';
|
|
|
|
export function ownerOnly(req, res, next) {
|
|
const expected = process.env.OWNER_TOKEN;
|
|
if (!expected) {
|
|
return res.status(500).json({
|
|
error: { code: 'no_owner_token', message: 'OWNER_TOKEN not configured' }
|
|
});
|
|
}
|
|
const auth = req.headers.authorization || '';
|
|
const [scheme, token] = auth.split(' ');
|
|
if (scheme !== 'Bearer' || !timingSafeStrEqual(token, expected)) {
|
|
return res.status(401).json({
|
|
error: { code: 'unauthorized', message: 'invalid token' }
|
|
});
|
|
}
|
|
req.actor = { kind: 'user', id: null };
|
|
next();
|
|
}
|