| |
| |
| |
| |
| |
| |
| |
| |
|
|
| const KNOWN_WEAK_SECRETS = [ |
| "omniroute-default-secret-change-me", |
| "change-me-to-a-long-random-secret", |
| "endpoint-proxy-api-key-secret", |
| "change-me-storage-encryption-key", |
| "your-secret-here", |
| "secret", |
| "password", |
| "changeme", |
| ]; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| const SECRET_RULES = [ |
| { |
| name: "JWT_SECRET", |
| minLength: 32, |
| required: true, |
| description: "JWT signing secret for dashboard authentication", |
| generateHint: "openssl rand -base64 48", |
| }, |
| { |
| name: "API_KEY_SECRET", |
| minLength: 16, |
| required: true, |
| description: "HMAC secret for API key CRC generation", |
| generateHint: "openssl rand -hex 32", |
| }, |
| ]; |
|
|
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| export function validateSecrets() { |
| const errors = []; |
| const warnings = []; |
|
|
| for (const rule of SECRET_RULES) { |
| const value = process.env[rule.name]; |
|
|
| |
| if (!value || value.trim() === "") { |
| if (rule.required) { |
| errors.push({ |
| name: rule.name, |
| issue: `Required environment variable "${rule.name}" is not set.`, |
| hint: `Generate with: ${rule.generateHint}`, |
| }); |
| } |
| continue; |
| } |
|
|
| |
| if (value.length < rule.minLength) { |
| errors.push({ |
| name: rule.name, |
| issue: `"${rule.name}" is too short (${value.length} chars, minimum ${rule.minLength}).`, |
| hint: `Generate with: ${rule.generateHint}`, |
| }); |
| continue; |
| } |
|
|
| |
| if (KNOWN_WEAK_SECRETS.includes(value.toLowerCase())) { |
| warnings.push({ |
| name: rule.name, |
| issue: `"${rule.name}" appears to use a default/weak value. Please generate a strong secret.`, |
| }); |
| } |
| } |
|
|
| return { |
| valid: errors.length === 0, |
| errors, |
| warnings, |
| }; |
| } |
|
|
| |
| |
| |
| |
| |
| export function enforceSecrets(logger = console) { |
| const result = validateSecrets(); |
|
|
| |
| for (const w of result.warnings) { |
| logger.warn(`β οΈ [SECURITY] ${w.issue}`); |
| } |
|
|
| |
| if (!result.valid) { |
| logger.error(""); |
| logger.error("βββββββββββββββββββββββββββββββββββββββββββββββββββ"); |
| logger.error(" β SECURITY: Missing required secrets"); |
| logger.error("βββββββββββββββββββββββββββββββββββββββββββββββββββ"); |
| for (const e of result.errors) { |
| logger.error(` β’ ${e.issue}`); |
| logger.error(` β ${e.hint}`); |
| } |
| logger.error(""); |
| logger.error(" Set these in your .env file or environment."); |
| logger.error(" See .env.example for reference."); |
| logger.error("βββββββββββββββββββββββββββββββββββββββββββββββββββ"); |
| logger.error(""); |
| process.exit(1); |
| } |
| } |
|
|