import os import re import tempfile from pathlib import Path import pytest from fastapi.testclient import TestClient from theHarvester.__main__ import sanitize_filename, sanitize_for_xml class TestCORSConfiguration: """Test CORS security configuration.""" def test_cors_does_not_allow_credentials_with_wildcard_origins(self): """ Security Test: CORS should not allow credentials with wildcard origins. This prevents credential theft attacks where any origin can make authenticated requests to the API. """ from theHarvester.lib.api.api import app # Find CORS middleware in the app cors_middleware = None for middleware in app.user_middleware: if 'CORSMiddleware' in str(middleware.cls): cors_middleware = middleware break assert cors_middleware is not None, 'CORS middleware should be configured' # Check that if allow_origins contains '*', allow_credentials must be False # Access kwargs from the middleware options = cors_middleware.kwargs allow_origins = options.get('allow_origins', []) allow_credentials = options.get('allow_credentials', False) if isinstance(allow_origins, (list, tuple, set)) and '*' in allow_origins: assert ( allow_credentials is False ), 'CRITICAL: CORS must not allow credentials with wildcard origins (CVE risk)' def test_cors_restricts_http_methods(self): """ Security Test: CORS should restrict HTTP methods to only what's needed. Reduces attack surface by limiting available methods. """ from theHarvester.lib.api.api import app cors_middleware = None for middleware in app.user_middleware: if 'CORSMiddleware' in str(middleware.cls): cors_middleware = middleware break assert cors_middleware is not None options = cors_middleware.kwargs allow_methods = options.get('allow_methods', []) # Should not allow all methods assert allow_methods != ['*'], 'CORS should restrict HTTP methods, not allow all (*)' # Should only allow necessary methods (GET, POST for this API) if isinstance(allow_methods, list): dangerous_methods = {'DELETE', 'PUT', 'PATCH', 'TRACE', 'CONNECT'} allowed_set = {m.upper() for m in allow_methods} assert not ( allowed_set & dangerous_methods ), f'Unnecessary HTTP methods detected: {allowed_set & dangerous_methods}' class TestXMLInjectionPrevention: """Test XML injection prevention.""" def test_sanitize_for_xml_escapes_special_characters(self): """ Security Test: Verify XML special characters are properly escaped. Prevents XML injection attacks. """ # Test all XML special characters test_cases = [ ('&', '&'), ('<', '<'), ('>', '>'), ('"', '"'), ("'", '''), ('', '<script>alert("XSS")</script>'), ('user@example.com & ', 'user@example.com & <test>'), ('Normal text', 'Normal text'), ] for input_text, expected_output in test_cases: result = sanitize_for_xml(input_text) assert result == expected_output, f'Failed to properly escape: {input_text}' def test_sanitize_for_xml_prevents_xml_entity_injection(self): """ Security Test: Prevent XML entity injection attempts. """ malicious_inputs = [ ']>', '', '', '<script>', ] for malicious_input in malicious_inputs: result = sanitize_for_xml(malicious_input) # Ensure dangerous characters are escaped assert '<' in result or '&' in result, f'Failed to sanitize: {malicious_input}' assert '<' not in result or result == malicious_input.replace('<', '<'), f'XML tags not escaped: {malicious_input}' def test_command_line_args_are_sanitized_in_xml_output(self): """ Security Test: Command line arguments must be sanitized before XML output. This test is a conceptual check - in real usage, ensure the XML writing code uses sanitize_for_xml() on all user-controlled data. """ # Simulate dangerous command line arguments dangerous_args = [ '--domain=test.com', "--source=''", '--output="; rm -rf /', '--domain=example.com¶m=', ] for arg in dangerous_args: sanitized = sanitize_for_xml(arg) # Verify no unescaped XML special characters remain assert '