Skip to content

fix: tighten workflow permissions, add security hardening, and fix uv tool invocations#136

Merged
jmeridth merged 2 commits intomainfrom
fix/security-hardening-uv-invocations
Mar 14, 2026
Merged

fix: tighten workflow permissions, add security hardening, and fix uv tool invocations#136
jmeridth merged 2 commits intomainfrom
fix/security-hardening-uv-invocations

Conversation

@jmeridth
Copy link
Collaborator

What

Move elevated permissions from workflow level to job level across four workflows (mark-ready-when-ready, scorecard, stale, contributor_report) so each job only holds the permissions it actually needs. Add step-security/harden-runner to all eight workflows that define steps. Add CodeQL SAST scanning and dependency-review workflows. Add pre-commit configuration with gitleaks, formatting hooks, and local linter hooks. Fix Makefile to invoke flake8, pytest, pylint, and mypy via uv run python -m since they lack console script entry points in the uv venv. Upgrade PyJWT from 2.11.0 to 2.12.1 to address CVE-2026-32597. Add Copilot setup steps workflow and copilot-instructions.md.

Why

Workflow-level write permissions apply to every job in the workflow, granting broader access than necessary. Moving them to job level follows the principle of least privilege. Harden-runner audits outbound network calls from GitHub-hosted runners, improving supply-chain visibility. CodeQL and dependency-review close gaps in static analysis and vulnerable-dependency detection. The Makefile commands failed under uv because those packages don't install console scripts; python -m ensures the tools are always found. PyJWT <= 2.11.0 doesn't validate the RFC 7515 crit header parameter (CVSS 7.5).

Notes

  • The uv run to uv run python -m change also affects CI since python-package calls make lint and make test
  • release.yml, auto-labeler.yml, and pr-title.yml use reusable workflows at the job level so harden-runner cannot be added there; it must go in the reusable workflow definitions instead
  • The scorecard workflow previously used permissions: read-all which granted read access to all scopes; now explicitly scoped to only what's needed
  • PyJWT is a transitive dependency; verify downstream consumers aren't relying on the old crit-header-ignored behavior
  • copilot-instructions.md was adapted from issue-metrics to reflect this repo's structure and dependencies

@jmeridth jmeridth requested a review from zkoppert as a code owner March 14, 2026 02:25
Copilot AI review requested due to automatic review settings March 14, 2026 02:25
@github-actions github-actions bot added the fix label Mar 14, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Tightens GitHub Actions workflow permissions to job level, adds step-security/harden-runner to all workflows with steps, introduces CodeQL and dependency-review workflows, adds pre-commit configuration, fixes uv run tool invocations to use python -m, and upgrades PyJWT to 2.12.1.

Changes:

  • Moved elevated permissions from workflow level to job level and added harden-runner across all workflows
  • Added CodeQL, dependency-review, copilot-setup-steps workflows and copilot-instructions
  • Fixed Makefile/pre-commit to use uv run python -m for tools without console script entry points; upgraded PyJWT

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
Makefile Switch tool invocations to uv run python -m; removed --fail-under from pylint
.pre-commit-config.yaml New pre-commit config with gitleaks, formatting, and local linter hooks
.github/workflows/stale.yaml Move permissions to job level, add harden-runner
.github/workflows/scorecard.yml Replace read-all with explicit scoped permissions, add harden-runner
.github/workflows/python-package.yml Add harden-runner
.github/workflows/mark-ready-when-ready.yml Move permissions to job level, add harden-runner
.github/workflows/linter.yaml Add harden-runner
.github/workflows/docker-image.yml Add harden-runner
.github/workflows/dependency-review.yml New dependency review workflow
.github/workflows/copilot-setup-steps.yml New Copilot setup steps workflow
.github/workflows/contributor_report.yaml Move permissions to job level, add harden-runner
.github/workflows/codeql.yml New CodeQL scanning workflow
.github/copilot-instructions.md New Copilot instructions for the repo
uv.lock Upgrade PyJWT 2.11.0 → 2.12.1

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

… tool invocations

## What

