Security audit: fix IDOR, add rate limiting, HMAC auth, token hashing, XSS sanitization
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 3m22s

Critical: Add ownership checks to all order routes (IDOR fix).
High: Redis rate limiting on auth endpoints, HMAC-signed internal
service calls replacing header-presence-only checks, nh3 HTML
sanitization on ghost_sync and product import, internal auth on
market API endpoints, SHA-256 hashed OAuth grant/code tokens.
Medium: SECRET_KEY production guard, AP signature enforcement,
is_admin param removal, cart_sid validation, SSRF protection on
remote actor fetch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-26 13:30:27 +00:00
parent 404449fcab
commit c015f3f02f
27 changed files with 607 additions and 33 deletions

View File

@@ -77,7 +77,13 @@ def create_base_app(
configure_logging(name)
app.secret_key = os.getenv("SECRET_KEY", "dev-secret-key-change-me-777")
secret_key = os.getenv("SECRET_KEY")
if not secret_key:
env = os.getenv("ENVIRONMENT", "development")
if env in ("production", "staging"):
raise RuntimeError("SECRET_KEY environment variable must be set in production")
secret_key = "dev-secret-key-change-me-777"
app.secret_key = secret_key
# Per-app first-party session cookie (no shared domain — avoids Safari ITP)
app.config["SESSION_COOKIE_NAME"] = f"{name}_session"
@@ -192,11 +198,14 @@ def create_base_app(
from sqlalchemy import select
from shared.db.session import get_account_session
from shared.models.oauth_grant import OAuthGrant
from shared.models.oauth_grant import OAuthGrant, hash_token
try:
token_h = hash_token(grant_token)
async with get_account_session() as s:
grant = await s.scalar(
select(OAuthGrant).where(OAuthGrant.token == grant_token)
select(OAuthGrant).where(
(OAuthGrant.token_hash == token_h) | (OAuthGrant.token == grant_token)
)
)
valid = grant is not None and grant.revoked_at is None
except Exception: