forked from claw/flaskpaste
fix: share PoW HMAC secret across gunicorn workers
get_pow_secret() generated a random secret per process, so challenges signed by worker A failed verification on worker B (~90% failure rate with 2 workers). Persist a file-backed secret to data/.pow_secret using O_EXCL for atomic creation. FLASKPASTE_POW_SECRET env var still takes priority when configured. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -68,8 +68,6 @@ GENERIC_MIME_TYPES = frozenset(
|
||||
}
|
||||
)
|
||||
|
||||
# Runtime PoW secret cache
|
||||
_pow_secret_cache: bytes | None = None
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Anti-flood: dynamic PoW difficulty adjustment
|
||||
@@ -753,14 +751,8 @@ def is_admin() -> bool:
|
||||
|
||||
|
||||
def get_pow_secret() -> bytes:
|
||||
"""Get or generate PoW signing secret."""
|
||||
global _pow_secret_cache
|
||||
configured: str = current_app.config.get("POW_SECRET", "")
|
||||
if configured:
|
||||
return configured.encode()
|
||||
if _pow_secret_cache is None:
|
||||
_pow_secret_cache = secrets.token_bytes(32)
|
||||
return _pow_secret_cache
|
||||
"""Get PoW signing secret from app config."""
|
||||
return current_app.config["POW_SECRET"].encode()
|
||||
|
||||
|
||||
def generate_challenge(difficulty_override: int | None = None) -> dict[str, Any]:
|
||||
|
||||
Reference in New Issue
Block a user