Move elevated permissions from workflow level to job level across four workflows
(mark-ready-when-ready, scorecard, stale, contributor_report) so each job only
holds the permissions it actually needs. Add step-security/harden-runner to all
eight workflows that define steps. Add CodeQL SAST scanning and dependency-review
workflows. Add pre-commit configuration with gitleaks, formatting hooks, and local
linter hooks. Fix Makefile to invoke flake8, pytest, pylint, and mypy via
`uv run python -m` since they lack console script entry points in the uv venv.
Upgrade PyJWT from 2.11.0 to 2.12.1 to address CVE-2026-32597. Add Copilot
setup steps workflow and copilot-instructions.md.

## Why

Workflow-level write permissions apply to every job in the workflow, granting
broader access than necessary. Moving them to job level follows the principle of
least privilege. Harden-runner audits outbound network calls from GitHub-hosted
runners, improving supply-chain visibility. CodeQL and dependency-review close
gaps in static analysis and vulnerable-dependency detection. The Makefile commands
failed under uv because those packages don't install console scripts; `python -m`
ensures the tools are always found. PyJWT <= 2.11.0 doesn't validate the RFC 7515
`crit` header parameter (CVSS 7.5).

## Notes

- The `uv run` to `uv run python -m` change also affects CI since python-package calls `make lint` and `make test`
- release.yml, auto-labeler.yml, and pr-title.yml use reusable workflows at the job level so harden-runner cannot be added there; it must go in the reusable workflow definitions instead
- The scorecard workflow previously used `permissions: read-all` which granted read access to all scopes; now explicitly scoped to only what's needed
- PyJWT is a transitive dependency; verify downstream consumers aren't relying on the old crit-header-ignored behavior
- copilot-instructions.md was adapted from issue-metrics to reflect this repo's structure and dependencies

Signed-off-by: jmeridth <jmeridth@gmail.com>
@jmeridth jmeridth force-pushed the fix/security-hardening-uv-invocations branch from 6e05cec to f9b64b9 Compare March 14, 2026 02:37
@zkoppert
Copy link
Collaborator

The Autobuild step in codeql.yml is a no-op for Python since CodeQL analyzes source directly without a build step. Please remove the Autobuild step and its surrounding comments to keep the workflow clean.

Signed-off-by: jmeridth <jmeridth@gmail.com>
Copilot AI review requested due to automatic review settings March 14, 2026 03:59
Copy link
Collaborator

@zkoppert zkoppert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - minor note: consider removing the Autobuild step from codeql.yml since it's a no-op for Python.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Tightens GitHub Actions workflow permissions to job level (least privilege), adds step-security/harden-runner to all workflows with steps, introduces CodeQL and dependency-review workflows, adds pre-commit config, fixes Makefile tool invocations for uv, and upgrades PyJWT to 2.12.1.

Changes:

  • Move elevated permissions from workflow level to job level in four workflows; add harden-runner to all eight workflows
  • Add CodeQL, dependency-review, and copilot-setup-steps workflows plus copilot-instructions.md and .pre-commit-config.yaml
  • Fix Makefile to use uv run python -m for flake8/pytest/pylint/mypy; upgrade PyJWT 2.11.0 → 2.12.1

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
.github/workflows/stale.yaml Move permissions to job level, add harden-runner
.github/workflows/scorecard.yml Replace read-all with explicit scopes, add harden-runner
.github/workflows/mark-ready-when-ready.yml Move permissions to job level, add harden-runner
.github/workflows/contributor_report.yaml Move permissions to job level, add harden-runner
.github/workflows/python-package.yml Add harden-runner
.github/workflows/linter.yaml Add harden-runner
.github/workflows/docker-image.yml Add harden-runner
.github/workflows/dependency-review.yml New workflow for dependency vulnerability scanning
.github/workflows/codeql.yml New CodeQL SAST workflow
.github/workflows/copilot-setup-steps.yml New Copilot setup steps workflow
.github/copilot-instructions.md New Copilot instructions for the repo
.pre-commit-config.yaml New pre-commit config with gitleaks, formatting, and linter hooks
Makefile Switch to uv run python -m for tool invocations
uv.lock Upgrade PyJWT 2.11.0 → 2.12.1

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@jmeridth jmeridth merged commit f143045 into main Mar 14, 2026
42 checks passed
@jmeridth jmeridth deleted the fix/security-hardening-uv-invocations branch March 14, 2026 04:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants