mirror of
https://github.com/Rarebuffalo/securelens-backend.git
synced 2026-06-19 07:00:30 +00:00
95 lines
3.4 KiB
Python
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
|