You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by ar...@apache.org on 2026/09/29 15:38:48 UTC

(tooling-trusted-releases) 01/02: #1591 - pin pre-commit hooks and make a few fixes

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

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

commit d318a3ca68b4950b00273ca6df3419bf7e5b8809
Author: Alastair McFarlane <ar...@apache.org>
AuthorDate: Tue Sep 29 13:54:32 2026 +0100

    #1591 - pin pre-commit hooks and make a few fixes
---
 .pre-commit-config.yaml                 | 18 +++++++++---------
 .pre-commit-heavy.yaml                  |  4 ++--
 Makefile                                |  2 +-
 atr/admin/__init__.py                   |  2 ++
 atr/static/js/src/finish-downloads.js   |  2 +-
 atr/static/js/src/heatmap-columns.js    |  2 +-
 atr/static/js/src/ongoing-tasks-poll.js |  5 +++--
 atr/static/js/src/report-results.js     |  2 +-
 atr/swhid.py                            |  4 ++++
 playwright/test.py                      |  2 ++
 scripts/hints_import.py                 |  2 ++
 11 files changed, 28 insertions(+), 17 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 49a44a5b..680cd16c 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -6,7 +6,7 @@ repos:
       name: check that hooks apply
       description: check that all the hooks apply to the repository
 - repo: https://github.com/pre-commit/pre-commit-hooks
-  rev: v6.0.0
+  rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c  # frozen: v6.0.0
   hooks:
     - id: check-ast
     - id: check-case-conflict
@@ -27,7 +27,7 @@ repos:
     - id: trailing-whitespace
       exclude: ^atr/static/js/(ts|min)/
 - repo: https://github.com/Lucas-C/pre-commit-hooks
-  rev: v1.5.6
+  rev: ad1b27d73581aa16cca06fc4a0761fc563ffe8e8  # frozen: v1.5.6
   hooks:
     - id: insert-license
       name: add a license for all Python files
@@ -48,7 +48,7 @@ repos:
         - scripts/ci/LICENSE-template.txt
         - --fuzzy-match-generates-todo
 - repo: https://github.com/igorshubovych/markdownlint-cli
-  rev: v0.49.1
+  rev: 5b5dddc4fb0f83c3ea1fc5616fa63e115dce83e0  # frozen: v0.49.1
   hooks:
     - id: markdownlint
       name: run Markdown lints
@@ -57,11 +57,11 @@ repos:
       types: [markdown]
       files: \.md$
 - repo: https://github.com/shellcheck-py/shellcheck-py
-  rev: v0.11.0.1-1
+  rev: a6564f5d57444e123433a5c9af733e3975c77229  # frozen: v0.11.0.1-1
   hooks:
     - id: shellcheck
 - repo: https://github.com/rtts/djhtml
-  rev: 3.0.11
+  rev: 8577ec017145d76a0b954ebb7cb3169d4303014c  # frozen: 3.0.11
   hooks:
     - id: djhtml
       files: .*/.*\.html$
@@ -84,7 +84,7 @@ repos:
 #        - --profile=jinja
 #        - --reformat
 - repo: https://github.com/thibaudcolas/pre-commit-stylelint
-  rev: v17.15.0
+  rev: d6d653746a0a510b098377a8919bea816eea3c09  # frozen: v17.15.0
   hooks:
     - id: stylelint
       additional_dependencies: ['stylelint@16.14.1', 'stylelint-config-standard@37.0.0']
@@ -92,12 +92,12 @@ repos:
       types_or: ['css']
       args: ['--fix', '--allow-empty-input']
 - repo: https://github.com/woodruffw/zizmor-pre-commit
-  rev: v1.30.1
+  rev: fa412071e4f5d44d44f9e365f4676f9df92456a2  # frozen: v1.30.1
   hooks:
     - id: zizmor
       args: [--min-severity, low]
 - repo: https://github.com/pypa/pip-audit
-  rev: v2.10.1
+  rev: 8894eb8cee033531a1fbd9f2fb160892531c14e3  # frozen: v2.10.1
   hooks:
     - id: pip-audit
       args:
