Skip to content

Send the PR title with the verify request - #70

Merged
rodchalski merged 3 commits into
mainfrom
claude/send-pr-title
Sep 29, 2026
Merged

rodchalski merged 3 commits into
mainfrom
claude/send-pr-title

Conversation

@rodchalski

@rodchalski rodchalski commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

What

The PP approval page shows a request's title from the request row when PP cannot read the pull request itself (no GitHub App access to the repository in that workspace). POST /api/v1/receipts/verify has accepted an optional prTitle for a while (normalizePrTitle, schema z.string().max(300).optional()); this action never sent one, so those pages fell back to "Authorize production deploy" with no description, even for a PR with a full title and body (seen on this repo's #69).

One env entry and one jq argument:

  • PP_PR_TITLE: ${{ github.event.pull_request.title }} in the step's env, never interpolated into the run: script, since a PR title is attacker-controlled text.
  • --arg prTitle "${PP_PR_TITLE:-}", and the body gains prTitle, or no key at all when the title is empty (the schema rejects null). PP accepts at most 300 UTF-16 units, so the title is cut to 300 code points when each is a single unit, else 150 (an emoji is two units). An over-long title must not fail the gate closed.

No behaviour change for the gate decision; the verify route ignores the field for anything but the request row.

Checked

test/run-tests.sh (the harness that landed with #69, merged into this branch) runs the action's real script with stubbed gh and curl and inspects the exact body sent to PP. New cases:

  • a title with quotes, a newline and a $(...) round-trips as a JSON string and is never executed;
  • an empty title omits the key; a push-mode deploy sends no title;
  • a 400-character title is cut to 300; a 200-emoji title is cut to 150 code points, 300 UTF-16 units.

77 passed locally (bash 3.2, jq 1.7.1). Reverting to a plain 300-code-point cut fails the emoji case. The repo's own gate on this PR fails closed until the request is signed, as intended.

🤖 Generated with Claude Code

The approval page shows a request's title from the request row when PP
cannot read the pull request itself (no GitHub App access to the repository
in that workspace). The verify route has accepted an optional prTitle for a
while; this action never sent one, so those pages fell back to "Authorize
production deploy" with no description, even for a PR with a full title.

The title reaches the script through env, never interpolated into it, since
a PR title is attacker-controlled text, and reaches jq through --arg. PP
accepts at most 300 characters and rejects null, so the value is trimmed to
300 and the key is left out when the title is empty.

Checked locally with jq: a title with quotes and a newline round-trips as a
JSON string; an empty title omits the key; a 400-character title is sent as
300.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@permission-protocol

permission-protocol Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

🔒 Permission Protocol

✅ Approved — human authorization recorded. View receipt
Request: cmun6xl6r000qi4ok1k048x5s · Commit: 01b89e9


Approval brief

Affected flow: Permission Protocol approval page display for pull requests.

Why this change: The approval page shows a generic title when Permission Protocol lacks GitHub App access to read the pull request directly.

What changes for users/operators: The PR title is now sent during verification, allowing the approval page to display the actual PR title instead of a generic fallback.

Blast radius:

  • Affected: Limited to changed files shown in this PR
  • Not indicated: auth, database, billing, secrets

⚠️ What this change risks

This change modifies the GitHub Action infrastructure and shell scripts to pass additional metadata. It includes safeguards against shell injection.

  • Risk: 🔴 High — Infra
  • Impact: If incorrect, the approval page may continue to show generic titles or fail to display the request if the title payload is malformed.
  • Files: action.yml, test/run-tests.sh
  • Status: ✅ Approved — receipt

✅ View authorization receipt →

Authorization recorded; use the checks below as merge/deploy verification evidence.


✅ Verify before authorizing
  • Confirm PP_PR_TITLE is passed via environment variables and not interpolated directly into the shell script.
  • Verify the jq argument --arg prTitle handles empty titles by defaulting to an empty string.
  • Check that the test suite confirms the prTitle field is absent during non-PR events like workflow_dispatch.
📋 Why was this flagged?
  • The PR title is passed to the verification request via a new environment variable and jq argument.
  • The change addresses a fallback issue where the approval page displayed 'Authorize production deploy' without a description.
  • The PR title is handled as attacker-controlled text and passed through env to avoid shell interpolation.
  • Tests were updated to ensure the title field is not present outside of PR events.

🔒 Permission Protocol · Decision: approved with human authorization

@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

✅ Permission Protocol: Approved
View receipt →

rodchalski and others added 2 commits September 29, 2026 15:26
PP rejects a prTitle longer than 300 UTF-16 units. The first version cut at
300 code points, and an emoji counts as two units, so a long emoji-heavy
title could exceed the limit and fail the gate closed with a validation
error. The title is now cut to 300 code points when every code point is a
single unit, else to 150 (at most two units each).

test/run-tests.sh (from #69) now covers the title: quotes, a newline and a
$(...) round-trip as a JSON string without being run; an empty title omits
the key; a long ASCII title is cut to 300; a 200-emoji title is cut to 150
code points, 300 UTF-16 units; a push-mode deploy sends no title. Reverting
to the code-point cap fails the emoji case. 77 passed locally (bash 3.2,
jq 1.7.1).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rodchalski
rodchalski merged commit 788dd7b into main Sep 29, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant