Skip to content

Harden manual store submission workflow#990

Open
PeterDaveHello wants to merge 1 commit into
masterfrom
codex/fix-manual-release-workflow-vulnerability
Open

Harden manual store submission workflow#990
PeterDaveHello wants to merge 1 commit into
masterfrom
codex/fix-manual-release-workflow-vulnerability

Conversation

@PeterDaveHello

@PeterDaveHello PeterDaveHello commented Jun 30, 2026

Copy link
Copy Markdown
Member

Motivation

Storing store credentials could allow collaborators who can dispatch workflows to use a protected branch to steal release keys.

Description

  • Updated .github/workflows/tagged-release.yml to remove the global GH_TOKEN and inject GH_TOKEN only into the push-only step that requires gh release.
  • Added persist-credentials: ${{ github.event_name == 'push' }} to actions/checkout to prevent manually triggered runs from inheriting repository credentials.
  • Split store submission into two steps: the manual path now adds a Submit stores dry run step that only allows --dry-run and injects a set of dummy store environment variables; the actual submission is handled by the push-only Submit stores step, which injects the real secrets.*.
  • Only workflow behavior was changed (without modifying scripts/submit-stores.mjs) to minimize risk with the smallest possible scope.

Testing

  • Ran npm test, and all tests passed.
  • Ran npm run pretty, npm run lint, and npm run build; all commands completed successfully.
  • Verified the workflow YAML format with ruby -e 'require "yaml"; YAML.load_file(".github/workflows/tagged-release.yml")'.
  • Verified locally that build/chromium contains the main release files (manifest.json, background.js, content-script.js, popup.html, etc.).

Codex Task

Summary by CodeRabbit

  • Chores
    • Improved the release workflow to handle store submissions more reliably across tag releases and manual runs.
    • Separated dry-run and live store submission steps for clearer release behavior.
    • Updated release steps to use the appropriate token settings at each step, reducing credential-related issues.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Note

Gemini is unable to generate a review for this pull request due to the file types involved not being currently supported.

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR modifies the tagged-release GitHub Actions workflow. It removes the workflow-level GH_TOKEN env block and instead sets GH_TOKEN per-step for checkout, upload, and edit steps. It also conditionally sets persist-credentials on checkout and splits the single store-submission step into separate dry-run and push-triggered steps.

Changes

Release Workflow GH_TOKEN Scoping and Submission Split

Layer / File(s) Summary
Checkout credential handling
.github/workflows/tagged-release.yml
Removes the top-level GH_TOKEN env block and sets persist-credentials on the checkout step conditionally based on whether the run is a tag push.
Store submission step split
.github/workflows/tagged-release.yml
Replaces the single shell-branching submission step with two distinct steps: a dry-run step gated on non-push events with submit_stores and dry_run checks, and a push-only step that runs the real submission.
Per-step GH_TOKEN for upload/edit steps
.github/workflows/tagged-release.yml
Adds step-local env blocks setting GH_TOKEN for the release upload and release edit command steps.

Sequence Diagram(s)

sequenceDiagram
  participant Trigger as Workflow Trigger
  participant Checkout as actions/checkout
  participant SubmitDryRun as Submit stores dry run
  participant SubmitPush as Submit stores
  participant ReleaseScript as release:submit script

  Trigger->>Checkout: run with persist-credentials based on push flag
  alt non-push and submit_stores=true
    Checkout->>SubmitDryRun: proceed to dry-run step
    SubmitDryRun->>SubmitDryRun: validate inputs.dry_run == "true"
    SubmitDryRun->>ReleaseScript: npm run release:submit -- --dry-run
  else push event
    Checkout->>SubmitPush: proceed to push step
    SubmitPush->>ReleaseScript: npm run release:submit
  end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

A rabbit hops through YAML grass,
Tokens scoped to steps at last 🐇
Dry-run hops before the push,
Credentials guarded, no more rush.
Carrots stacked, the workflow clean—
Hop hop hooray for CI's sheen! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: hardening the manual store submission workflow to reduce risk.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-manual-release-workflow-vulnerability

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Harden tagged-release workflow to prevent secret exposure on manual dispatch