@@ -108,7 +108,7 @@ repos:
         - '--ignore-vuln'
         - 'PYSEC-2025-183'
 - repo: https://github.com/oxc-project/mirrors-oxlint
-  rev: v1.60.0
+  rev: 7ab19fc41bc7c63cb01d4322509971371c285e16  # frozen: v1.85.0
   hooks:
     - id: oxlint
       name: lint JS files with Oxlint
diff --git a/.pre-commit-heavy.yaml b/.pre-commit-heavy.yaml
index 08880606..d0a3a9e0 100644
--- a/.pre-commit-heavy.yaml
+++ b/.pre-commit-heavy.yaml
@@ -1,7 +1,7 @@
 exclude: ^node_modules/
 repos:
 - repo: https://github.com/oxipng/oxipng
-  rev: v9.1.5
+  rev: 36f3ef8aac65ecf1761739ea2f2e530281f1312b  # frozen: v10.2.1
   hooks:
     - id: oxipng
       name: run oxipng
@@ -10,7 +10,7 @@ repos:
       # types: [image]
       # files: \.png$
 - repo: https://github.com/semgrep/semgrep
-  rev: v1.145.0
+  rev: e279a884ad6f16b050de690bdfdc26e921c364dc  # frozen: v1.177.0
   hooks:
     - id: semgrep
       args:
diff --git a/Makefile b/Makefile
index 98026223..7e8e49d2 100644
--- a/Makefile
+++ b/Makefile
@@ -161,7 +161,7 @@ unit:
 	sh tests/run-unit.sh
 
 update-deps:
-	pre-commit autoupdate || :
+	pre-commit autoupdate --freeze || :
 	uv lock --upgrade
 	uv sync --frozen --all-groups
 	python3 -S scripts/check_pth_files.py
