#!/usr/bin/env python3 """Unit tests for web_interface.py security features.""" import subprocess import sys import tempfile from pathlib import Path from unittest.mock import MagicMock, patch sys.path.insert(0, str(Path(__file__).parent.parent)) def test_validate_archive_path_blocks_traversal(): """Test validate_archive_path function blocks traversal.""" from web_interface import validate_archive_path, ARCHIVE_DIR for bad in ["../../../etc/passwd", "..%2Fetc%2Fpasswd", "../secret.txt"]: result = validate_archive_path(bad) assert result is None, f"Should block: {bad}" print(" PASS: traversal blocked") def test_xss_safe_filter_removed(): """Test that article.html no longer uses |safe filter.""" result = subprocess.run( ["grep", "-rn", "|safe", "templates/article.html"], capture_output=True, text=True, ) assert result.returncode != 0, "article.html should not contain |safe" print(" PASS: no |safe in article.html") def test_security_headers_present(): """Test security headers are added to responses.""" from web_interface import app client = app.test_client() resp = client.get("/") assert resp.headers.get("X-Content-Type-Options") == "nosniff" assert resp.headers.get("X-Frame-Options") == "DENY" assert resp.headers.get("X-XSS-Protection") == "1; mode=block" assert resp.headers.get("Referrer-Policy") == "strict-origin-when-cross-origin" print(" PASS: security headers present") def test_server_url_not_hardcoded(): """Test that SERVER_URL comes from env, not hardcoded.""" result = subprocess.run( ["grep", "-n", "192\\.168", "web_interface.py"], capture_output=True, text=True, ) assert result.returncode != 0, "No hardcoded internal IPs" print(" PASS: no hardcoded IPs") def test_no_safe_filter_in_rss(): """Test RSS/Atom feeds escape content properly.""" result = subprocess.run( ["grep", "-rn", "|safe", "templates/rss.xml", "templates/atom.xml"], capture_output=True, text=True, ) assert result.returncode != 0, "No |safe in RSS templates" print(" PASS: no |safe in RSS/Atom") if __name__ == "__main__": test_validate_archive_path_blocks_traversal() test_xss_safe_filter_removed() test_security_headers_present() test_server_url_not_hardcoded() test_no_safe_filter_in_rss() print("\nAll web interface tests passed!")