Remove the Dependabot github-actions ecosystem config and its companion
auto-merge / major-analysis workflows. Renovate (via
renovate.json -> local>CopilotKit/renovate, Dependency Dashboard #592)
now owns github-actions updates.
Also clean stale references to the deleted files:
- zizmor.yml: drop dangerous-triggers ignores for the two dependabot
workflows, remove the now-empty dependabot-cooldown rule, and update
the unpinned-uses comment to reference Renovate.
- security_zizmor.yml: drop the .github/dependabot.yml path trigger.
npm and other ecosystems are untouched (dependabot.yml had only the
github-actions ecosystem).
## Summary
- Add `persist-credentials: false` to checkout so the devops-bot app
token
(which bypasses branch protection) is not left in `.git/config` for ~30
minutes while ffmpeg, Playwright, and npm packages install
- Inject credentials via `git config insteadOf` only in the new
"Configure git for push" step, immediately before the commit/push step
- Remove the now-unnecessary `artipacked` suppression for
`showcase_capture-previews.yml` from `.github/zizmor.yml`
## Why
A compromised dependency installed during the ~30-minute window could
exfiltrate the persisted devops-bot token from `.git/config` and push
directly to main, bypassing branch protection.
## Test plan
- [ ] Trigger capture-previews workflow manually and verify registry
commit + push still succeeds
- [ ] Verify zizmor CI passes (no new artipacked findings)
Add persist-credentials: false to the checkout step in the format job
so the write-scoped GITHUB_TOKEN is not persisted in .git/config while
third-party tools (ruff from PyPI, oxfmt from npm) are installed and
executed. Credentials are injected via git insteadOf only immediately
before the push step, reducing the exposure window from the full job
duration to seconds.
Remove the artipacked suppression for static_quality.yml in zizmor.yml
since it no longer triggers the finding.
persist-credentials: false on checkout so the devops-bot app token
is not left in .git/config for ~30 minutes while ffmpeg, Playwright,
and npm packages install. Credentials are injected via insteadOf
only in the new "Configure git for push" step immediately before
the commit/push step.
Remove the now-unnecessary artipacked suppression for
showcase_capture-previews.yml from .github/zizmor.yml.
Comprehensive CI/CD security hardening pass over all 33 workflows.
Action pinning
- Every `uses:` is now pinned to a 40-char commit SHA with a `# vX.Y.Z`
comment alongside (167 occurrences resolved). Tag-style refs like `@v4`
are mutable and have been used in past supply-chain attacks (e.g.
tj-actions/changed-files in March 2025) to repoint widely-used actions
to malicious commits.
- Removed redundant `version: "10.13.1"` hardcodes from `pnpm/action-setup`
call sites so the action inherits from package.json `packageManager`
(one source of truth).
Automated maintenance
- Added `.github/dependabot.yml` for the `github-actions` ecosystem so
SHA pins stay current. Without this, pins go stale fast and new
upstream advisories never reach us. Minor/patch bumps are grouped;
major bumps stay separate so they get a real review.
Static analysis
- Added `.github/zizmor.yml` configuration and
`.github/workflows/security_zizmor.yml` (blocking on PR, runs on push
to main, weekly schedule for advisory drift). zizmor catches the
well-known classes of Actions footguns: template injection from
untrusted input, dangerous triggers, unpinned uses, excessive token
scopes, secret exfil patterns.
- All 28 high-severity and 54 medium-severity findings from the baseline
scan are remediated. Each suppression in zizmor.yml carries a
per-finding justification comment so future maintainers can audit the
trust assumption.
Workflow hardening (from zizmor + manual audit)
- Added `persist-credentials: false` to every `actions/checkout` except
the 7 workflows that legitimately push back to the repo via the
workflow token (release tagging, auto-formatting, docs-sync, registry
updates). Each retained credential persistence carries a
`persist-credentials required: ...` comment explaining the call site.
- Routed every attacker-controllable expansion (`github.head_ref`,
`github.event.pull_request.head.repo.full_name`, `inputs.*`,
step outputs) through `env:` and referenced as quoted shell variables.
Eliminates 17 template-injection vectors in fork-PR-reachable
workflows.
- Added per-job `permissions:` blocks across 14 workflows; demoted
broad workflow-level `id-token: write` to the specific Depot-runner
jobs that need it; narrowed `pull-requests: write` /
`actions: write` to the jobs that actually call those APIs.
Audit-driven fixes
- `publish-release.yml` build job: dropped `token:` and added
`persist-credentials: false`. The subsequent `Upload workspace` step
was packing `.git/config` (with the persisted GITHUB_TOKEN) into a
1-day-retention artifact downloadable by anyone with `actions:read`.
- `auto_merge_showcases.yml`: team-membership check now authorizes on
the PR AUTHOR (`pull_request.user.login`), never `context.actor` —
the actor is whoever triggered the latest event, so a team member
synchronizing or reopening an outsider's PR would otherwise
green-light auto-merge of code they didn't author.
- `static_quality.yml`: pinned ruff to a specific version so a
compromised release can't land on the next PR run with the
persisted-credentials write token in the format job.
- `showcase_capture-previews.yml`: switched the args-string construction
to a bash array so a slug or demo value containing whitespace or shell
metacharacters stays a single argument rather than being re-tokenized
by the shell.