"""Security tests for SQL injection prevention.""" import pytest @pytest.mark.security class TestSQLInjectionPrevention: """Test SQL injection prevention in database queries.""" @pytest.mark.skip(reason="Requires database fixture - covered by existing unit tests") def test_token_service_sql_injection_in_me(self, db_session): """Test token service prevents SQL injection in 'me' parameter.""" from gondulf.services.token_service import TokenService token_service = TokenService(db_session) # Attempt SQL injection via 'me' parameter malicious_me = "https://user.example.com'; DROP TABLE tokens; --" client_id = "https://client.example.com" # Should not raise exception, should treat as literal string token = token_service.generate_access_token( me=malicious_me, client_id=client_id, scope="" ) assert token is not None # Verify token was stored safely (not executed as SQL) result = token_service.verify_access_token(token) assert result is not None assert result["me"] == malicious_me # Stored as literal string @pytest.mark.skip(reason="Requires database fixture - covered by existing unit tests") def test_token_lookup_sql_injection(self, db_session): """Test token lookup prevents SQL injection in token parameter.""" from gondulf.services.token_service import TokenService token_service = TokenService(db_session) # Attempt SQL injection via token parameter malicious_token = "' OR '1'='1" # Should return None (not found), not execute malicious SQL result = token_service.verify_access_token(malicious_token) assert result is None @pytest.mark.skip(reason="Requires database fixture - covered by existing unit tests") def test_domain_service_sql_injection_in_domain(self, db_session): """Test domain service prevents SQL injection in domain parameter.""" from gondulf.email import EmailService from gondulf.services.domain_verification import DomainVerificationService email_service = EmailService( smtp_host="localhost", smtp_port=25, smtp_from="noreply@example.com", smtp_username=None, smtp_password=None, smtp_use_tls=False, ) domain_service = DomainVerificationService( db_session=db_session, email_service=email_service ) # Attempt SQL injection via domain parameter malicious_domain = "example.com'; DROP TABLE domains; --" # Should handle safely (will fail validation but not execute SQL) try: # This will fail DNS validation, but shouldn't execute SQL domain_service.start_email_verification( domain=malicious_domain, me_url="https://example.com" ) except Exception: # Expected: validation or email failure pass # Verify no SQL error occurred and tables still exist # If SQL injection worked, this would raise an error result = db_session.execute( "SELECT name FROM sqlite_master WHERE type='table' AND name='tokens'" ) assert result.fetchone() is not None # Table exists @pytest.mark.skip(reason="Requires database fixture - covered by existing unit tests") def test_parameterized_queries_behavioral(self, db_session): """Test that SQL injection attempts fail safely using behavioral testing.""" from gondulf.services.token_service import TokenService token_service = TokenService(db_session) # Common SQL injection attempts injection_attempts = [ "' OR 1=1--", "'; DROP TABLE tokens; --", "' UNION SELECT * FROM tokens--", "admin'--", "' OR ''='", ] for attempt in injection_attempts: # Try as 'me' parameter try: token = token_service.generate_access_token( me=attempt, client_id="https://client.example.com", scope="" ) # If it succeeds, verify it was stored as literal string result = token_service.verify_access_token(token) assert result["me"] == attempt, "SQL injection modified the value" except Exception as e: # If it fails, it should be a validation error, not SQL error assert "syntax" not in str(e).lower(), f"SQL syntax error detected: {e}" assert "drop" not in str(e).lower(), f"SQL DROP detected: {e}"