diff --git a/atr/admin/__init__.py b/atr/admin/__init__.py
index 287e6e52..5eec0719 100644
--- a/atr/admin/__init__.py
+++ b/atr/admin/__init__.py
@@ -1906,6 +1906,8 @@ async def validate_jwt_post(
         result["header_error"] = f"{type(exc).__name__}: {exc}"
 
     try:
+        # Decoding without verification is the point here, we show claims even when the signature fails
+        # nosemgrep: python.jwt.security.unverified-jwt-decode.unverified-jwt-decode
         result["claims_unverified"] = jwt.decode(token, options={"verify_signature": False}, algorithms=["HS256"])
     except jwt.PyJWTError as exc:
         result["claims_unverified_error"] = f"{type(exc).__name__}: {exc}"
diff --git a/atr/static/js/src/finish-downloads.js b/atr/static/js/src/finish-downloads.js
index b756fd71..179e5a1a 100644
--- a/atr/static/js/src/finish-downloads.js
+++ b/atr/static/js/src/finish-downloads.js
@@ -20,7 +20,7 @@
 function initFinishDownloads() {
 	const status = document.getElementById("finish-publication-status");
 	const button = document.getElementById("finish-announce");
-	if (!status || !button || !button.classList.contains("disabled")) return;
+	if (!status || !button?.classList.contains("disabled")) return;
 	const message = document.getElementById("finish-publication-message");
 	const refresh = document.getElementById("finish-publication-refresh");
 
diff --git a/atr/static/js/src/heatmap-columns.js b/atr/static/js/src/heatmap-columns.js
index 52cef637..c46ae204 100644
--- a/atr/static/js/src/heatmap-columns.js
+++ b/atr/static/js/src/heatmap-columns.js
@@ -103,7 +103,7 @@ function bar(v) {
 
 export function esc(s) {
 	return String(s).replaceAll(
-		/[&<>"']/g,
+		/[&<>"']/gu,
 		(c) =>
 			({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[
 				c
diff --git a/atr/static/js/src/ongoing-tasks-poll.js b/atr/static/js/src/ongoing-tasks-poll.js
index 3fbd5738..075e9e8c 100644
--- a/atr/static/js/src/ongoing-tasks-poll.js
+++ b/atr/static/js/src/ongoing-tasks-poll.js
@@ -52,9 +52,10 @@
 	const filesCardHeaderText = document.getElementById("files-card-header-text");
 	const pollInterval = 3000;
 
-	const initialOngoing = parseInt(banner.dataset.ongoingCount || "0", 10) || 0;
+	const initialOngoing =
+		Math.trunc(Number(banner.dataset.ongoingCount || "0")) || 0;
 	const initialQuarantinePending =
-		parseInt(banner.dataset.quarantinePendingCount || "0", 10) || 0;
+		Math.trunc(Number(banner.dataset.quarantinePendingCount || "0")) || 0;
 	const initialPollingActive = banner.dataset.pollingActive === "true";
 
 	const shouldStart =
diff --git a/atr/static/js/src/report-results.js b/atr/static/js/src/report-results.js
index 158830b2..a34ea434 100644
--- a/atr/static/js/src/report-results.js
+++ b/atr/static/js/src/report-results.js
@@ -60,7 +60,7 @@ function toggleStatusVisibility(type, status) {
 	}
 	const filledClass = mapping.filled;
 	const outlineClass = mapping.outline;
-	const cntMatch = btn.textContent.match(/\((\d+)\)/);
+	const cntMatch = btn.textContent.match(/\((\d+)\)/u);
 	if (!cntMatch) {
 		console.error("Button text regex mismatch for:", btn.textContent);
 		return;
diff --git a/atr/swhid.py b/atr/swhid.py
index ebacc3af..9271e861 100644
--- a/atr/swhid.py
+++ b/atr/swhid.py
@@ -147,6 +147,8 @@ def _as_bytes(value: Commit) -> bytes:
 
 
 def _blob_digest_of_file(path: Path, size: int) -> bytes:
+    # SWHIDs are defined over git object IDs, which are SHA-1
+    # nosemgrep: python.lang.security.insecure-hash-algorithms.insecure-hash-algorithm-sha1
     hasher = hashlib.sha1(b"blob %d\x00" % size, usedforsecurity=False)
     with open(path, "rb") as handle:
         while chunk := handle.read(_CHUNK):
@@ -182,6 +184,8 @@ def _entry_sort_key(entry: tuple[bytes, bytes, bytes]) -> bytes:
 
 
 def _git_object_digest(kind: bytes, payload: bytes) -> bytes:
+    # SWHIDs are defined over git object IDs, which are SHA-1
+    # nosemgrep: python.lang.security.insecure-hash-algorithms.insecure-hash-algorithm-sha1
     hasher = hashlib.sha1(b"%s %d\x00" % (kind, len(payload)), usedforsecurity=False)
     hasher.update(payload)
     return hasher.digest()
diff --git a/playwright/test.py b/playwright/test.py
index 02fa68e8..e8c2cd4b 100755
--- a/playwright/test.py
+++ b/playwright/test.py
@@ -1336,6 +1336,8 @@ def test_ssh_02_rsync_upload(page: Page, credentials: Credentials) -> None:
 
     logging.info(f"Executing rsync command: {' '.join(rsync_cmd)}")
     try:
+        # The rsync arguments come from the test's own config, not from untrusted input
+        # nosemgrep
         result = subprocess.run(rsync_cmd, check=True, capture_output=True, text=True)
         logging.info(f"rsync completed successfully. stdout:\n{result.stdout}")
         if result.stderr:
diff --git a/scripts/hints_import.py b/scripts/hints_import.py
index b4084fad..03087217 100755
--- a/scripts/hints_import.py
+++ b/scripts/hints_import.py
@@ -86,6 +86,8 @@ def key_packet_ids(body: bytes) -> set[str]:
         fingerprint = hashlib.md5(modulus + exponent, usedforsecurity=False).hexdigest()
         return {fingerprint, modulus[-8:].hex()}
     if version == 4:
+        # RFC 4880 defines v4 fingerprints as SHA-1
+        # nosemgrep: python.lang.security.insecure-hash-algorithms.insecure-hash-algorithm-sha1
         digest = hashlib.sha1(b"\x99" + len(body).to_bytes(2, "big") + body, usedforsecurity=False).hexdigest()
         return {digest, digest[-16:]}
     if version in (5, 6):


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org