Skip to content

fix: authenticate summaries with downloaded GitHub App keys - #52

Open
steipete wants to merge 1 commit into
mainfrom
maintenance/sweep-3
Open

steipete wants to merge 1 commit into
mainfrom
maintenance/sweep-3

Conversation

@steipete

@steipete steipete commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes: GitHub summaries silently use anonymous requests when configured with the RSA private key downloaded from a GitHub App, losing installation access and authenticated rate limits.

User Impact

Both GitHub-downloaded PKCS#1 keys and existing PKCS#8 PEM keys authenticate successfully. No key conversion or configuration migration is needed.

Why This Change Was Made

The old parser removed either PEM header but always passed the bytes to a PKCS#8-only importer. Use the Worker’s existing Node crypto compatibility to sign either supported PEM format, removing the manual key parser and base64 encoder.

Evidence

  • Before the fix, the generated PKCS#1 key regression failed (anonymous headers); the PKCS#8 control passed.
  • After the fix, both generated-key cases pass and independently verify the JWT signature, application identity, lifetime and installation exchange request. The focused remote authentication/summary suite passes 25 tests.
  • Independent Codex review: no actionable P0–P2 findings.
  • GitHub documents its downloaded keys as PKCS#1 RSAPrivateKey.
  • Production signing also passes inside local workerd (Wrangler 4.127.1, the repository’s compatibility date and Node compatibility). Generated PKCS#1 and PKCS#8 keys both produce signatures independently verified by Web Crypto. The GitHub token exchange is mocked; no live GitHub access is claimed.
  • Worker and forwarder typechecks and the Worker dry-run build pass on Linux with Bun 1.4.0 and Node.js 24.18.1.
  • Full remote suite: 368 passed with one unchanged artwork test timing out on the small runner. That file then passed both tests (262 seconds) after using the ImageMagick 7 binary directly with one thread, under the original five-minute timeout. No test or assertion was weakened.

Validation commands: bun install --frozen-lockfile in both packages; bun test tests/githubAuth.test.ts tests/githubSummary.test.ts; bun run typecheck in both packages; bun run deploy:dry-run; bun run test; focused recovery with bun test tests/lobsterArtFinalization.test.ts. The additional synthetic Worker proof runs the unchanged authentication code under wrangler dev --local.

Inspectable Worker runtime result

The following line is copied from the successful Linux workerd run, launched with bunx wrangler dev --config tmp/auth-proof/wrangler.json --local --port 8797 and invoked over localhost. The tested production source was unchanged when committed as af2b07dd98da2275cf75eb73dd5e5a323c633208; the run occurred before that commit. The temporary proof Worker imported getGitHubHeaders from the production module.

{"runtime":"workerd","passed":["pkcs1","pkcs8"],"liveGitHub":false}

For each PEM format, the harness intercepted the installation-token exchange and independently verified the produced JWT with a public key imported by Web Crypto. It returned HTTP 500 unless both verification and the synthetic returned authorization header succeeded. These are the corresponding conditions from the executed harness:

verified = String(input) === "https://api.github.com/app/installations/67890/access_tokens"
  && await crypto.subtle.verify(
    "RSASSA-PKCS1-v1_5", publicKey,
    Buffer.from(signature, "base64url"), Buffer.from(`${header}.${payload}`)
  )
// The intercept returns a synthetic installation token with an expired cache time.
const headers = await getGitHubHeaders()
if (!verified || headers.Authorization !== "Bearer synthetic-token")
  return Response.json({ failed: type }, { status: 500 })
passed.push(type)

All key material was generated for this test. The GitHub exchange was mocked; this establishes Worker signing and header behavior, not live GitHub installation access. No keys, JWTs, real tokens, host addresses, or private endpoints are included here.

Exact-head Build and test and CodeQL checks passed.

@clawsweeper

clawsweeper Bot commented Sep 23, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Sep 23, 2026
@clawsweeper

clawsweeper Bot commented Sep 23, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed September 23, 2026, 4:14 AM ET / 08:14 UTC (Revision 2).

ClawSweeper review

What this changes

Use Node-compatible signing for GitHub App authentication so downloaded PKCS#1 keys and existing PKCS#8 keys both work, with regression tests and documentation.

Merge readiness

Ready for maintainer review

The fix remains necessary on main. The added Worker output satisfies the previous proof request, and this review found no blocking correctness or security concerns.

Priority: P2
Reviewed head: af2b07dd98da2275cf75eb73dd5e5a323c633208

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) A focused repair with relevant Worker runtime evidence, compatibility coverage, and no actionable findings.
Proof confidence 🐚 platinum hermit (4/6) Sufficient (live_output): Copied local workerd output exercises the production authentication helper with both PEM formats and independently verifies signatures through Web Crypto before accepting synthetic authorization headers. This resolves the prior proof request for the changed signing behavior; live GitHub access is explicitly unclaimed. No stored-data contract changes.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Verified Sufficient (live_output): Copied local workerd output exercises the production authentication helper with both PEM formats and independently verifies signatures through Web Crypto before accepting synthetic authorization headers. This resolves the prior proof request for the changed signing behavior; live GitHub access is explicitly unclaimed. No stored-data contract changes.
Evidence reviewed 8 items Pinned patch: The introduced delta replaces manual PEM decoding and the PKCS#8-only importer with Node-compatible RSA signing. JWT claims, installation endpoint, token caching, and anonymous fallback remain unchanged.
Still necessary on main: Current main still strips either PEM header but imports the resulting bytes exclusively as PKCS#8. The live branch endpoint confirms the supplied main revision; the releases endpoint returned no releases.
GitHub key format contract: GitHub’s private-key documentation confirms downloaded App keys use PKCS#1 RSAPrivateKey format.
Findings None None.
Security None None.

