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:
user
2026-02-23 21:32:06 +01:00
parent ca1cbd6e73
commit e7c278be0d
3 changed files with 33 additions and 12 deletions

View File

@@ -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]: