fix: harden SAC security per audit (0.4.15)

Close audit findings: anti-spoof client IP for login rate limit, JWT/CORS
enforce on startup, SSH host-key verification and sudo via stdin, optional
WinRM HTTPS, SSE httpOnly cookie auth, ingest body limit, ILIKE escaping,
and HMAC API key hashing with legacy SHA-256 fallback.
This commit is contained in:
2026-07-07 19:32:12 +10:00
parent 939fe122c5
commit 80320ae698
29 changed files with 452 additions and 160 deletions
+52
View File
@@ -0,0 +1,52 @@
"""Security bootstrap and API key hashing."""
import hashlib
import pytest
from app.auth.api_key import _legacy_hash_api_key, hash_api_key, verify_api_key_hash
from app.security_bootstrap import validate_security_settings
from app.config import Settings
def test_hash_api_key_uses_hmac(monkeypatch):
monkeypatch.setenv("JWT_SECRET", "unit-test-secret")
from app.config import get_settings
get_settings.cache_clear()
raw = "sac_example_key"
assert hash_api_key(raw) != _legacy_hash_api_key(raw)
assert verify_api_key_hash(raw, hash_api_key(raw))
get_settings.cache_clear()
def test_verify_api_key_hash_accepts_legacy_sha256(monkeypatch):
monkeypatch.setenv("JWT_SECRET", "unit-test-secret")
from app.config import get_settings
get_settings.cache_clear()
raw = "sac_legacy_key"
legacy = hashlib.sha256(raw.encode("utf-8")).hexdigest()
assert verify_api_key_hash(raw, legacy)
get_settings.cache_clear()
def test_validate_security_settings_rejects_weak_jwt():
settings = Settings(
jwt_secret="change-me-in-production",
sac_public_url="https://sac.example.com",
cors_origins="https://sac.example.com",
sac_security_enforce=True,
)
with pytest.raises(RuntimeError, match="JWT_SECRET"):
validate_security_settings(settings)
def test_validate_security_settings_rejects_wildcard_cors(monkeypatch):
settings = Settings(
jwt_secret="strong-secret-value",
sac_public_url="https://sac.example.com",
cors_origins="*",
sac_security_enforce=True,
)
with pytest.raises(RuntimeError, match="CORS_ORIGINS"):
validate_security_settings(settings)