From 14917cde839a508939db3b44d2aef6da1b79de2a Mon Sep 17 00:00:00 2001 From: Vinit Kumar Date: Mon, 25 May 2026 21:11:39 +0530 Subject: [PATCH 1/2] fix: harden repo settings --- .github/dependabot.yml | 6 +++ .github/workflows/build-rust-wheels.yml | 45 +++++++++++----------- .github/workflows/codeql.yml | 11 ++++-- .github/workflows/lint.yml | 11 ++++-- .github/workflows/publish-to-live-pypi.yml | 9 +++-- .github/workflows/publish-to-test-pypi.yml | 9 +++-- .github/workflows/pythonpackage.yml | 17 ++++---- .github/workflows/rust-ci.yml | 19 +++++---- lat.md/architecture.md | 6 +++ 9 files changed, 79 insertions(+), 54 deletions(-) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..ca79ca5 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly diff --git a/.github/workflows/build-rust-wheels.yml b/.github/workflows/build-rust-wheels.yml index 8325170..55705c8 100644 --- a/.github/workflows/build-rust-wheels.yml +++ b/.github/workflows/build-rust-wheels.yml @@ -16,6 +16,9 @@ env: PACKAGE_NAME: json2xml_rs PYTHON_VERSION: '3.12' +permissions: + contents: read + jobs: # Build wheels for Linux linux: @@ -24,14 +27,14 @@ jobs: matrix: target: [x86_64, aarch64] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - uses: actions/setup-python@v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: ${{ env.PYTHON_VERSION }} - name: Build wheels - uses: PyO3/maturin-action@v1 + uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1 with: target: ${{ matrix.target }} args: --release --out dist --find-interpreter @@ -40,7 +43,7 @@ jobs: working-directory: rust - name: Upload wheels - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: wheels-linux-${{ matrix.target }} path: rust/dist @@ -52,15 +55,15 @@ jobs: matrix: target: [x64] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - uses: actions/setup-python@v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: ${{ env.PYTHON_VERSION }} architecture: ${{ matrix.target }} - name: Build wheels - uses: PyO3/maturin-action@v1 + uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1 with: target: ${{ matrix.target == 'x64' && 'x86_64-pc-windows-msvc' || 'i686-pc-windows-msvc' }} args: --release --out dist --find-interpreter @@ -68,7 +71,7 @@ jobs: working-directory: rust - name: Upload wheels - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: wheels-windows-${{ matrix.target }} path: rust/dist @@ -80,14 +83,14 @@ jobs: matrix: target: [x86_64, aarch64] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - uses: actions/setup-python@v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: ${{ env.PYTHON_VERSION }} - name: Build wheels - uses: PyO3/maturin-action@v1 + uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1 with: target: ${{ matrix.target == 'x86_64' && 'x86_64-apple-darwin' || 'aarch64-apple-darwin' }} args: --release --out dist --find-interpreter @@ -95,7 +98,7 @@ jobs: working-directory: rust - name: Upload wheels - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: wheels-macos-${{ matrix.target }} path: rust/dist @@ -104,17 +107,17 @@ jobs: sdist: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Build sdist - uses: PyO3/maturin-action@v1 + uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1 with: command: sdist args: --out dist working-directory: rust - name: Upload sdist - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: wheels-sdist path: rust/dist @@ -128,12 +131,10 @@ jobs: environment: name: pypi url: https://pypi.org/project/json2xml-rs/ - permissions: - id-token: write # Required for trusted publishing steps: - name: Download all artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: pattern: wheels-* path: dist @@ -143,7 +144,7 @@ jobs: run: ls -la dist/ - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 with: password: ${{ secrets.PYPI_API_TOKEN_RUST }} skip-existing: true @@ -159,14 +160,14 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] python-version: ['3.10', '3.11', '3.12', '3.13'] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - uses: actions/setup-python@v5 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: ${{ matrix.python-version }} - name: Download wheels - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: pattern: wheels-* path: dist diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 50bcf48..21792df 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -8,6 +8,9 @@ on: schedule: - cron: "9 20 * * 5" +permissions: + contents: read + jobs: analyze: name: Analyze @@ -24,18 +27,18 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@03e4368ac7daa2bd82b3e85262f3bf87ee112f57 # v3 with: languages: ${{ matrix.language }} queries: +security-and-quality - name: Autobuild - uses: github/codeql-action/autobuild@v3 + uses: github/codeql-action/autobuild@03e4368ac7daa2bd82b3e85262f3bf87ee112f57 # v3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@03e4368ac7daa2bd82b3e85262f3bf87ee112f57 # v3 with: category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0a88c20..25e4800 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -6,15 +6,18 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: + contents: read + jobs: ruff: name: ruff runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version: "3.13" cache: 'pip' @@ -32,9 +35,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version: '3.13' - name: Install the latest version of uv diff --git a/.github/workflows/publish-to-live-pypi.yml b/.github/workflows/publish-to-live-pypi.yml index 7080ce0..56bcf6f 100644 --- a/.github/workflows/publish-to-live-pypi.yml +++ b/.github/workflows/publish-to-live-pypi.yml @@ -5,14 +5,17 @@ on: types: - published +permissions: + contents: read + jobs: build-n-publish: name: Build and publish Python 🐍 distributions 📦 to pypi runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Set up Python 3.12 - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version: '3.12' @@ -33,7 +36,7 @@ jobs: - name: Publish distribution 📦 to PyPI if: startsWith(github.ref, 'refs/tags') - uses: pypa/gh-action-pypi-publish@release/v1 + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/publish-to-test-pypi.yml b/.github/workflows/publish-to-test-pypi.yml index 63b1e64..911c69a 100644 --- a/.github/workflows/publish-to-test-pypi.yml +++ b/.github/workflows/publish-to-test-pypi.yml @@ -6,14 +6,17 @@ on: - 'develop' - 'release/**' +permissions: + contents: read + jobs: build-n-publish: name: Build and publish Python 🐍 distributions 📦 to TestPyPI runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Set up Python 3.12 - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version: '3.12' @@ -33,7 +36,7 @@ jobs: . - name: Publish distribution 📦 to Test PyPI - uses: pypa/gh-action-pypi-publish@release/v1 + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 with: user: __token__ password: ${{ secrets.TEST_PYPI_API_TOKEN }} diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 4949054..be8ccc5 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -15,8 +15,6 @@ on: permissions: contents: read - checks: write # For test results - pull-requests: write # For codecov concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -36,12 +34,12 @@ jobs: "ubuntu-24.04-arm" ] steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: persist-credentials: false - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version: ${{ matrix.python-version }} allow-prereleases: true @@ -53,7 +51,7 @@ jobs: python -c "import sys; print('Free-threading enabled:', not sys._is_gil_enabled() if hasattr(sys, '_is_gil_enabled') else False)" - name: Install uv - uses: astral-sh/setup-uv@v6 + uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6 with: enable-cache: true cache-dependency-glob: | @@ -76,7 +74,7 @@ jobs: PYTHONPATH: ${{ github.workspace }} - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5 if: success() with: directory: ./coverage/reports/ @@ -94,17 +92,17 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: persist-credentials: false - name: Set up Python 3.12 - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version: '3.12' - name: Install uv - uses: astral-sh/setup-uv@v6 + uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6 with: enable-cache: true cache-dependency-glob: | @@ -118,4 +116,3 @@ jobs: - name: Run ruff run: uvx ruff check json2xml tests - diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index 5028607..514942a 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -18,15 +18,18 @@ on: env: CARGO_TERM_COLOR: always +permissions: + contents: read + jobs: rust-lint: name: Rust Lint & Format runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1 + uses: actions-rust-lang/setup-rust-toolchain@46268bd060767258de96ed93c1251119784f2ab6 # v1 with: components: rustfmt, clippy @@ -51,15 +54,15 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] python-version: ['3.10', '3.11', '3.12', '3.13'] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: ${{ matrix.python-version }} - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1 + uses: actions-rust-lang/setup-rust-toolchain@46268bd060767258de96ed93c1251119784f2ab6 # v1 - name: Install maturin run: pip install maturin @@ -95,15 +98,15 @@ jobs: # Only run benchmarks on push to main/master or manual trigger, not on PRs if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: '3.12' - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1 + uses: actions-rust-lang/setup-rust-toolchain@46268bd060767258de96ed93c1251119784f2ab6 # v1 - name: Install maturin run: pip install maturin diff --git a/lat.md/architecture.md b/lat.md/architecture.md index 705d250..7a1105e 100644 --- a/lat.md/architecture.md +++ b/lat.md/architecture.md @@ -34,6 +34,12 @@ Dependency floors and lockfiles keep known vulnerable packages out of runtime an Runtime dependencies are declared in `pyproject.toml` and mirrored by `uv.lock`; legacy requirements inputs remain pinned for tooling that still consumes requirements files. Security fixes should update both resolver paths so `uv audit` and requirements-based installs agree. +## Workflow supply-chain hardening + +GitHub Actions workflows run with read-only tokens by default and use full SHA pins so third-party action updates are explicit. + +The `.github/workflows/` files declare the minimum `permissions:` scopes needed by each workflow, with CodeQL retaining `security-events: write` for result upload. Action references are pinned to immutable commits with the upstream tag retained in comments for reviewability, and `.github/dependabot.yml` checks the `github-actions` ecosystem weekly so those pins do not silently age. + ## CLI entrypoint The CLI is a thin adapter that parses options, resolves one input source, and forwards those options into the same converter used by the library API. From 89a25b94f47b915769f27991be706ce2566c8c5c Mon Sep 17 00:00:00 2001 From: Vinit Kumar Date: Mon, 25 May 2026 21:16:51 +0530 Subject: [PATCH 2/2] fix: sufficient permission for security events --- .github/workflows/codeql.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 21792df..403bd22 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -10,6 +10,7 @@ on: permissions: contents: read + security-events: write jobs: analyze: