This is an automated email from the ASF dual-hosted git repository.

sbp pushed a commit to branch sbp
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git


The following commit(s) were added to refs/heads/sbp by this push:
     new 731b389a Add the quarantined directory and tests
731b389a is described below

commit 731b389ae90d6d58a65afd37aec682335e10ad60
Author: Sean B. Palmer <[email protected]>
AuthorDate: Mon Feb 23 19:35:32 2026 +0000

    Add the quarantined directory and tests
---
 atr/server.py           |  1 +
 atr/util.py             | 21 ++++++++++++++++-----
 tests/unit/test_util.py | 23 +++++++++++++++++++++++
 3 files changed, 40 insertions(+), 5 deletions(-)

diff --git a/atr/server.py b/atr/server.py
index e30fc5fb..3119098f 100644
--- a/atr/server.py
+++ b/atr/server.py
@@ -174,6 +174,7 @@ def _app_dirs_setup(state_dir_str: str, hot_reload: bool) 
-> None:
         pathlib.Path(state_dir_str) / "secrets" / "generated",
         util.get_downloads_dir(),
         util.get_finished_dir(),
+        util.get_quarantined_dir(),
         util.get_tmp_dir(),
         util.get_unfinished_dir(),
     ]
diff --git a/atr/util.py b/atr/util.py
index bec78bf0..e412f74c 100644
--- a/atr/util.py
+++ b/atr/util.py
@@ -140,11 +140,6 @@ def as_url(func: Callable, **kwargs: Any) -> str:
     return quart.url_for(annotations["endpoint"], **kwargs)
 
 
-def json_for_script_element(value: Any) -> markupsafe.Markup:
-    """Serialise JSON safely for use inside a script element."""
-    return jinja2.utils.htmlsafe_json_dumps(value, dumps=json.dumps, 
ensure_ascii=False)
-
-
 def asf_uid_from_email(email: str) -> str | None:
     ldap_params = ldap.SearchParameters(email_query=email)
     ldap.search(ldap_params)
@@ -559,6 +554,10 @@ def get_finished_dir() -> pathlib.Path:
     return pathlib.Path(config.get().FINISHED_STORAGE_DIR)
 
 
+def get_quarantined_dir() -> pathlib.Path:
+    return pathlib.Path(config.get().STATE_DIR) / "quarantined"
+
+
 async def get_release_stats(release: sql.Release) -> tuple[int, int, str]:
     """Calculate file count, total byte size, and formatted size for a 
release."""
     base_dir = release_directory(release)
@@ -681,6 +680,11 @@ def is_user_viewing_as_admin(uid: str | None) -> bool:
         return True
 
 
+def json_for_script_element(value: Any) -> markupsafe.Markup:
+    """Serialise JSON safely for use inside a script element."""
+    return jinja2.utils.htmlsafe_json_dumps(value, dumps=json.dumps, 
ensure_ascii=False)
+
+
 def key_ssh_fingerprint(ssh_key_string: str) -> str:
     try:
         return key_ssh_fingerprint_core(ssh_key_string)
@@ -889,6 +893,13 @@ def plural(count: int, singular: str, plural_form: str | 
None = None, *, include
     return word
 
 
+def quarantine_directory(quarantined: sql.Quarantined) -> pathlib.Path:
+    if not quarantined.token.isalnum():
+        raise ValueError("Invalid quarantine token")
+    release = quarantined.release
+    return get_quarantined_dir() / release.project_name / release.version / 
quarantined.token
+
+
 async def read_file_for_viewer(full_path: pathlib.Path, max_size: int) -> 
tuple[str | None, bool, bool, str | None]:
     """Read file content for viewer."""
     content: str | None = None
diff --git a/tests/unit/test_util.py b/tests/unit/test_util.py
index 20ff6505..aec4aaac 100644
--- a/tests/unit/test_util.py
+++ b/tests/unit/test_util.py
@@ -19,6 +19,9 @@ import json
 import os
 import pathlib
 import stat
+import types
+
+import pytest
 
 import atr.util as util
 
@@ -92,6 +95,12 @@ def test_chmod_files_sets_default_permissions(tmp_path: 
pathlib.Path):
     assert file_mode == 0o444
 
 
+def test_get_quarantined_dir_uses_state_dir(monkeypatch, tmp_path: 
pathlib.Path):
+    mock_config = types.SimpleNamespace(STATE_DIR=str(tmp_path))
+    monkeypatch.setattr("atr.config.get", lambda: mock_config)
+    assert util.get_quarantined_dir() == tmp_path / "quarantined"
+
+
 def test_json_for_script_element_escapes_correctly():
     payload = ["example.txt", "</script><script>alert(1)</script>", 
"apple&banana"]
 
@@ -102,3 +111,17 @@ def test_json_for_script_element_escapes_correctly():
     assert "apple&banana" not in serialized
     assert "apple\\u0026banana" in serialized
     assert json.loads(serialized) == payload
+
+
+def test_quarantine_directory_builds_deterministic_path(monkeypatch, tmp_path: 
pathlib.Path):
+    mock_config = types.SimpleNamespace(STATE_DIR=str(tmp_path))
+    monkeypatch.setattr("atr.config.get", lambda: mock_config)
+    mock_release = types.SimpleNamespace(project_name="example", 
version="1.2.3")
+    quarantined = types.SimpleNamespace(release=mock_release, 
token="0123456789abcdef")
+    assert util.quarantine_directory(quarantined) == tmp_path / "quarantined" 
/ "example" / "1.2.3" / "0123456789abcdef"
+
+
+def test_quarantine_directory_rejects_non_alnum_token():
+    quarantined = types.SimpleNamespace(token="../escape")
+    with pytest.raises(ValueError, match="Invalid quarantine token"):
+        util.quarantine_directory(quarantined)


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to