fix(audit): accept empty OSV source reports
This commit is contained in:
@@ -133,8 +133,82 @@ class SecurityAuditWrapperTests(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
path.chmod(0o755)
|
path.chmod(0o755)
|
||||||
|
|
||||||
|
def _install_full_mode_stubs(self) -> None:
|
||||||
|
self._write_stub(
|
||||||
|
"trivy",
|
||||||
|
r"""
|
||||||
|
if [[ " $* " == *" --version "* ]]; then
|
||||||
|
echo 'trivy stub 1.0'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
output=''
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
if [[ "$1" == '--output' ]]; then
|
||||||
|
output="$2"
|
||||||
|
shift 2
|
||||||
|
else
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
printf '%s\n' '{"version":"2.1.0","runs":[]}' > "$output"
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
self._write_stub(
|
||||||
|
"osv-scanner",
|
||||||
|
r"""
|
||||||
|
if [[ " $* " == *" --version "* ]]; then
|
||||||
|
echo 'osv-scanner stub 1.0'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [[ " $* " == *" scan --help "* ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
output=''
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
if [[ "$1" == '--output-file' ]]; then
|
||||||
|
output="$2"
|
||||||
|
shift 2
|
||||||
|
else
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
printf '{"results": %s}\n' "${STUB_OSV_RESULTS:-null}" > "$output"
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
self._write_stub(
|
||||||
|
"jscpd",
|
||||||
|
r"""
|
||||||
|
if [[ " $* " == *" --version "* ]]; then
|
||||||
|
echo 'jscpd stub 1.0'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
output=''
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
if [[ "$1" == '--output' ]]; then
|
||||||
|
output="$2"
|
||||||
|
shift 2
|
||||||
|
else
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
mkdir -p "$output"
|
||||||
|
printf '%s\n' '{"duplicates":[],"statistics":{}}' > "$output/jscpd-report.json"
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
for tool in ("pip-audit", "npm", "radon", "xenon"):
|
||||||
|
self._write_stub(
|
||||||
|
tool,
|
||||||
|
f"""
|
||||||
|
if [[ " $* " == *" --version "* ]]; then
|
||||||
|
echo '{tool} stub 1.0'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
|
||||||
def _run(
|
def _run(
|
||||||
self, *arguments: str, **environment: str
|
self, *arguments: str, mode: str = "quick", **environment: str
|
||||||
) -> tuple[subprocess.CompletedProcess[str], Path]:
|
) -> tuple[subprocess.CompletedProcess[str], Path]:
|
||||||
reports = self.temporary_root / "reports"
|
reports = self.temporary_root / "reports"
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
@@ -151,7 +225,7 @@ class SecurityAuditWrapperTests(unittest.TestCase):
|
|||||||
"bash",
|
"bash",
|
||||||
str(self.checkout / "tools" / "checks" / AUDIT_SCRIPT.name),
|
str(self.checkout / "tools" / "checks" / AUDIT_SCRIPT.name),
|
||||||
"--mode",
|
"--mode",
|
||||||
"quick",
|
mode,
|
||||||
"--scope",
|
"--scope",
|
||||||
"current",
|
"current",
|
||||||
"--reports-dir",
|
"--reports-dir",
|
||||||
@@ -215,6 +289,28 @@ class SecurityAuditWrapperTests(unittest.TestCase):
|
|||||||
(reports / "step-status.tsv").read_text(),
|
(reports / "step-status.tsv").read_text(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_osv_null_results_are_valid_but_wrong_shapes_fail(self) -> None:
|
||||||
|
self._install_full_mode_stubs()
|
||||||
|
|
||||||
|
result, reports = self._run("--report-only", mode="full")
|
||||||
|
self.assertEqual(0, result.returncode, result.stderr)
|
||||||
|
osv_report = json.loads(
|
||||||
|
(reports / "osv-scanner-checkout.json").read_text(encoding="utf-8")
|
||||||
|
)
|
||||||
|
self.assertIsNone(osv_report["results"])
|
||||||
|
|
||||||
|
invalid_result, invalid_reports = self._run(
|
||||||
|
"--report-only",
|
||||||
|
mode="full",
|
||||||
|
STUB_OSV_RESULTS="{}",
|
||||||
|
)
|
||||||
|
self.assertEqual(1, invalid_result.returncode)
|
||||||
|
self.assertIn(
|
||||||
|
"invalid OSV-Scanner report",
|
||||||
|
invalid_result.stderr,
|
||||||
|
)
|
||||||
|
self.assertEqual(1, self._manifest(invalid_reports)["execution_error_status"])
|
||||||
|
|
||||||
def test_workspace_mutation_invalidates_the_audit(self) -> None:
|
def test_workspace_mutation_invalidates_the_audit(self) -> None:
|
||||||
result, reports = self._run(
|
result, reports = self._run(
|
||||||
"--report-only",
|
"--report-only",
|
||||||
|
|||||||
@@ -444,7 +444,8 @@ for raw_path in sorted(set(sys.argv[2:])):
|
|||||||
errors.append(f"{relative_path}: npm audit returned an invalid or error report")
|
errors.append(f"{relative_path}: npm audit returned an invalid or error report")
|
||||||
elif report_name.startswith("osv-scanner-") and (
|
elif report_name.startswith("osv-scanner-") and (
|
||||||
not isinstance(payload, dict)
|
not isinstance(payload, dict)
|
||||||
or not isinstance(payload.get("results"), list)
|
or "results" not in payload
|
||||||
|
or (payload["results"] is not None and not isinstance(payload["results"], list))
|
||||||
):
|
):
|
||||||
errors.append(f"{relative_path}: invalid OSV-Scanner report")
|
errors.append(f"{relative_path}: invalid OSV-Scanner report")
|
||||||
elif report_name == "jscpd-report.json" and (
|
elif report_name == "jscpd-report.json" and (
|
||||||
|
|||||||
Reference in New Issue
Block a user