Skip to content

fix(security): guard pages-deploy against non-main workflow_dispatch (#87) - #88

Merged
FabioLeitao merged 1 commit into
mainfrom
fix/pages-deploy-ref-guard-87
Aug 24, 2026
Merged

FabioLeitao merged 1 commit into
mainfrom
fix/pages-deploy-ref-guard-87

Conversation

@FabioLeitao

Copy link
Copy Markdown
Contributor

Summary

workflow_dispatch had no branch filter, and the checkout step didn't pin a ref — it used whatever ref triggered the run. The github-pages environment allowlists a gh-pages branch (confirmed via the environment API) that isn't protected by main's signature/PR rules and doesn't exist yet. Any collaborator with contents: write (no admin, no PR into main required) could create that branch with a malicious payload, dispatch this workflow against it, and publish to databoar.com.br unreviewed — XSS, HubSpot form PII skim, defacement, or a rewritten wheelhouse PEP 503 index, with no trace on main.

Fix

Two independent guards, so a bug in one doesn't reopen the hole:

  • Job-level if: github.ref == 'refs/heads/main' — refuses to run at all unless the triggering ref is main.
  • Checkout now pins ref: main explicitly instead of following the triggering ref, so even a run that did start checks out and deploys main's content regardless of what ref invoked it.

Test plan

  • YAML parses (python3 -c "import yaml; yaml.safe_load(...)")
  • zizmor online (GH_TOKEN=$(gh auth token) uvx zizmor .github/workflows/pages-deploy.yml) — 0 findings
  • Operator: confirm push: main deploy still works normally after merge (no behavior change on that path — same trigger, same checkout target)

Closes #87

…87)

workflow_dispatch had no branch filter, and the checkout step didn't pin a
ref -- it used whatever ref triggered the run. The github-pages environment
allowlists a gh-pages branch (confirmed via the environment API) that isn't
protected by main's signature/PR rules and doesn't exist yet. Any
collaborator with contents:write (no admin, no PR into main required) could
create that branch with a malicious payload, dispatch this workflow against
it, and publish to databoar.com.br unreviewed -- XSS, HubSpot form PII skim,
defacement, or a rewritten wheelhouse PEP 503 index, with no trace on main.

Two independent guards, so a bug in one doesn't reopen the hole:
- Job-level `if: github.ref == 'refs/heads/main'` refuses to run at all
  unless the triggering ref is main.
- Checkout now pins `ref: main` explicitly instead of following the
  triggering ref, so even a workflow run that did start checks out and
  deploys main's content regardless of what ref invoked it.

Verified: YAML parses, zizmor (online, GH_TOKEN) reports 0 findings against
the changed file.

Closes #87
@FabioLeitao
FabioLeitao merged commit 5eaba75 into main Aug 24, 2026
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.

[security][high] pages-deploy.yml: workflow_dispatch sem branch filter + checkout sem ref pin permite deploy não-assinado via gh-pages

1 participant