Skip to content

chore(lint): Require GitHub plugin requests to use host egress - #2222

Merged
BYK merged 2 commits into
mainfrom
chore/lint-direct-github-requests
Oct 27, 2026
Merged

BYK merged 2 commits into
mainfrom
chore/lint-direct-github-requests

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

#2218 first shipped a GitHub plugin hook that minted its own installation token and called api.github.com directly. That skipped Junior's credential proxy: egress policy, grant selection, the shared credential lease, and egress audit logs. Review caught it, and #2218 now reads through ctx.egress. This adds lint rules so the next one fails CI instead of relying on review.

The rules are built-in oxlint rules, applied to packages/junior-github/src:

  • no-restricted-imports bans githubRequest and issueInstallationToken from credential-support.js.
  • no-restricted-globals bans fetch, and no-restricted-properties bans globalThis.fetch.

The error tells the author to use ctx.egress.fetch. Only credential-support.ts and webhooks/ may call GitHub directly. A webhook delivery has no Turn and no egress context.

These rules work per file, so this PR also moves the direct GitHub calls out of plugin.ts:

  • The webhook commit-page and feedback-reaction requests move to webhooks/installation-requests.ts.
  • The issueCredential body moves to issueGitHubCredential in credential-support.ts. It needs an IssueCredentialHookContext, so other hooks cannot easily misuse it. The installation and user credential helpers are no longer exported.

The rules live in the shared packages/junior/.oxlintrc.json with **/junior-github/... globs. I first tried a package config that extends the shared one, but oxlint 1.79 then fails to load the anti-slop JS plugin. The relative jsPlugins path does not resolve when the base config is in another directory. Override globs also resolve from the config's own directory, so the globs must use **/junior-github.

Verification:

  • pnpm lint, pnpm typecheck, and the GitHub plugin tests (233) pass.
  • A probe file in src/ that imports issueInstallationToken and githubRequest (direct and nested paths) and calls fetch and globalThis.fetch gets 8 errors. That is the same pattern as the original feat(conversations): Name conversations after linked issues #2218 bypass. The new webhooks/installation-requests.ts passes.

The rules only cover the GitHub plugin. Someone could still get around them, for example by re-exporting a function from another module. The rules are there to catch honest mistakes, not to enforce a security boundary.

If #2218 merges first, this branch needs a rebase. Both change the imports in plugin.ts.

via BYK.

--

View Junior Session in Sentry

Add an ast-grep rule that rejects direct GitHub tokens and requests in
the GitHub plugin. Code must use ctx.egress.fetch, so egress policy,
grant selection, the shared credential lease, and egress audit logs
apply.

Credential issuing and webhook routes may still call GitHub directly.
They run without a Turn or an egress context.

Co-Authored-By: BYK <burak.kaya@sentry.io>
@vercel

vercel Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
junior-docs Ready Ready Preview Oct 25, 2026 4:08pm UTC

Request Review

Replace the ast-grep rule with built-in oxlint rules. In the GitHub
plugin source, no-restricted-imports bans githubRequest and
issueInstallationToken, and no-restricted-globals and
no-restricted-properties ban fetch. Only credential-support.ts and
webhooks/ may call GitHub directly.

These rules work per file, so move the direct GitHub calls out of
plugin.ts. The webhook commit-page and feedback-reaction requests move to
webhooks/installation-requests.ts. The issueCredential body moves to
issueGitHubCredential in credential-support.ts, and the installation and
user credential helpers are no longer exported.

The rules live in the shared oxlint config with **/junior-github globs.
A package config that extends it fails in oxlint 1.79, because relative
jsPlugins paths do not resolve from a base config in another directory.

Co-Authored-By: BYK <burak.kaya@sentry.io>
@BYK
BYK requested a review from dcramer October 25, 2026 16:19
@BYK
BYK merged commit 11d1221 into main Oct 27, 2026
44 checks passed
@BYK
BYK deleted the chore/lint-direct-github-requests branch October 27, 2026 17:28

This branch was successfully deployed

1 active deployment
Preview – junior-docs — 9f6baa41 Deployed Oct 25, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: high PR risk score: high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant