A Python port of the Invisible Internet Project (I2P)
at main 145 lines 5.7 kB view raw
1"""Tests for tools/security/check_results.py.""" 2from __future__ import annotations 3 4import json 5import sys 6from pathlib import Path 7 8import pytest 9 10# Add tools/security to path so we can import check_results 11sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "tools" / "security")) 12import check_results 13 14 15class TestCheckBandit: 16 def test_missing_file(self, tmp_path: Path) -> None: 17 result = check_results.check_bandit(tmp_path / "nonexistent.json") 18 assert result == [] 19 20 def test_empty_results(self, tmp_path: Path) -> None: 21 f = tmp_path / "bandit.json" 22 f.write_text(json.dumps({"results": []})) 23 assert check_results.check_bandit(f) == [] 24 25 def test_low_severity_ignored(self, tmp_path: Path) -> None: 26 f = tmp_path / "bandit.json" 27 f.write_text(json.dumps({"results": [ 28 {"issue_severity": "LOW", "issue_confidence": "HIGH", 29 "issue_text": "test", "filename": "x.py", "line_number": 1} 30 ]})) 31 assert check_results.check_bandit(f) == [] 32 33 def test_high_severity_high_confidence(self, tmp_path: Path) -> None: 34 finding = {"issue_severity": "HIGH", "issue_confidence": "HIGH", 35 "issue_text": "shell=True", "filename": "x.py", "line_number": 5} 36 f = tmp_path / "bandit.json" 37 f.write_text(json.dumps({"results": [finding]})) 38 result = check_results.check_bandit(f) 39 assert len(result) == 1 40 assert result[0]["issue_text"] == "shell=True" 41 42 def test_high_severity_low_confidence_ignored(self, tmp_path: Path) -> None: 43 f = tmp_path / "bandit.json" 44 f.write_text(json.dumps({"results": [ 45 {"issue_severity": "HIGH", "issue_confidence": "LOW", 46 "issue_text": "test", "filename": "x.py", "line_number": 1} 47 ]})) 48 assert check_results.check_bandit(f) == [] 49 50 def test_critical_severity(self, tmp_path: Path) -> None: 51 f = tmp_path / "bandit.json" 52 f.write_text(json.dumps({"results": [ 53 {"issue_severity": "CRITICAL", "issue_confidence": "MEDIUM", 54 "issue_text": "eval", "filename": "y.py", "line_number": 10} 55 ]})) 56 result = check_results.check_bandit(f) 57 assert len(result) == 1 58 59 60class TestCheckSemgrep: 61 def test_missing_file(self, tmp_path: Path) -> None: 62 assert check_results.check_semgrep(tmp_path / "nope.json") == [] 63 64 def test_empty_results(self, tmp_path: Path) -> None: 65 f = tmp_path / "semgrep.json" 66 f.write_text(json.dumps({"results": []})) 67 assert check_results.check_semgrep(f) == [] 68 69 def test_warning_ignored(self, tmp_path: Path) -> None: 70 f = tmp_path / "semgrep.json" 71 f.write_text(json.dumps({"results": [ 72 {"check_id": "test", "path": "x.py", 73 "start": {"line": 1}, "extra": {"severity": "WARNING"}} 74 ]})) 75 assert check_results.check_semgrep(f) == [] 76 77 def test_error_captured(self, tmp_path: Path) -> None: 78 f = tmp_path / "semgrep.json" 79 f.write_text(json.dumps({"results": [ 80 {"check_id": "no-eval", "path": "x.py", 81 "start": {"line": 3}, "extra": {"severity": "ERROR", "message": "no eval"}} 82 ]})) 83 result = check_results.check_semgrep(f) 84 assert len(result) == 1 85 86 87class TestCheckPipAudit: 88 def test_missing_file(self, tmp_path: Path) -> None: 89 assert check_results.check_pip_audit(tmp_path / "nope.json") == [] 90 91 def test_no_vulns(self, tmp_path: Path) -> None: 92 f = tmp_path / "audit.json" 93 f.write_text(json.dumps({"dependencies": [ 94 {"name": "cryptography", "version": "42.0", "vulns": []} 95 ]})) 96 assert check_results.check_pip_audit(f) == [] 97 98 def test_vuln_found(self, tmp_path: Path) -> None: 99 f = tmp_path / "audit.json" 100 f.write_text(json.dumps({"dependencies": [ 101 {"name": "requests", "version": "2.28.0", "vulns": [ 102 {"id": "CVE-2023-1234", "description": "bad thing"} 103 ]} 104 ]})) 105 result = check_results.check_pip_audit(f) 106 assert len(result) == 1 107 assert result[0]["name"] == "requests" 108 109 def test_build_tools_excluded(self, tmp_path: Path) -> None: 110 f = tmp_path / "audit.json" 111 f.write_text(json.dumps({"dependencies": [ 112 {"name": "pip", "version": "24.0", "vulns": [ 113 {"id": "CVE-2025-8869", "description": "tar issue"} 114 ]}, 115 {"name": "setuptools", "version": "69.0", "vulns": [ 116 {"id": "CVE-2024-5678", "description": "another issue"} 117 ]}, 118 {"name": "wheel", "version": "0.45", "vulns": [ 119 {"id": "CVE-2026-2049", "description": "path traversal"} 120 ]}, 121 ]})) 122 assert check_results.check_pip_audit(f) == [] 123 124 125class TestMain: 126 def test_all_clean(self, tmp_path: Path) -> None: 127 bandit_f = tmp_path / "bandit.json" 128 bandit_f.write_text(json.dumps({"results": []})) 129 audit_f = tmp_path / "audit.json" 130 audit_f.write_text(json.dumps({"dependencies": []})) 131 132 sys.argv = ["check_results.py", 133 "--bandit", str(bandit_f), 134 "--pip-audit", str(audit_f)] 135 assert check_results.main() == 0 136 137 def test_failure_on_high(self, tmp_path: Path) -> None: 138 bandit_f = tmp_path / "bandit.json" 139 bandit_f.write_text(json.dumps({"results": [ 140 {"issue_severity": "HIGH", "issue_confidence": "HIGH", 141 "issue_text": "bad", "filename": "x.py", "line_number": 1} 142 ]})) 143 144 sys.argv = ["check_results.py", "--bandit", str(bandit_f)] 145 assert check_results.main() == 1