All checks were successful
Build and Publish Container Image / build-and-push (push) Successful in 38s
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02b22-9638-76d2-bbff-b7ea1770b118
58 lines
1.7 KiB
Python
58 lines
1.7 KiB
Python
from __future__ import annotations
|
|
|
|
import io
|
|
import tarfile
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from sbom_nexus.source_fetch import SourceRejected, _extract, validate_source_ref
|
|
|
|
|
|
def _archive(path: Path, members: dict[str, bytes]) -> None:
|
|
with tarfile.open(path, "w:gz") as bundle:
|
|
for name, content in members.items():
|
|
info = tarfile.TarInfo(name)
|
|
info.size = len(content)
|
|
bundle.addfile(info, io.BytesIO(content))
|
|
|
|
|
|
def test_validate_source_ref_binds_repository_to_slug() -> None:
|
|
revision = "a" * 40
|
|
assert validate_source_ref(
|
|
"demo",
|
|
{
|
|
"kind": "forgejo-archive-v1",
|
|
"repository": "coulomb/demo",
|
|
"revision": revision,
|
|
},
|
|
)["revision"] == revision
|
|
with pytest.raises(SourceRejected, match="does not match"):
|
|
validate_source_ref(
|
|
"demo",
|
|
{
|
|
"kind": "forgejo-archive-v1",
|
|
"repository": "coulomb/other",
|
|
"revision": revision,
|
|
},
|
|
)
|
|
|
|
|
|
def test_extract_rejects_path_traversal(tmp_path: Path) -> None:
|
|
archive = tmp_path / "unsafe.tar.gz"
|
|
_archive(archive, {"repo/../../escaped": b"nope"})
|
|
|
|
with pytest.raises(SourceRejected, match="unsafe path"):
|
|
_extract(archive, tmp_path / "out")
|
|
|
|
|
|
def test_extract_accepts_one_regular_root(tmp_path: Path) -> None:
|
|
archive = tmp_path / "safe.tar.gz"
|
|
_archive(archive, {"repo/requirements.txt": b"fastapi==0.136.1\n"})
|
|
destination = tmp_path / "out"
|
|
destination.mkdir()
|
|
|
|
root = _extract(archive, destination)
|
|
|
|
assert root == destination / "repo"
|
|
assert (root / "requirements.txt").read_text() == "fastapi==0.136.1\n"
|