Skip to content

ci(e2e): wire CF mint secrets into behaviour job - #5181

Merged
waynesun09 merged 2 commits into
fullsend-ai:mainfrom
ifireball:ci/5167-wire-cf-mint-secrets-behaviour
Jul 16, 2026
Merged

ci(e2e): wire CF mint secrets into behaviour job#5181
waynesun09 merged 2 commits into
fullsend-ai:mainfrom
ifireball:ci/5167-wire-cf-mint-secrets-behaviour

Conversation

@ifireball

Copy link
Copy Markdown
Member

Summary

Wire the existing repo secrets for CF mint BT (TEST_*_PEM and Cloudflare credentials) into the behaviour job so make behaviour-test can deploy a temporary Worker mint in CI. This is workflow wiring only (prerequisite for #5109).

Related Issue

Fixes #5167

Changes

  • Add TEST_FULLSEND_PEM, TEST_TRIAGE_PEM, TEST_CODER_PEM, TEST_REVIEW_PEM, TEST_RETRO_PEM, TEST_PRIORITIZE_PEM, CLOUDFLARE_ACCOUNT_ID, and CLOUDFLARE_API_TOKEN to the "Run behaviour tests" step env in .github/workflows/e2e.yml
  • Authorization is unchanged (pull_request_target + gate job)

Testing

Checklist

  • PR title follows Conventional Commits (correct type, ! for breaking changes)
  • Commits are signed off (DCO) — human and human-directed agent sessions only
  • I wrote this contribution myself and can explain all changes in it

Made with Cursor

Expose TEST_*_PEM and Cloudflare credentials to make behaviour-test so
temp CF Worker mint deploys can authenticate in CI (fullsend-ai#5167).

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@ifireball
ifireball requested a review from a team as a code owner July 16, 2026 13:30
@ifireball ifireball self-assigned this Jul 16, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Jul 16, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 1:31 PM UTC · Completed 1:39 PM UTC
Commit: ba3a6e5 · View workflow run →

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Wire Cloudflare mint secrets into CI behaviour job

⚙️ Configuration changes 🕐 10-20 Minutes

Grey Divider

AI Description

• Expose CF mint PEM and Cloudflare secrets to behaviour test step.
• Allow behaviour CI to deploy temporary Worker mint via make behaviour-test.
• Keep pull_request_target workflow and gate job authorization unchanged.
Diagram

graph TD
  A{{"pull_request_target"}} --> B["Gate job"] --> C["behaviour job"] --> D["Run behaviour tests"] --> E["make behaviour-test"] --> F["Temp Worker mint"] --> G{{"Cloudflare API"}}
  S[("GitHub Secrets")] --> D
  subgraph Legend
    direction LR
    _job["Job/Step"] ~~~ _sec[(Secrets)] ~~~ _ext{{External}}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use a protected GitHub Environment for CF mint secrets
  • ➕ Adds explicit environment protection/audit controls for high-privilege secrets
  • ➕ Can require approvals before exposing Cloudflare credentials
  • ➖ Operational overhead (environment management) and potential CI friction
  • ➖ May require reworking the existing gate-job logic and contributor workflow
2. Wrap secret wiring in a reusable workflow/composite action
  • ➕ Keeps secret export logic centralized and consistent across jobs/workflows
  • ➕ Reduces repetition if other jobs later need the same CF mint deploy capability
  • ➖ More indirection for a one-step change today
  • ➖ Still requires careful scoping to avoid broadening secret exposure

Recommendation: The current approach (injecting the needed secrets into the specific “Run behaviour tests” step) is appropriate as a minimal, auditable wiring change and keeps the secret exposure scoped to the narrowest point. If additional workflows/jobs will need the same Cloudflare mint deploy capability, consider migrating the secret wiring into a reusable workflow/composite action; if security posture needs tightening, consider moving these secrets behind a protected GitHub Environment.

Files changed (1) +9 / -0

Other (1) +9 / -0
e2e.ymlExpose CF mint PEMs and Cloudflare creds to behaviour test step +9/-0

Expose CF mint PEMs and Cloudflare creds to behaviour test step

• Adds TEST_*_PEM role credentials plus CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN to the environment for the “Run behaviour tests” step. This enables make behaviour-test to deploy a temporary Worker mint during CI without changing the workflow’s existing authorization model.

.github/workflows/e2e.yml

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown

Site preview

Preview: https://50b4a04c-site.fullsend-ai.workers.dev

Commit: 2a0bebd4497e53cd0038c440433703a7c8262e1c

@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@qodo-code-review

qodo-code-review Bot commented Jul 16, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 54 rules

Grey Divider


Informational

1. Secrets exposed to PR code ✓ Resolved 🐞 Bug ⛨ Security
Description
The behaviour job now injects CLOUDFLARE_API_TOKEN/CLOUDFLARE_ACCOUNT_ID and TEST_*_PEM into
the make behaviour-test step, which executes code from the PR head checkout under
pull_request_target, so authorized PR code can read/exfiltrate these credentials. This is
especially high impact because the same Cloudflare token is used for Wrangler deployments and the
TEST_*_PEM values are GitHub App private keys.
Code

.github/workflows/e2e.yml[R258-266]

+          # CF mint BT path: temp Worker deploy needs role PEMs + Cloudflare creds
+          TEST_FULLSEND_PEM: ${{ secrets.TEST_FULLSEND_PEM }}
+          TEST_TRIAGE_PEM: ${{ secrets.TEST_TRIAGE_PEM }}
+          TEST_CODER_PEM: ${{ secrets.TEST_CODER_PEM }}
+          TEST_REVIEW_PEM: ${{ secrets.TEST_REVIEW_PEM }}
+          TEST_RETRO_PEM: ${{ secrets.TEST_RETRO_PEM }}
+          TEST_PRIORITIZE_PEM: ${{ secrets.TEST_PRIORITIZE_PEM }}
+          CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
+          CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
Relevance

⭐ Low

Similar “don’t expose secrets to PR head under pull_request_target” suggestion was rejected in PR
#2534; e2e design intentionally runs with secrets (PR #2106).

PR-#2534
PR-#2106

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The workflow is explicitly pull_request_target and checks out PR head SHA before running `make
behaviour-test`; the PR adds Cloudflare credentials and GitHub App PEMs to that step’s environment.
The same Cloudflare token is used by the site deployment workflow for Wrangler deploys, and the docs
identify TEST_*_PEM as GitHub App private keys stored as repo secrets.

.github/workflows/e2e.yml[3-6]
.github/workflows/e2e.yml[44-46]
.github/workflows/e2e.yml[178-235]
.github/workflows/e2e.yml[248-266]
.github/workflows/site-deploy.yml[136-147]
docs/guides/dev/e2e-testing.md[168-193]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `behaviour` job runs untrusted PR-head code (via checkout of `github.event.pull_request.head.sha`) in a `pull_request_target` workflow and now provides it with Cloudflare and GitHub App private-key secrets. This increases the blast radius of any authorized PR run: the PR code can directly access and exfiltrate these secrets.

## Issue Context
- `pull_request_target` workflows run in the base repo context and can access repository secrets.
- The behaviour job checks out PR head and runs `make behaviour-test`.
- `CLOUDFLARE_API_TOKEN` is also used for Wrangler deployments in the site deploy workflow.

## Fix Focus Areas
- Use separate, least-privileged Cloudflare credentials dedicated to behaviour/mint CI (e.g., `E2E_CLOUDFLARE_API_TOKEN`), not the same secret used for site deployments.
- Consider moving these secrets to a protected GitHub Environment (with required reviewers) and attaching the environment to the `behaviour` job, so access is explicitly approved beyond the current label gate.
- Keep secret exposure as narrow as possible (only in the specific step(s) that truly need them).

### References
- .github/workflows/e2e.yml[229-266]
- .github/workflows/site-deploy.yml[136-147]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@fullsend-ai-review

Copy link
Copy Markdown

Review of #5181ci(e2e): wire CF mint secrets into behaviour job

Verdict: approve · 9 lines added across 1 file · purely additive CI wiring

Summary

This PR adds 8 environment variables (6 test GitHub App PEM keys + 2 Cloudflare credentials) to the behaviour job's "Run behaviour tests" step in .github/workflows/e2e.yml. The change is authorized by #5167 and is a prerequisite for #5109.

The change follows the established pattern — the behaviour job already receives GCP secrets (E2E_GCP_PROJECT_ID, E2E_GCP_WIF_PROVIDER) in the same pull_request_target context, behind the same gate authorization. The env var names exactly match the linked issue's specification. YAML indentation and structure are correct.

Dimension summary

Dimension Result
Correctness ✅ No findings — env var names match issue spec, YAML structure valid, no consumers expected yet (follow-up #5109)
Security ✅ Two low-severity observations (see below) — follows established security model
Intent & coherence ✅ Mechanical wiring change, explicitly authorized by #5167
Style & conventions ✅ Follows existing KEY: ${{ secrets.KEY }} pattern
Documentation ✅ No staleness — secrets are already documented in e2e-testing guide
Cross-repo contracts ⏭ Skipped — no exported interfaces or API surfaces modified

Low-severity observations

  1. [permission-expansion] .github/workflows/e2e.yml:258 — Adding 8 secrets to the behaviour job expands the blast radius if the e2e gate is ever bypassed. The TEST_*_PEM secrets are private keys for 6 test GitHub Apps with permissions including administration:write on test pool orgs. This follows the established pattern (GCP secrets are already exposed here) and the gate authorization is the accepted control, but the expanded surface is worth noting.

  2. [secret-exposure] .github/workflows/e2e.yml:265CLOUDFLARE_API_TOKEN is also used in site-deploy.yml for production site deployments (a trusted context). If the same token is used for both production deploys and e2e testing, a gate bypass would grant access to production Cloudflare Workers. Consider verifying this is a separate, test-scoped Cloudflare token — or minting one if not.


Protected paths detected — this PR modifies files under one or more
protected paths. The review agent cannot approve PRs that touch these paths.
A human reviewer must approve this PR.

Protected files in this PR:

  • .github/workflows/e2e.yml

Labels: PR modifies e2e CI workflow to wire mint-related secrets into the behaviour test job.

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

See the review comment for full details.

Comment thread .github/workflows/e2e.yml
Comment thread .github/workflows/e2e.yml Outdated
@fullsend-ai-review fullsend-ai-review Bot added requires-manual-review Review requires human judgment component/ci CI pipelines and checks component/e2e End-to-end tests component/mint Token mint and cross-boundary credentials labels Jul 16, 2026
@waynesun09

Copy link
Copy Markdown
Member

Reviewed this alongside the broader CF mint rollout chain (#5111#5167/this PR → #5109#5115#5116). No other open PR currently depends on this one — the downstream work is still at the issue stage — but flagging two things before merge given the secrets involved:

1. Please confirm CLOUDFLARE_ACCOUNT_ID/CLOUDFLARE_API_TOKEN scope

The 6 TEST_*_PEM secrets are lower risk since they're for dedicated test GitHub Apps on halfsend-* test orgs (per #5111), not production. But the Cloudflare credentials aren't TEST_-prefixed and their scope isn't visible from the diff. Given #5116 will deploy the real public mint at mint.fullsend.sh, could you confirm:

  • Is this token scoped narrowly (e.g. Workers Scripts:Edit on a specific account), not broader account/zone access?
  • Is it a distinct account/token from whatever will back production, or the same one?

If it's the same account/token that prod will eventually use, a leak here would mean an attacker could deploy a malicious Worker at the actual public token-issuing mint, not just a test sandbox — worth being explicit about that before this lands.

2. The behaviour job's debug-artifact upload is a secret-exfiltration path independent of the gate auth

The "Upload behaviour debug artifacts" step runs unconditionally on failure and uploads ${{ runner.temp }}/behaviour-artifacts/ with no content filtering. GitHub auto-masks known secret substrings in logs, but does not scan uploaded artifact files the same way. Since this directory is populated by the PR's own pkg/behaviourtest/e2e/behaviour code (checked out via allow-unsafe-pr-checkout), an authorized-but-malicious fork PR could write $CLOUDFLARE_API_TOKEN or any of the PEMs into a file there and have it uploaded as a downloadable artifact, unredacted. This pattern already existed for the GCP secrets, but this PR raises the stakes by adding higher-value long-lived credentials to the same exposure surface — the gate (which looks solid — nice staleness check on ok-to-test) only protects against unauthorized PRs running at all, not against an authorized-but-compromised/malicious PR exfiltrating via this path.

Worth applying the same kind of secret-redaction treatment that fullsend-ai/agents#38 added for post-failure-report.lib.sh (token/PEM pattern redaction before anything gets written to a file that leaves the job) — either to the debug-artifact contents themselves, or at minimum documented as an accepted risk given the gate's authorization bar.

Keep CLOUDFLARE_* env var names for Wrangler/mint deploy, but source
values from TEST_CLOUDFLARE_* repo secrets so behaviour CI does not
share the production site-deploy credentials.

Signed-off-by: Barak Korren <bkorren@redhat.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@ifireball

Copy link
Copy Markdown
Member Author

Thanks @waynesun09 — addressed both points:

1. Cloudflare secret scope — Updated the behaviour job to read from TEST_CLOUDFLARE_ACCOUNT_ID / TEST_CLOUDFLARE_API_TOKEN (env var names stay CLOUDFLARE_ACCOUNT_ID / CLOUDFLARE_API_TOKEN for Wrangler/mint deploy compatibility). Those repo secrets are initialized with placeholder values for now; a test-scoped token/worker can replace them when the CF mint BT path needs real credentials. Prod CLOUDFLARE_* used by site-deploy.yml is no longer wired into this job.

2. Debug-artifact exfiltration — Follow-up filed: #5221

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@waynesun09
waynesun09 added this pull request to the merge queue Jul 16, 2026
Merged via the queue into fullsend-ai:main with commit d9779f7 Jul 16, 2026
16 checks passed
@fullsend-ai-retro

fullsend-ai-retro Bot commented Jul 16, 2026

Copy link
Copy Markdown

🤖 Finished Retro · ✅ Success · Started 7:20 PM UTC · Completed 7:27 PM UTC
Commit: 2a0bebd · View workflow run →

@fullsend-ai-retro

Copy link
Copy Markdown

PR #5181 wired Cloudflare mint secrets into the e2e behaviour job. The review agent correctly identified both key security concerns (permission expansion and potential production secret sharing) but rated them [low] and approved. Human reviewer waynesun09 escalated the Cloudflare credential scope concern to a blocking request, leading to a fix (switching to TEST_-prefixed secrets). The human also identified an independent exfiltration vector via the debug artifact upload step that the review agent missed entirely. The post-review script appropriately downgraded the agent's approve to comment due to protected-path rules.

Two proposals target the agents repo security sub-agent to close the gaps for future similar PRs:

  1. Escalate severity when secrets cross trust boundaries between trusted and untrusted workflows
  2. Detect artifact uploads as secret exfiltration vectors in untrusted CI contexts

Proposals filed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/ci CI pipelines and checks component/e2e End-to-end tests component/mint Token mint and cross-boundary credentials requires-manual-review Review requires human judgment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

e2e: wire TEST_*_PEM and Cloudflare credentials into the behaviour job

2 participants