From a95270a24b709539cb50c0a18894b291a2091cd1 Mon Sep 17 00:00:00 2001 From: Dustin Ingram Date: Thu, 16 Oct 2025 16:02:49 +0000 Subject: [PATCH] Don't permit pull_request_target for GitHub publishers --- tests/unit/oidc/models/test_github.py | 12 ++++++++++++ warehouse/oidc/models/github.py | 19 ++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/tests/unit/oidc/models/test_github.py b/tests/unit/oidc/models/test_github.py index 7e187b6c9746..3087c686c754 100644 --- a/tests/unit/oidc/models/test_github.py +++ b/tests/unit/oidc/models/test_github.py @@ -433,6 +433,18 @@ def test_check_repository(self, truth, claim, valid): check = github.GitHubPublisher.__required_verifiable_claims__["repository"] assert check(truth, claim, pretend.stub()) == valid + def test_check_event_name_invalid(self): + check = github.GitHubPublisher.__required_verifiable_claims__["event_name"] + + with pytest.raises( + errors.InvalidPublisherError, + match=( + "Publishing from a workflow invoked via 'pull_request_target' " + "is not supported." + ), + ): + check("throwaway", "pull_request_target", pretend.stub()) + @pytest.mark.parametrize( ("claim", "ref", "sha", "valid", "expected"), [ diff --git a/warehouse/oidc/models/github.py b/warehouse/oidc/models/github.py index 121e024604a6..a773c5fd3d76 100644 --- a/warehouse/oidc/models/github.py +++ b/warehouse/oidc/models/github.py @@ -152,6 +152,18 @@ def _check_sub( return f"{org}:{repo}".lower() == ground_truth.lower() +def _check_event_name( + ground_truth: str, signed_claim: str, _all_signed_claims: SignedClaims, **_kwawrgs +) -> bool: + if signed_claim == "pull_request_target": + raise InvalidPublisherError( + "Publishing from a workflow invoked via 'pull_request_target' is " + "not supported." + ) + else: + return True + + class GitHubPublisherMixin: """ Common functionality for both pending and concrete GitHub OIDC publishers. @@ -170,6 +182,7 @@ class GitHubPublisherMixin: "repository_owner_id": check_claim_binary(str.__eq__), "job_workflow_ref": _check_job_workflow_ref, "jti": check_existing_jti, + "event_name": _check_event_name, } __required_unverifiable_claims__: set[str] = {"ref", "sha"} @@ -186,7 +199,6 @@ class GitHubPublisherMixin: "run_attempt", "head_ref", "base_ref", - "event_name", "ref_type", "repository_id", "workflow", @@ -275,6 +287,11 @@ def jti(self) -> str: """Placeholder value for JTI.""" return "placeholder" + @property + def event_name(self) -> str: + """Placeholder value for event_name (not used)""" + return "placeholder" + def publisher_url(self, claims: SignedClaims | None = None) -> str: base = self.publisher_base_url sha = claims.get("sha") if claims else None