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 afc8c087 Set length limits on reads of KEYS, LICENSE, and NOTICE files
afc8c087 is described below

commit afc8c087aa01b0cd9c51ce2cd829af5770b3250c
Author: Sean B. Palmer <[email protected]>
AuthorDate: Wed Mar 11 20:21:49 2026 +0000

    Set length limits on reads of KEYS, LICENSE, and NOTICE files
---
 atr/post/keys.py            | 21 ++++++++++++++++++++-
 atr/tasks/checks/license.py | 15 +++++++++++++--
 2 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/atr/post/keys.py b/atr/post/keys.py
index df295ea1..92b678a3 100644
--- a/atr/post/keys.py
+++ b/atr/post/keys.py
@@ -41,6 +41,9 @@ import atr.web as web
 
 _KEYS_BASE_URL: Final[str] = "https://downloads.apache.org";
 
+# The Apache Subversion KEYS file is largest at 3732091 bytes
+_MAX_KEYS_SIZE: Final[int] = 10 * 1024 * 1024
+
 
 @post.typed
 async def add(
@@ -273,7 +276,23 @@ async def _fetch_keys_from_url(keys_url: str) -> str:
         async with util.create_secure_session(timeout=timeout) as session:
             async with session.get(keys_url, allow_redirects=True) as response:
                 response.raise_for_status()
-                return await response.text()
+                content_length = response.content_length
+                if (content_length is not None) and (content_length > 
_MAX_KEYS_SIZE):
+                    raise base.ASFQuartException(
+                        f"KEYS file too large ({content_length} bytes, limit 
{_MAX_KEYS_SIZE})",
+                        errorcode=502,
+                    )
+                chunks: list[bytes] = []
+                size = 0
+                async for chunk in response.content.iter_chunked(65536):
+                    size += len(chunk)
+                    if size > _MAX_KEYS_SIZE:
+                        raise base.ASFQuartException(
+                            f"KEYS file too large (limit {_MAX_KEYS_SIZE} 
bytes)",
+                            errorcode=502,
+                        )
+                    chunks.append(chunk)
+                return b"".join(chunks).decode("utf-8")
     except aiohttp.ClientResponseError as e:
         raise base.ASFQuartException(f"Unable to fetch keys from remote 
server: {e.status} {e.message}", errorcode=502)
     except aiohttp.ClientError as e:
diff --git a/atr/tasks/checks/license.py b/atr/tasks/checks/license.py
index b5858deb..ff28087e 100644
--- a/atr/tasks/checks/license.py
+++ b/atr/tasks/checks/license.py
@@ -84,6 +84,8 @@ INPUT_EXTRA_ARGS: Final[list[str]] = ["is_podling"]
 CHECK_VERSION_FILES: Final[str] = "3"
 CHECK_VERSION_HEADERS: Final[str] = "3"
 
+_MAX_LICENSE_NOTICE_SIZE: Final[int] = 1024 * 1024
+
 # Types
 
 
@@ -298,7 +300,11 @@ def _files_check_core_logic(cache_dir: pathlib.Path, 
is_podling: bool) -> Iterat
 
 def _files_check_core_logic_license(file_path: pathlib.Path) -> str | None:
     """Verify that the start of the LICENSE file matches the Apache 2.0 
license."""
-    package_license_bytes = file_path.read_bytes()
+    with open(file_path, "rb") as f:
+        package_license_bytes = f.read(_MAX_LICENSE_NOTICE_SIZE + 1)
+    if len(package_license_bytes) > _MAX_LICENSE_NOTICE_SIZE:
+        log.warning(f"LICENSE file exceeds {_MAX_LICENSE_NOTICE_SIZE} byte 
limit: {file_path}")
+        package_license_bytes = 
package_license_bytes[:_MAX_LICENSE_NOTICE_SIZE]
 
     sha3e = hashlib.sha3_256()
     sha3e.update(constants.APACHE_LICENSE_2_0.encode("utf-8"))
@@ -331,7 +337,12 @@ def _files_check_core_logic_license(file_path: 
pathlib.Path) -> str | None:
 def _files_check_core_logic_notice(file_path: pathlib.Path) -> tuple[bool, 
list[str], str]:
     """Verify that the NOTICE file follows the required format."""
     try:
-        content = file_path.read_bytes().decode("utf-8")
+        with open(file_path, "rb") as f:
+            raw = f.read(_MAX_LICENSE_NOTICE_SIZE + 1)
+        if len(raw) > _MAX_LICENSE_NOTICE_SIZE:
+            log.warning(f"NOTICE file exceeds {_MAX_LICENSE_NOTICE_SIZE} byte 
limit: {file_path}")
+            raw = raw[:_MAX_LICENSE_NOTICE_SIZE]
+        content = raw.decode("utf-8")
     except UnicodeDecodeError:
         return False, ["the NOTICE file is not valid UTF-8"], ""
     preamble = "".join(content.splitlines(keepends=True)[:3])


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

Reply via email to