From b3d66899b08dbe97b8cb72166c8ecdb83ae4272e Mon Sep 17 00:00:00 2001 From: Yaniv Golan Date: Sat, 25 Apr 2026 22:05:54 +0300 Subject: [PATCH] fix: resolve remaining code scanning alerts - Pin all GitHub Actions in codeql.yml and scorecard.yml to commit SHAs - Scope security-events:write to the analyze job in codeql.yml - Scope contents:write and id-token:write to per-job in release.yml - Add explanatory comment to empty ImportError except in images.py - Replace flickr.com substring URL checks with is_flickr_url() in test_pages.py and test_social.py Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/codeql.yml | 11 +++++++---- .github/workflows/release.yml | 8 ++++++-- .github/workflows/scorecard.yml | 8 ++++---- src/offlickr/derive/images.py | 2 +- tests/test_render/test_pages.py | 2 +- tests/test_render/test_social.py | 4 +++- 6 files changed, 22 insertions(+), 13 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1172ab8..e98b3dc 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -11,15 +11,18 @@ on: permissions: actions: read contents: read - security-events: write jobs: analyze: runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write steps: - - uses: actions/checkout@v4 - - uses: github/codeql-action/init@v3 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: github/codeql-action/init@ce64ddcb0d8d890d2df4a9d1c04ff297367dea2a # v3 with: languages: python queries: security-and-quality - - uses: github/codeql-action/analyze@v3 + - uses: github/codeql-action/analyze@ce64ddcb0d8d890d2df4a9d1c04ff297367dea2a # v3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 93fda31..0ea4860 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,8 +9,7 @@ on: - "v*.*.*-alpha*" permissions: - contents: write - id-token: write # for PyPI trusted publishing + contents: read jobs: preflight: @@ -78,6 +77,9 @@ jobs: needs: [preflight, build] runs-on: ubuntu-latest environment: pypi # configure Trusted Publishing in this environment + permissions: + id-token: write # for PyPI trusted publishing + contents: read steps: - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: @@ -91,6 +93,8 @@ jobs: github-release: needs: [preflight, build] runs-on: ubuntu-latest + permissions: + contents: write # to create GitHub releases steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index 4532054..75e6bf3 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -21,25 +21,25 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: persist-credentials: false - name: Run analysis - uses: ossf/scorecard-action@v2.4.0 + uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 with: results_file: results.sarif results_format: sarif publish_results: true - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: SARIF file path: results.sarif retention-days: 5 - name: Upload to code-scanning - uses: github/codeql-action/upload-sarif@v3 + uses: github/codeql-action/upload-sarif@ce64ddcb0d8d890d2df4a9d1c04ff297367dea2a # v3 with: sarif_file: results.sarif diff --git a/src/offlickr/derive/images.py b/src/offlickr/derive/images.py index d04d006..33e650c 100644 --- a/src/offlickr/derive/images.py +++ b/src/offlickr/derive/images.py @@ -15,7 +15,7 @@ _register_heif() except ImportError: - pass + pass # optional dependency; HEIF support is simply unavailable without it Image.MAX_IMAGE_PIXELS = 400_000_000 # allow large panoramas (default is ~178 MP) diff --git a/tests/test_render/test_pages.py b/tests/test_render/test_pages.py index a91a505..78f41a6 100644 --- a/tests/test_render/test_pages.py +++ b/tests/test_render/test_pages.py @@ -93,7 +93,7 @@ def test_search_js_copied(built_site: Path) -> None: def test_external_links_have_rel(built_site: Path, photo_href: dict[str, str]) -> None: """Every link to flickr.com must have rel='noopener noreferrer external'.""" soup = _parse(built_site / photo_href["10000001"]) - flickr_links = [a for a in soup.find_all("a", href=True) if "flickr.com" in str(a["href"])] + flickr_links = [a for a in soup.find_all("a", href=True) if is_flickr_url(str(a["href"]))] for link in flickr_links: rel = cast(list[str], link.get("rel") or []) assert "noopener" in rel diff --git a/tests/test_render/test_social.py b/tests/test_render/test_social.py index 3d69869..beccb2a 100644 --- a/tests/test_render/test_social.py +++ b/tests/test_render/test_social.py @@ -2,6 +2,8 @@ from bs4 import BeautifulSoup +from offlickr.render.filters import is_flickr_url + def _parse(path: Path) -> BeautifulSoup: return BeautifulSoup(path.read_text(encoding="utf-8"), "html.parser") @@ -26,7 +28,7 @@ def test_groups_index_has_flickr_links(built_site: Path) -> None: links = [ str(a["href"]) for a in soup.find_all("a", href=True) - if "flickr.com" in str(a.get("href", "")) + if is_flickr_url(str(a.get("href", ""))) ] assert len(links) >= 1