Skip to content

feat(plugins): Add top-level API header injection#282

Merged
dcramer merged 4 commits intogetsentry:mainfrom
carderne:static-headers
May 3, 2026
Merged

feat(plugins): Add top-level API header injection#282
dcramer merged 4 commits intogetsentry:mainfrom
carderne:static-headers

Conversation

@carderne
Copy link
Copy Markdown
Contributor

@carderne carderne commented May 2, 2026

Add plugin-level API header injection for providers that authenticate through host-managed HTTP headers. Header-authenticated plugins now declare api-domains and api-headers at the manifest top level, keeping real header values in deployment env and out of sandbox env vars.

Manifest Shape

Header-only providers no longer use a credential type. Env-backed header values use declared ${NAME} placeholders, and API header env vars cannot define defaults.

Before, header auth was modeled as a credential type:

credentials:
  type: static-headers
  api-domains:
    - api.example.com
  api-headers:
    Authorization: ${EXAMPLE_AUTH_HEADER}

After, headers are plugin-level request metadata:

env-vars:
  EXAMPLE_AUTH_HEADER:

api-domains:
  - api.example.com

api-headers:
  Authorization: ${EXAMPLE_AUTH_HEADER}

Credential Interaction

credentials.type stays limited to oauth-bearer and github-app. Existing credentials.api-headers remains only as extra token-backed headers, while top-level API headers can stand alone or combine with token credentials; token credential headers win on overlap.

Runtime Safety

Header transforms are attached by the capability runtime to sandbox bash executions; the model-facing bash schema remains command-only. Eval mode uses deterministic dummy header values so test brokers never read deployment secrets.

Support providers that authenticate with fixed HTTP headers resolved from deployment env instead of OAuth or app-issued bearer tokens.

This lets sandboxed tools call services like Better Stack through the existing host-managed header injection path without exposing real secrets inside the sandbox or requiring changes to the MCP credential model.

Co-Authored-By: OpenAI ChatGPT <chatgpt@openai.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 2, 2026

@carderne is attempting to deploy a commit to the Sentry Team on Vercel.

A member of the Team first needs to authorize it.

@carderne carderne marked this pull request as draft May 2, 2026 20:16
sentry[bot]

This comment was marked as resolved.

cursor[bot]

This comment was marked as resolved.

@dcramer
Copy link
Copy Markdown
Member

dcramer commented May 3, 2026

tbqh i think the goal of this is totally reasonable. will take a look at make sure it hits our stability reqs as sometimes the test suite here isnt capable enough still

dcramer added a commit to carderne/junior that referenced this pull request May 3, 2026
Reject empty static header credential maps during manifest normalization so misconfigured providers fail at load time instead of crashing when a broker issues a lease. Keep optional empty maps omitted for existing credential and MCP config paths, and avoid assuming every credential type has an auth token env name.

Refs getsentryGH-282

Co-Authored-By: GPT-5 Codex <codex@openai.com>
dcramer added a commit to carderne/junior that referenced this pull request May 3, 2026
Reject empty static header credential maps during manifest normalization so misconfigured providers fail at load time instead of crashing when a broker issues a lease. Keep optional empty maps omitted for existing credential and MCP config paths, and avoid assuming every credential type has an auth token env name.

Refs getsentryGH-282

Co-Authored-By: GPT-5 Codex <codex@openai.com>
dcramer added a commit to carderne/junior that referenced this pull request May 3, 2026
Treat api-headers as plugin-level sandbox header injection instead of a credential type. Require header env placeholders to be declared in env-vars, forbid defaults for header secrets, and keep header-only plugins eligible for turn-scoped injection.

Refs getsentryGH-282

Co-Authored-By: GPT-5 Codex <codex@openai.com>
dcramer added a commit to carderne/junior that referenced this pull request May 3, 2026
Treat api-headers as plugin-level sandbox header injection instead of a credential type. Require header env placeholders to be declared in env-vars, forbid defaults for header secrets, and keep header-only plugins eligible for turn-scoped injection.

Refs getsentryGH-282

Co-Authored-By: GPT-5 Codex <codex@openai.com>
cursor[bot]

