Workflow protections GA: keep the Sume key off fork PR runs
GitHub's workflow execution protections are GA. Pair them with a Sume workflow that only runs on push, schedule or dispatch, so a fork PR never sees the key.

Should a pull request from a fork ever be able to spend your Sume credits? No. The simplest rule is that the job holding SUME_API_KEY never runs for a pull request at all. GitHub's workflow execution protections, which went generally available on September 17, give you a policy layer that enforces rules of this kind across a repository or organization (read 2026-10-04). This post shows the workflow shape that makes the rule true on its own, and where the new protections add a second lock.
Sume's authentication docs are blunt about why this matters: an API key's scopes are fixed when you create it, and a key that shows up in logs, screenshots or tickets should be rotated. A leaked key on a paid API is a billing problem, not just a security one.
What the GA release adds
According to the changelog, workflow execution protections let admins set rules by actor and by event, and the general availability release adds targeting by workflow file, insights, a REST API, and an evaluate mode for trying a rule before it blocks anything (read 2026-10-04). It also describes a default protection against the pull_request_target event in public repositories.
That last item is the one that touches paid APIs most. pull_request_target runs in the context of the base repository, which is where secrets live, while the code under test can come from a fork. A workflow that calls a paid API from that trigger is the classic way a key gets read by someone else's code.
| Capability | Why it matters for a Sume key |
|---|---|
| Rules by actor | Limit who can start a workflow that has the secret |
| Rules by event | Block the events that carry fork code into a secret-bearing job |
| Workflow-file targeting | Apply a rule only to the file that calls Sume |
| Evaluate mode | See what a rule would have blocked before enforcing it |
| REST API and insights | Audit the policy instead of trusting a settings page |
A workflow that never needs the policy to save it
Policy is a backstop. The workflow itself should only listen to events where the code is yours. Below, the Sume job runs on a push to main, on a weekly schedule, and on manual dispatch. There is no pull_request or pull_request_target trigger, so there is no fork path to the secret to begin with.
The step submits nothing paid. It reads GET /v1/balance and fails the job when the available balance is below a floor you choose, which is a useful gate before a batch step runs. Sume documents /v1/balance as a free read. Only one credential header is sent, because sending both Authorization and x-api-key returns 401 unauthorized.
name: sume-balance-gate
on:
push:
branches: [main]
schedule:
- cron: '5 7 * * 1'
workflow_dispatch:
permissions:
contents: read
jobs:
balance:
runs-on: ubuntu-latest
steps:
- name: Check balance
env:
SUME_API_KEY: ${{ secrets.SUME_API_KEY }}
run: |
set -eu
code=$(curl -sS -o /dev/null -w '%{http_code}' \
https://api.sume.com/v1/balance \
-H "x-api-key: $SUME_API_KEY")
echo "GET /v1/balance -> $code"
test "$code" = 200Where cache-mode fits
A second GitHub change from September 10 is relevant in a different way. The cache-mode setting controls whether a job can read from, write to, both, or neither of the Actions cache, with values read, write, write-only and none, and a job-level setting overrides a workflow-level one. Per the changelog, untrusted events default to read (read 2026-10-04).
If your Sume workflow caches downloaded tools, that default means a fork-triggered run cannot poison the cache your keyed job later restores. This post does not show cache-mode YAML, because the changelog entry describes the values without giving the exact syntax; take that from GitHub's documentation. The point for Sume users is conceptual: a cache is a shared surface, and the job that holds a paid key should only restore from caches written by trusted events.
A short review list
Run through this once per repository that calls Sume. Each item is a check you can finish in a few minutes, and the evaluate mode in the new protections is a safe way to confirm the policy side without blocking anyone.
When a key is found somewhere it should not be, rotate it and review recent usage with GET /v1/usage, which Sume documents as a free read. For retries after a runner failure, see the post on idempotency keys for re-run workflows.
- Search workflow files for
pull_request_targetand for anypull_requestjob that references the secret. - Keep the Sume key in a repository or environment secret, never in a workflow file or an artifact.
- Give the job
permissions: contents: readunless it needs more. - Prefer a key created only for CI, so rotating it affects nothing else.
- Turn on evaluate mode for a new event rule first and read what it would have blocked.
Sources
Related posts
More in Integrations
- Zapier Heal mode on a failed Sume step: keep the idempotency key
Zapier's Agentic Management can fix a failed run. For a Sume step, make sure the fix keeps the Idempotency-Key, or a changed payload returns a 409.
- How to add an MCP server to ChatGPT with developer mode
Turn on ChatGPT developer mode, create an app for the server's URL, and sign in with OAuth. The steps, with Sume's hosted MCP server as the example.
- How to add subtitles to a video in Python
Add subtitles to a video in Python with Requests: POST the video URL to Sume's /v1/video-captions, poll the job, then read the captioned video_url.
- Add Sume to Claude as a custom connector (remote MCP)
Add Sume's hosted MCP server to Claude under Customize > Connectors, see what Sume's OAuth consent grants, and decide whether to allow paid tools.
Written by Sume