chore: remove finding-ID prefixes from code comments
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -46,7 +46,7 @@ export async function authenticateApiRequest(
|
||||
throw new ApiAuthError("Unauthorized", 401);
|
||||
}
|
||||
|
||||
// M14: Deny access when role is missing rather than defaulting to "user"
|
||||
// Deny access when role is missing rather than defaulting to "user"
|
||||
const role = session.user.role;
|
||||
if (!role) {
|
||||
throw new ApiAuthError("Session missing role claim", 401);
|
||||
|
||||
+3
-5
@@ -392,7 +392,7 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
|
||||
session.user.id = token.id as string;
|
||||
session.user.provider = token.provider as string;
|
||||
|
||||
// H1: Always fetch current role and avatar from database to reflect
|
||||
// Always fetch current role from database to reflect
|
||||
// role changes (e.g. demotion) without waiting for JWT expiry
|
||||
const userId = Number(token.id);
|
||||
const currentUser = await getUserById(userId);
|
||||
@@ -409,7 +409,7 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
|
||||
},
|
||||
},
|
||||
secret: config.sessionSecret,
|
||||
// H7: Only trust Host header when explicitly opted in or when NEXTAUTH_URL
|
||||
// Only trust Host header when explicitly opted in or when NEXTAUTH_URL
|
||||
// is set (operator has declared the canonical URL, so Host validation is moot).
|
||||
trustHost: !!process.env.NEXTAUTH_TRUST_HOST || !!process.env.NEXTAUTH_URL,
|
||||
basePath: "/api/auth",
|
||||
@@ -451,10 +451,8 @@ export async function requireAdmin() {
|
||||
*/
|
||||
export function checkSameOrigin(request: NextRequest): NextResponse | null {
|
||||
const origin = request.headers.get("origin");
|
||||
// L1: For mutating requests, require Origin header to be present.
|
||||
// For mutating requests, require Origin header to be present.
|
||||
// Browsers always send Origin on cross-origin POST/PUT/DELETE.
|
||||
// A missing Origin on a mutating request from a cookie-authenticated session
|
||||
// could indicate a non-browser attacker with a stolen cookie.
|
||||
const method = request.method.toUpperCase();
|
||||
const isMutating = method !== "GET" && method !== "HEAD" && method !== "OPTIONS";
|
||||
if (!origin) {
|
||||
|
||||
@@ -108,7 +108,7 @@ export function buildWafHandler(waf: WafSettings, allowWebsocket = false): Recor
|
||||
);
|
||||
}
|
||||
|
||||
// L7: Runtime-validate excluded_rule_ids are positive integers
|
||||
// Runtime-validate excluded_rule_ids are positive integers
|
||||
if (waf.excluded_rule_ids?.length) {
|
||||
const validIds = waf.excluded_rule_ids.filter(
|
||||
(id): id is number => typeof id === "number" && Number.isFinite(id) && id > 0 && Number.isInteger(id)
|
||||
@@ -132,7 +132,7 @@ export function buildWafHandler(waf: WafSettings, allowWebsocket = false): Recor
|
||||
'SecResponseBodyAccess Off',
|
||||
);
|
||||
|
||||
// H5: Validate WAF custom directives — block dangerous engine-level overrides
|
||||
// Block dangerous engine-level overrides in custom directives
|
||||
if (waf.custom_directives?.trim()) {
|
||||
const directives = waf.custom_directives.trim();
|
||||
const forbiddenPatterns = [
|
||||
|
||||
+2
-2
@@ -800,7 +800,7 @@ async function buildProxyRoutes(
|
||||
outpostRoute = {
|
||||
match: [
|
||||
{
|
||||
// M10: Sanitize outpostDomain to prevent path traversal and placeholder injection
|
||||
// Sanitize outpostDomain to prevent path traversal and placeholder injection
|
||||
path: [`/${authentik.outpostDomain.replace(/\.\./g, '').replace(/\{[^}]*\}/g, '').replace(/\/+/g, '/')}/*`]
|
||||
}
|
||||
],
|
||||
@@ -879,7 +879,7 @@ async function buildProxyRoutes(
|
||||
}
|
||||
|
||||
// Structured path prefix rewrite
|
||||
// M9: Sanitize path_prefix to prevent Caddy placeholder injection
|
||||
// Sanitize path_prefix to prevent Caddy placeholder injection
|
||||
if (meta.rewrite?.path_prefix) {
|
||||
const safePrefix = meta.rewrite.path_prefix.replace(/\{[^}]*\}/g, '');
|
||||
if (safePrefix) {
|
||||
|
||||
+1
-2
@@ -30,8 +30,7 @@ function resolveSessionSecret(): string {
|
||||
return DEV_SECRET;
|
||||
}
|
||||
|
||||
// C1: Fail-closed on unrecognized NODE_ENV to prevent silent DEV_SECRET usage
|
||||
// in staging, test, or misconfigured environments.
|
||||
// Fail-closed on unrecognized NODE_ENV to prevent silent DEV_SECRET usage
|
||||
if (!isDevelopment && !isProduction && !secret) {
|
||||
throw new Error(
|
||||
`SESSION_SECRET is required when NODE_ENV="${process.env.NODE_ENV ?? ""}" ` +
|
||||
|
||||
@@ -161,7 +161,7 @@ function insertBatch(rows: typeof trafficEvents.$inferInsert[]): void {
|
||||
|
||||
function purgeOldEntries(): void {
|
||||
const cutoff = Math.floor(Date.now() / 1000) - RETENTION_DAYS * 86400;
|
||||
// M5: Use parameterized query instead of string interpolation
|
||||
// Use parameterized query instead of string interpolation
|
||||
db.run(sql`DELETE FROM traffic_events WHERE ts < ${cutoff}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ export async function createApiToken(
|
||||
createdBy: number,
|
||||
expiresAt?: string
|
||||
): Promise<{ token: ApiToken; rawToken: string }> {
|
||||
// C3: Validate expires_at is a valid ISO 8601 date in the future
|
||||
// Validate expires_at is a valid ISO 8601 date in the future
|
||||
let validatedExpiresAt: string | null = null;
|
||||
if (expiresAt) {
|
||||
const parsed = new Date(expiresAt);
|
||||
|
||||
@@ -12,7 +12,7 @@ export type AuditEvent = {
|
||||
created_at: string;
|
||||
};
|
||||
|
||||
// L6: Escape LIKE metacharacters so user input is treated as literal text
|
||||
// Escape LIKE metacharacters so user input is treated as literal text
|
||||
function escapeLikePattern(input: string): string {
|
||||
return input.replace(/[%_\\]/g, (ch) => `\\${ch}`);
|
||||
}
|
||||
|
||||
+2
-2
@@ -32,7 +32,7 @@ export function encryptSecret(value: string): string {
|
||||
}
|
||||
|
||||
/**
|
||||
* L5: Legacy fallback is time-limited. After the migration grace period,
|
||||
* Legacy fallback is time-limited. After the migration grace period,
|
||||
* the legacy key is no longer tried, forcing re-encryption of old secrets.
|
||||
* Set LEGACY_KEY_CUTOFF_DATE env var to extend/disable (ISO 8601 date or "never").
|
||||
*/
|
||||
@@ -49,7 +49,7 @@ export function decryptSecret(value: string): string {
|
||||
try {
|
||||
return _decryptWithKey(value, deriveKey());
|
||||
} catch (hkdfError: unknown) {
|
||||
// L5: Only fall back to legacy key within the grace period
|
||||
// Only fall back to legacy key within the grace period
|
||||
if (LEGACY_KEY_CUTOFF && new Date() > LEGACY_KEY_CUTOFF) {
|
||||
throw new Error(
|
||||
"[secret] HKDF decryption failed and legacy key grace period has expired. " +
|
||||
|
||||
@@ -213,7 +213,7 @@ function insertBatch(rows: typeof wafEvents.$inferInsert[]): void {
|
||||
|
||||
function purgeOldEntries(): void {
|
||||
const cutoff = Math.floor(Date.now() / 1000) - RETENTION_DAYS * 86400;
|
||||
// M5: Use parameterized query instead of string interpolation
|
||||
// Use parameterized query instead of string interpolation
|
||||
db.run(sql`DELETE FROM waf_events WHERE ts < ${cutoff}`);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user