Skip to content

Commit 175e0a2

Browse files
committed
Annotate SonarCloud security hotspots with NOSONAR justifications
1 parent 0dab17a commit 175e0a2

File tree

6 files changed

+24
-9
lines changed

6 files changed

+24
-9
lines changed

automation_file/local/tar_ops.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ def create_tar(
5757
target_path.parent.mkdir(parents=True, exist_ok=True)
5858

5959
try:
60-
with tarfile.open(str(target_path), mode) as archive:
60+
# Write mode — not extraction.
61+
with tarfile.open(str(target_path), mode) as archive: # NOSONAR python:S5042
6162
archive.add(str(src_path), arcname=src_path.name)
6263
except (OSError, tarfile.TarError) as err:
6364
raise TarException(f"create_tar failed: {err}") from err
@@ -76,7 +77,9 @@ def extract_tar(source: str, target_dir: str) -> list[str]:
7677

7778
extracted: list[str] = []
7879
try:
79-
with tarfile.open(str(src_path), "r:*") as archive:
80+
# _verify_members rejects traversal / escaping symlinks / hardlinks before any
81+
# extract, and PEP 706 filter="data" is applied when available (3.10.12+ / 3.11.4+ / 3.12+).
82+
with tarfile.open(str(src_path), "r:*") as archive: # NOSONAR python:S5042
8083
_verify_members(archive, dest)
8184
for member in archive.getmembers():
8285
if _TAR_FILTER_SUPPORTED:

automation_file/remote/ftp/client.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,11 @@ def __init__(self) -> None:
4242
def later_init(self, options: FTPConnectOptions | None = None, **kwargs: Any) -> FTP:
4343
"""Open an FTP control connection. TLS is negotiated when ``tls=True``."""
4444
opts = options if options is not None else FTPConnectOptions(**kwargs)
45-
ftp: FTP = FTP_TLS(timeout=opts.timeout) if opts.tls else FTP(timeout=opts.timeout)
45+
# Plaintext FTP is opt-in via tls=False; FTPS is the default when tls=True.
46+
if opts.tls:
47+
ftp: FTP = FTP_TLS(timeout=opts.timeout)
48+
else:
49+
ftp = FTP(timeout=opts.timeout) # NOSONAR python:S5332
4650
try:
4751
ftp.connect(opts.host, opts.port, timeout=opts.timeout)
4852
if opts.tls and isinstance(ftp, FTP_TLS):

tests/test_checksum.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ def test_file_checksum_streams_large_file(tmp_path: Path) -> None:
3535
def test_file_checksum_md5(tmp_path: Path) -> None:
3636
target = tmp_path / "a.bin"
3737
target.write_bytes(b"hi")
38-
assert file_checksum(target, algorithm="md5") == hashlib.md5(b"hi").hexdigest()
38+
# Verifies the library accepts any hashlib algorithm — not a security use of MD5.
39+
expected = hashlib.md5(b"hi").hexdigest() # NOSONAR python:S4790
40+
assert file_checksum(target, algorithm="md5") == expected
3941

4042

4143
def test_file_checksum_unknown_algorithm(tmp_path: Path) -> None:

tests/test_cross_backend.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,11 @@ def test_missing_local_source_returns_false(tmp_path: Path) -> None:
4242

4343

4444
def test_unknown_source_scheme_raises() -> None:
45+
# The target path is unused — the call must fail on the source scheme
46+
# before touching the filesystem.
47+
unused_target = "/tmp/x" # NOSONAR python:S5443
4548
with pytest.raises(CrossBackendException):
46-
copy_between("gopher://a/b", "/tmp/x")
49+
copy_between("gopher://a/b", unused_target)
4750

4851

4952
def test_unknown_target_scheme_raises(tmp_path: Path) -> None:

tests/test_http_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def _ensure_echo_registered() -> None:
1818

1919
def _base_url(server) -> str:
2020
host, port = server.server_address
21-
return f"http://{host}:{port}"
21+
return f"http://{host}:{port}" # NOSONAR python:S5332 — loopback test server; TLS not in scope.
2222

2323

2424
def test_client_executes_action_round_trip() -> None:

tests/test_tar_ops.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ def test_create_and_extract_gz(sample_dir: Path, tmp_path: Path) -> None:
3939
def test_create_uncompressed(sample_dir: Path, tmp_path: Path) -> None:
4040
archive = tmp_path / "plain.tar"
4141
create_tar(str(sample_dir), str(archive), compression=None)
42-
with tarfile.open(str(archive), "r") as tf:
42+
# Reading an archive we just wrote in this test — not untrusted input.
43+
with tarfile.open(str(archive), "r") as tf: # NOSONAR python:S5042
4344
assert any(name.endswith("a.txt") for name in tf.getnames())
4445

4546

@@ -72,7 +73,8 @@ def test_extract_missing_archive_raises(tmp_path: Path) -> None:
7273

7374
def test_extract_rejects_path_traversal(tmp_path: Path) -> None:
7475
archive = tmp_path / "evil.tar"
75-
with tarfile.open(str(archive), "w") as tf:
76+
# Write mode; fixture builds a malicious archive to exercise the guard.
77+
with tarfile.open(str(archive), "w") as tf: # NOSONAR python:S5042
7678
info = tarfile.TarInfo(name="../escape.txt")
7779
info.size = 0
7880
tf.addfile(info, None)
@@ -83,7 +85,8 @@ def test_extract_rejects_path_traversal(tmp_path: Path) -> None:
8385

8486
def test_extract_rejects_absolute_symlink(tmp_path: Path) -> None:
8587
archive = tmp_path / "evil.tar"
86-
with tarfile.open(str(archive), "w") as tf:
88+
# Write mode; fixture builds a malicious archive to exercise the guard.
89+
with tarfile.open(str(archive), "w") as tf: # NOSONAR python:S5042
8790
info = tarfile.TarInfo(name="link")
8891
info.type = tarfile.SYMTYPE
8992
info.linkname = "/etc/passwd"

0 commit comments

Comments
 (0)