🐞 Bug fix ⚙️ Configuration changes 🕐 10-20 Minutes

Grey Divider

AI Description

• Scope GH_TOKEN only to gh release steps executed on push-tag runs.
• Prevent workflow_dispatch checkouts from inheriting repository credentials.
• Split store submission into manual dry-run (dummy env only) vs push-only real submission
 (secrets).
Diagram

graph TD
A(("Workflow trigger")) --> B{{"Event type?"}}
B -->|"push v* tag"| C["Checkout (persist creds on push)"] --> D["Release steps (GH_TOKEN scoped)"] --> E["Submit stores (real secrets)"] --> F["Publish release (GH_TOKEN scoped)"]
B -->|"workflow_dispatch"| C --> G["Build + package"] --> H["Submit stores (dry-run, dummy env)"]
subgraph Legend
direction LR
_start(("Trigger")) ~~~ _decision{{"Decision"}} ~~~ _step["Step"]
end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Split into two workflows (release vs manual preflight)
  • ➕ Eliminates complex conditional logic in a single YAML
  • ➕ Makes secret-free manual workflow intent explicit
  • ➖ Some duplication of build/release steps across workflows
  • ➖ Requires keeping two workflows in sync
2. Force workflow_dispatch to run only from default branch ref
  • ➕ Further reduces attack surface by never executing untrusted refs for manual runs
  • ➕ Simplifies credential hardening requirements
  • ➖ Loses ability to validate release pipeline against branch-specific changes
3. Use GitHub Environments with required reviewers for store submission
  • ➕ Adds an approval gate even if a step is misconfigured in the future
  • ➕ Environment-scoped secrets limit accidental exposure
  • ➖ Operational overhead and slower releases
  • ➖ Requires additional repository configuration

Recommendation: The PR’s approach is a good minimal-scope hardening: it removes global token exposure, disables persisted checkout credentials for manual runs, and ensures manual store submission cannot access real secrets. Consider adding an Environment approval gate for the push-only store submission as a defense-in-depth follow-up.

Files changed (1) +33 / -13

Other (1) +33 / -13
tagged-release.ymlScope tokens and split store submission into push-only vs manual dry-run +33/-13

Scope tokens and split store submission into push-only vs manual dry-run

• Removes the global GH_TOKEN and injects it only on gh release steps that run on push-tag events. Updates checkout to avoid persisting repository credentials on workflow_dispatch. Splits store submission into a manual-only dry-run step using dummy env vars and a push-only real submission step using secrets.

.github/workflows/tagged-release.yml

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a3d0e2303d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +123 to +125
CHROME_CLIENT_ID: dry-run-chrome-client-id
CHROME_CLIENT_SECRET: dry-run-chrome-client-secret
CHROME_REFRESH_TOKEN: dry-run-chrome-refresh-token

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Don't feed dummy credentials to dry-run submission

When this workflow is manually dispatched with submit_stores=true, these fake credentials make the dry run fail during store authentication rather than validating the release artifacts. I checked publish-browser-extension: its --dry-run option is documented as checking authentication, and its store submit paths fetch auth tokens/details before skipping upload, so npm run release:submit -- --dry-run will reject the dummy Chrome/Firefox/Edge values. If manual runs must avoid secrets, this step needs a non-auth preflight path instead of invoking the real dry-run submission with fake credentials.

Useful? React with 👍 / 👎.

Copilot AI 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.

Pull request overview

This PR hardens the tagged-release GitHub Actions workflow to prevent credential exposure when collaborators manually trigger workflow_dispatch, while keeping real store submissions restricted to trusted tag-push runs.

Changes:

  • Removed the workflow-wide GH_TOKEN and instead injects GH_TOKEN only into the push-only gh release steps.
  • Prevents credential persistence during manual runs by setting actions/checkout persist-credentials to only persist on push.
  • Splits store submission into a manual-only dry-run step (with dummy store env vars and forced --dry-run) and a push-only real submission step (with secrets.*).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Qodo Logo

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants