Files
securelens-backend/tests/test_headers.py
2026-04-07 18:13:43 +05:30

95 lines
3.4 KiB
Python

from unittest.mock import MagicMock
import pytest
from app.services.scanner.headers import HeaderScanner
scanner = HeaderScanner()
def _make_response(headers: dict) -> MagicMock:
response = MagicMock()
response.headers = headers
return response
@pytest.mark.asyncio
async def test_detects_all_missing_headers():
response = _make_response({})
issues = await scanner.scan("https://example.com", response)
issue_texts = [i.issue for i in issues]
assert any("Content-Security-Policy" in t for t in issue_texts)
assert any("X-Frame-Options" in t for t in issue_texts)
assert any("X-Content-Type-Options" in t for t in issue_texts)
assert any("Referrer-Policy" in t for t in issue_texts)
assert any("Permissions-Policy" in t for t in issue_texts)
assert any("Cache-Control" in t for t in issue_texts)
assert any("COOP" in t for t in issue_texts)
assert any("CORP" in t for t in issue_texts)
assert any("COEP" in t for t in issue_texts)
@pytest.mark.asyncio
async def test_detects_unsafe_inline_csp():
response = _make_response({
"Content-Security-Policy": "default-src 'self' 'unsafe-inline'",
"X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff",
"Referrer-Policy": "strict-origin",
"Permissions-Policy": "camera=()",
"Cache-Control": "no-store",
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Resource-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
})
issues = await scanner.scan("https://example.com", response)
assert any("unsafe-inline" in i.issue for i in issues)
@pytest.mark.asyncio
async def test_detects_unsafe_eval_csp():
response = _make_response({
"Content-Security-Policy": "default-src 'self' 'unsafe-eval'",
"X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff",
"Referrer-Policy": "strict-origin",
"Permissions-Policy": "camera=()",
"Cache-Control": "no-store",
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Resource-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
})
issues = await scanner.scan("https://example.com", response)
assert any("unsafe-eval" in i.issue for i in issues)
@pytest.mark.asyncio
async def test_detects_server_disclosure():
response = _make_response({"Server": "Apache/2.4.41"})
issues = await scanner.scan("https://example.com", response)
assert any("Server header" in i.issue for i in issues)
@pytest.mark.asyncio
async def test_detects_x_powered_by():
response = _make_response({"X-Powered-By": "Express"})
issues = await scanner.scan("https://example.com", response)
assert any("X-Powered-By" in i.issue for i in issues)
@pytest.mark.asyncio
async def test_no_issues_with_all_headers():
response = _make_response({
"Content-Security-Policy": "default-src 'self'",
"X-Frame-Options": "SAMEORIGIN",
"X-Content-Type-Options": "nosniff",
"Referrer-Policy": "strict-origin-when-cross-origin",
"Permissions-Policy": "geolocation=()",
"Cache-Control": "no-store",
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Resource-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
})
issues = await scanner.scan("https://example.com", response)
assert len(issues) == 0