How this fits together

Hermit’s shared GitHub authentication helper turns configured App credentials into installation-token headers. GitHub summaries and form actions use those headers for GitHub API requests.

flowchart LR
  A[Configured App credentials] --> B[Sign App JWT]
  B --> C[GitHub installation token exchange]
  C --> D{Token available?}
  D -->|Yes| E[Authenticated headers]
  D -->|No| F[Anonymous headers]
  E --> G[Summary and form requests]
  F --> G
Loading

Before merge

None.

Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Production and test delta Production −32 net lines; tests +47 lines The repair removes custom key parsing while adding independent signature checks for both supported formats.

Technical review

Best possible solution:

Keep one shared signer that accepts both supported PEM formats while preserving existing installation access, JWT claims, and fallback behavior.

Do we have a high-confidence way to reproduce the issue?

Yes, source establishes the failure: main passes PKCS#1 bytes to a PKCS#8-only importer and catches the error as anonymous fallback. This review did not execute a reproduction.

Is this the best way to solve the issue?

Yes. Using the Worker’s existing Node crypto support removes the faulty parser, and the supplied runtime evidence covers both downloaded keys and the existing PKCS#8 path.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against e5bc0b0bb5d4.

Labels

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. Copied local workerd output exercises the production authentication helper with both PEM formats and independently verifies signatures through Web Crypto before accepting synthetic authorization headers. This resolves the prior proof request for the changed signing behavior; live GitHub access is explicitly unclaimed. No stored-data contract changes.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): Copied local workerd output exercises the production authentication helper with both PEM formats and independently verifies signatures through Web Crypto before accepting synthetic authorization headers. This resolves the prior proof request for the changed signing behavior; live GitHub access is explicitly unclaimed. No stored-data contract changes.
  • remove rating: 🦐 gold shrimp: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.
  • remove status: 📣 needs proof: Current PR status label is status: 👀 ready for maintainer look.

Label justifications:

  • P2: Repairs configured GitHub App authentication for downloaded keys with a focused compatibility-preserving change.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): Copied local workerd output exercises the production authentication helper with both PEM formats and independently verifies signatures through Web Crypto before accepting synthetic authorization headers. This resolves the prior proof request for the changed signing behavior; live GitHub access is explicitly unclaimed. No stored-data contract changes.
  • proof: sufficient: Contributor real behavior proof is sufficient. Copied local workerd output exercises the production authentication helper with both PEM formats and independently verifies signatures through Web Crypto before accepting synthetic authorization headers. This resolves the prior proof request for the changed signing behavior; live GitHub access is explicitly unclaimed. No stored-data contract changes.

Evidence

What I checked:

  • Pinned patch: The introduced delta replaces manual PEM decoding and the PKCS#8-only importer with Node-compatible RSA signing. JWT claims, installation endpoint, token caching, and anonymous fallback remain unchanged. (src/utils/githubAuth.ts:11, af2b07dd98da)
  • Still necessary on main: Current main still strips either PEM header but imports the resulting bytes exclusively as PKCS#8. The live branch endpoint confirms the supplied main revision; the releases endpoint returned no releases. (src/utils/githubAuth.ts:41, e5bc0b0bb5d4)
  • GitHub key format contract: GitHub’s private-key documentation confirms downloaded App keys use PKCS#1 RSAPrivateKey format.
  • Production runtime compatibility: The Worker already enables nodejs_compat and environment population; the patch adds no runtime flag or package dependency. (wrangler.jsonc:24, af2b07dd98da)
  • Previous proof request resolved: The supplied body snapshot, sourceRevision a6b6250d48d9d113b0f530018d1f03ad0555f360619129d45ed18afbec17d4c2, includes copied local workerd output reporting both pkcs1 and pkcs8 passed. It identifies the production getGitHubHeaders entrypoint, ties unchanged source to the reviewed commit, and supplies the executed independent Web Crypto verification and authorization-header conditions. The GitHub exchange is explicitly synthetic. This addresses the prior request to attach inspectable runtime output without claiming live installation access. (src/utils/githubAuth.ts:20, af2b07dd98da)
  • Regression and compatibility coverage: Two generated-key cases verify JWT signatures, issuer, lifetime, installation endpoint, POST method, and returned authorization headers. PKCS#8 remains the compatibility control. Tests were inspected, not executed during this read-only review. (tests/githubAuth.test.ts:22, af2b07dd98da)

Likely related people:

  • Shadow: Raw commit c16b98b adds src/utils/githubAuth.ts:61 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: c16b98b7ce85; files: src/utils/githubAuth.ts)

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (1 earlier review cycle)
  • reviewed 2026-09-23T07:52:00.785Z sha af2b07d :: needs real behavior proof before merge. :: none

@steipete

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

The PR body now includes the saved workerd result for both key formats and the executed Web Crypto verification condition. The mocked GitHub exchange is explicitly identified. The production source is unchanged, and exact-head build/test and CodeQL checks are green.

@clawsweeper

clawsweeper Bot commented Sep 23, 2026

Copy link
Copy Markdown

🦞👀
Exact review queued.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant