"""HTTP hardening, error disclosure, and template escaping."""
from app.app import nl2br
class TestSecurityHeaders:
def test_core_headers_are_present(self, client):
headers = client.get('/auth/login').headers
assert headers['X-Content-Type-Options'] == 'nosniff'
assert headers['X-Frame-Options'] == 'DENY'
assert headers['Referrer-Policy'] == 'strict-origin-when-cross-origin'
assert 'frame-ancestors' in headers['Content-Security-Policy']
def test_deprecated_xss_auditor_header_is_not_sent(self, client):
"""X-XSS-Protection was removed: deprecated, and harmful in its
last implementations."""
assert 'X-XSS-Protection' not in client.get('/auth/login').headers
def test_csp_does_not_allow_inline_script(self, client):
"""SEC-WEB-001, closed: inline scripts are authorised by a
per-request nonce instead."""
csp = client.get('/auth/login').headers['Content-Security-Policy']
script_src = [d for d in csp.split(';') if d.strip().startswith('script-src')][0]
assert "'unsafe-inline'" not in script_src
assert "'nonce-" in script_src
class TestErrorDisclosure:
def test_health_reports_status_without_the_driver_message(self, app, client):
"""/health is unauthenticated. Driver exceptions routinely carry the
host, database name and user of the connection string."""
from app.extensions import db
def boom(*args, **kwargs):
raise RuntimeError(
'FATAL: password authentication failed for user "app" '
'host=db.internal port=5432'
)
original = db.session.execute
db.session.execute = boom
try:
response = client.get('/health')
finally:
db.session.execute = original
assert response.status_code == 503
body = response.get_data(as_text=True)
assert response.get_json()['database'] == 'error'
for leaked in ('password', 'db.internal', '5432', 'FATAL'):
assert leaked not in body, f'{leaked!r} leaked through /health'
def test_health_reports_healthy_when_the_database_answers(self, client):
response = client.get('/health')
assert response.status_code == 200
assert response.get_json()['database'] == 'connected'
class TestTemplateEscaping:
def test_nl2br_escapes_markup(self, app):
"""Markup('
'.join(...)) marked attacker text as safe.
Markup('
').join(...) escapes each segment first."""
with app.app_context():
rendered = str(nl2br('\nsecond'))
assert '