Files
flaskpaste/tests/security/headers_audit.py
Username 97bf955820
Some checks failed
CI / Security Scan (push) Successful in 20s
CI / Lint & Format (push) Failing after 22s
CI / Unit Tests (push) Has been skipped
CI / Security Tests (push) Has been skipped
CI / Advanced Security Tests (push) Has been skipped
CI / Memory Leak Check (push) Has been skipped
CI / SBOM Generation (push) Has been skipped
CI / Build & Push Image (push) Has been skipped
tests: fix ruff lint errors in security tests
2026-01-18 10:04:27 +01:00

109 lines
3.0 KiB
Python

#!/usr/bin/env python3
"""Security headers audit for FlaskPaste.
Verifies all required security headers are present and correctly configured.
"""
import sys
sys.path.insert(0, ".")
from app import create_app
# Required headers and their expected values
REQUIRED_HEADERS = {
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"Content-Security-Policy": "default-src 'none'",
"Referrer-Policy": "strict-origin-when-cross-origin",
"Permissions-Policy": "geolocation=(), microphone=(), camera=()",
"Cache-Control": "no-store, no-cache, must-revalidate",
"Pragma": "no-cache",
}
# Headers that should NOT be present
FORBIDDEN_HEADERS = [
"X-Powered-By",
"Server",
]
# Endpoints to test
TEST_ENDPOINTS = [
("/", "GET", 200),
("/health", "GET", 200),
("/challenge", "GET", 200),
("/nonexistent", "GET", 400), # Error response
]
def run_audit():
"""Run security headers audit."""
print("=" * 60)
print("SECURITY HEADERS AUDIT")
print("=" * 60)
app = create_app("testing")
client = app.test_client()
results = {"passed": 0, "failed": 0, "warnings": 0}
for endpoint, method, _expected_status in TEST_ENDPOINTS:
print(f"\n[{method} {endpoint}]")
print("-" * 40)
if method == "GET":
resp = client.get(endpoint)
elif method == "POST":
resp = client.post(endpoint, data=b"test")
else:
continue
# Check required headers
for header, expected in REQUIRED_HEADERS.items():
actual = resp.headers.get(header, "")
if expected in actual:
print(f"{header}")
results["passed"] += 1
else:
print(f"{header}")
print(f" Expected: {expected}")
print(f" Got: {actual or '(missing)'}")
results["failed"] += 1
# Check forbidden headers
for header in FORBIDDEN_HEADERS:
if header in resp.headers:
print(f"{header} should not be present")
results["warnings"] += 1
else:
print(f" ✓ No {header} header")
results["passed"] += 1
# Check X-Request-ID
if "X-Request-ID" in resp.headers:
print(" ✓ X-Request-ID present")
results["passed"] += 1
else:
print(" ✗ X-Request-ID missing")
results["failed"] += 1
# Summary
print("\n" + "=" * 60)
print("SUMMARY")
print("=" * 60)
print(f" Passed: {results['passed']}")
print(f" Failed: {results['failed']}")
print(f" Warnings: {results['warnings']}")
total = results["passed"] + results["failed"]
if results["failed"] == 0:
print(f"\n{results['passed']}/{total} checks passed")
return 0
else:
print(f"\nFAILED: {results['failed']}/{total} checks failed")
return 1
if __name__ == "__main__":
sys.exit(run_audit())