ci(infra): validate release dependencies against PyPI - #5612
Merged
Mason Daugherty (mdrxy) merged 4 commits intoAug 19, 2026
Conversation
Contributor
There was a problem hiding this comment.
This PR introduces unescaped GitHub Actions workflow command injection via _error() and _notice() in check_wheel_dep_freshness.py, where attacker-controlled requires-python values from a PR-modified pyproject.toml can be embedded into ::error annotations without escaping, enabling annotation/log spoofing in CI.
PR-controlled strings (sibling pyproject.toml requires-python, PyPI error messages) flow into ::error/::notice annotations verbatim. A crafted value containing newlines could inject additional runner workflow commands. Percent-escape %, CR, and LF before formatting command strings, per the GitHub Actions annotation spec.
Mason Daugherty (mdrxy)
deleted the
mdrxy/infra/release-dependency-freshness
branch
August 19, 2026 15:13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release PRs now fail before merge when their built wheel needs dependency metadata that has not reached PyPI, or when the wheel cannot be installed from the public index the way
release.ymlinstalls it.Source CI installs sibling packages from local editable paths, which can hide a required release order: a sibling package's source may declare a new Python floor or dependency floor that PyPI's latest published wheel does not yet have. Merging in that state would break the post-merge release install.
The
📦 Check Dependency Freshnessworkflow now, for release PRs only:Requires-Distconstraint against PyPI. For repo-managed dependencies it also verifies the newest eligible PyPI files satisfy the sibling's current Python metadata. Direct URL dependencies fail, since this path verifies PyPI.--index-url https://pypi.org/simple, with Talon getting the same--prerelease allowexception as the release workflow.Non-release PRs get a passing no-op, so the job is safe to require globally.
Demonstration
The check passes on this normal (non-release) PR: workflow run 32184070069.
A live GitHub-hosted failure run is not feasible before merge: pull-request workflows execute from the head branch, so the failing Talon 0.0.4 release PR (#5605) does not contain this code, and a new
workflow_dispatchtrigger is not recognized until it exists on the default branch. Locally, the same check against the built Talon wheel and live PyPI JSON fails with:The clean Python 3.12 install step was exercised separately and resolved 138 packages from PyPI, including
deepagents-code==0.1.57— expected, since the install step proves the public graph resolves while the metadata check catches the unpublished sibling change.Required status
After this lands, a maintainer must add the literal
validate release dependencies against PyPIjob name to themainruleset's required status checks (currently only✅ CI Successis required). The job passes on non-release PRs, so requiring it will not block unrelated PRs.