This comment was marked as resolved.

dcramer added a commit to carderne/junior that referenced this pull request May 3, 2026
Treat api-headers as plugin-level sandbox header injection instead of a credential type. Require header env placeholders to be declared in env-vars, forbid defaults for header secrets, and keep header-only plugins eligible for turn-scoped injection.

Refs getsentryGH-282

Co-Authored-By: GPT-5 Codex <codex@openai.com>
cursor[bot]

This comment was marked as resolved.

Treat api-headers as plugin-level sandbox header injection instead of a credential type. Require header env placeholders to be declared in env-vars, forbid defaults for header secrets, and keep header-only plugins eligible for turn-scoped injection.

Refs getsentryGH-282

Co-Authored-By: GPT-5 Codex <codex@openai.com>
@carderne
Copy link
Copy Markdown
Contributor Author

carderne commented May 3, 2026

@dcramer great. Happy for you to implement this however you like, or equally happy to take some nudges on this PR (just mention because going by commit history it seems a relatively private project).

Either way I'll look a bit closer at the code this week, since I'm using this in production now.

Two notes:

  1. The name static-headers is a bit weird since they're actually dynamic (just less dynamic than the others).
  2. It doesn't interpolate, just replace. Might be worth extending to support that, probably expected...
  api-headers:
    Authorization: "Bearer $TOKEN" // DOES NOT work
    Authorization: "$AUTH_HEADER"  // works

@dcramer
Copy link
Copy Markdown
Member

dcramer commented May 3, 2026

im dropping the credentials bit here and just allow headers to be configured like this - should simplify the whole thing

dont think there's any reason to require the extra step. just working through quality checks rn

dcramer and others added 2 commits May 3, 2026 11:40
Document how token-backed credential headers interact with top-level API headers and rename the credential-header test for accuracy.

Co-Authored-By: GPT-5 Codex <codex@openai.com>
Pin how plugin-level API headers merge with token-backed credential headers and update the plugin security contract wording.

Co-Authored-By: GPT-5 Codex <codex@openai.com>
@dcramer
Copy link
Copy Markdown
Member

dcramer commented May 3, 2026

Final implementation outcome after the cleanup pass:

This PR no longer adds a new credential type. The final manifest shape is top-level API header injection:

env-vars:
  EXAMPLE_AUTH_HEADER:

api-domains:
  - api.example.com

api-headers:
  Authorization: ${EXAMPLE_AUTH_HEADER}
  X-Api-Version: "2026-01-01"

Key contract:

  • credentials.type remains limited to oauth-bearer and github-app.
  • Header-only providers use top-level api-headers and api-domains; if headers exist, the runtime creates a broker and injects matching sandbox header transforms.
  • Header values can reference declared ${ENV_VAR} placeholders, matching the MCP env-var pattern. API header env vars cannot declare defaults because they may carry secrets.
  • Literal header values are also supported.
  • Existing credentials.api-headers still works only as extra headers alongside token-backed credentials, with Authorization reserved there.
  • When top-level headers are combined with token-backed credentials, credential headers are applied last and win on duplicate header names for the same domain.

Security/runtime notes:

  • Real secret values stay host-side and are delivered only through Vercel Sandbox network header transforms.
  • The model-facing bash tool still only accepts command; header transforms are attached by the runtime, not by model input.
  • Eval mode uses deterministic dummy header values instead of reading deployment secrets.

Validation done locally:

  • targeted plugin/capability tests: 8 files, 44 tests passed
  • pnpm typecheck passed
  • pnpm docs:check passed after docs changes

Remaining check noise is external to this patch: Vercel requires fork deploy authorization, and Warden can fail on fork PRs when required app secrets are unavailable.

@dcramer dcramer marked this pull request as ready for review May 3, 2026 19:27
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 5 additional findings.

Open in Devin Review

@dcramer dcramer changed the title feat(plugins): add static header credentials feat(plugins): Add top-level API header injection May 3, 2026
@dcramer dcramer merged commit 5affd71 into getsentry:main May 3, 2026
8 of 10 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.

2 participants