Skip to content

Security Audit "requirements are current" check produces false-positive failures on unrelated PRs #3802

Description

@mnriem

Summary

The Security Audit workflow's "Check committed audit requirements are current" step (.github/scripts/check_security_requirements.py) fails on PRs that make no dependency changes. Two independent design issues combine to turn any triggering PR red until someone re-commits the snapshot.

Recent real occurrence: PR #3769 (a code-only presets fix) failed this check — run 30368709737.

Root cause

1. The change-detection gate trips on non-dependency edits (incl. base/head SHA skew).

The gate diffs pyproject.toml between DEPENDENCY_DIFF_BASE (github.event.pull_request.base.sha) and DEPENDENCY_DIFF_HEAD (github.sha, the generated merge commit). In the #3769 run it reported Dependency audit inputs changed: pyproject.toml, yet the PR touches only presets/ and tests. The only pyproject.toml delta in that range was a version-string bump 0.14.3.dev0 -> 0.14.4.dev0 that lives solely in the merge commit (base.sha was still 0.14.3, PR head is 0.14.3). So main advancing between the recorded base.sha and the merge-ref generation misattributes an unrelated version bump to the PR — and a version string has zero effect on dependency resolution.

2. Once triggered, --upgrade guarantees drift.

The regeneration step runs uv pip compile ... --upgrade, which resolves the latest versions at CI runtime and compares byte-for-byte against the committed file. Any transitive dependency released since the snapshot was generated causes a mismatch. Reproduced against main: committed pins annotated-doc==0.0.4, a fresh --upgrade compile now resolves annotated-doc==0.0.5. This makes the check fail on any triggering PR, regardless of content, until the file is regenerated and re-committed.

Impact

  • Contributors get red CI on PRs they didn't cause and can't fix (fork PRs can't easily regenerate + push).
  • Maintainers must periodically re-commit the snapshot purely to chase upstream releases — churn unrelated to the PR under review.

Steps to reproduce

  1. Open any PR that doesn't change dependencies while a transitive dep has a newer release than the committed snapshot.
  2. Ensure the diff range includes a pyproject.toml edit (e.g. a version bump on main) so the gate fires.
  3. The "Check committed audit requirements are current" step fails with "Regenerate .github/security-audit-requirements.txt...".

Proposed fixes (either/both)

  1. Narrow the gate: ignore version-only pyproject.toml changes — key off [project.dependencies] / [project.optional-dependencies] rather than the whole file. This also sidesteps the base/merge SHA skew for version bumps.
  2. Drop --upgrade from the sync check: validate that the committed pins are internally consistent with pyproject.toml (deterministic), and leave "chase latest releases" to the scheduled job, which already does live --upgrade resolution across the matrix. This decouples "is the committed file correct?" from "has a new version shipped since?".

Notes

  • The scheduled dependency-audit-scheduled job already provides live upgrade coverage, so removing --upgrade from the PR gate does not reduce vulnerability detection.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions