fix(security): fail fast on a missing/placeholder/public LYRA_SECRET_KEY
.env.example shipped a valid, PUBLIC base64 key — if a user didn't replace it, every credential got encrypted with a publicly-known key and everything still "worked," so the footgun was silent. - .env.example now ships an obvious placeholder (CHANGE_ME_generate_with_...) with a "you MUST replace this" note and the openssl hint. - web + worker validate LYRA_SECRET_KEY at startup: missing / placeholder / wrong-length ⇒ loud FATAL banner and refuse to start (web via the Next.js instrumentation hook, worker via _require_secret_key before touching the DB). The old public example key ⇒ a loud WARNING but not fatal, since an existing install may have encrypted its creds under it (rotating needs re-entry). - Validation lives in an edge-safe web/src/lib/secret-key.ts (no node:crypto) so the instrumentation hook bundles for both runtimes; crypto.ts re-exports. - README emphasizes generating a fresh key + keeping it stable. Verified live: worker exits 1 on placeholder/unset before any DB call; web instrumentation throws and refuses to serve on the placeholder. web 138 tests, worker 204/7-skip, tsc clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import uuid
|
||||
|
||||
@@ -6,6 +7,7 @@ import psycopg
|
||||
|
||||
from lyra_worker.claim import claim_next
|
||||
from lyra_worker.config import get_config
|
||||
from lyra_worker.crypto import secret_key_problem
|
||||
from lyra_worker.db import wait_for_db
|
||||
from lyra_worker.discovery import DiscoveryConfig, DiscoveryResult, run_discovery
|
||||
from lyra_worker.library import clear_staging_root
|
||||
@@ -165,7 +167,26 @@ def maybe_run_discovery(conn, sources, browser, config, dcfg, now, last_discover
|
||||
return now if due else last_discover_tick
|
||||
|
||||
|
||||
def _require_secret_key() -> None:
|
||||
"""Fail fast (or warn loudly) on a missing/placeholder/public LYRA_SECRET_KEY before
|
||||
the worker touches any encrypted credential."""
|
||||
problem = secret_key_problem()
|
||||
if problem is None:
|
||||
return
|
||||
msg, fatal = problem
|
||||
banner = "=" * 72
|
||||
if fatal:
|
||||
print(
|
||||
f"\n{banner}\nFATAL: {msg}.\nGenerate one: openssl rand -base64 32\n"
|
||||
f"Then set LYRA_SECRET_KEY in your .env and restart.\n{banner}\n",
|
||||
flush=True,
|
||||
)
|
||||
sys.exit(1)
|
||||
print(f"\n{banner}\nWARNING: {msg}.\n{banner}\n", flush=True)
|
||||
|
||||
|
||||
def run_forever() -> None:
|
||||
_require_secret_key()
|
||||
conn = wait_for_db()
|
||||
clear_staging_root(STAGING_ROOT) # sweep any staging dirs orphaned by a prior crash
|
||||
adapters = build_adapters(get_config(conn))
|
||||
|
||||
Reference in New Issue
Block a user