Skip to content

ci: apply the CI security standard (no cache in release, pins, permissions) - #1060

Merged
taylanpince merged 5 commits into
masterfrom
ci-security-standard
Nov 3, 2026
Merged

taylanpince merged 5 commits into
masterfrom
ci-security-standard

Conversation

@taylanpince

@taylanpince taylanpince commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Brings the GitHub Actions workflows in line with the CI security standard for GitHub Actions (npm and Go). Publishing still goes through changesets and npm stage publish; no triggers are changed.

Release path

  • 6.2: the release and snapshot jobs hold id-token: write, but setup-node restored the shared pnpm cache there (cache: pnpm). It now runs with package-manager-cache: false, so nothing from the shared cache reaches the jobs that can stage packages. Releases install from the registry and take a little longer.
  • 5.4: the snapshot checkout no longer persists the job token. The release checkout already didn't.

Workflow hygiene

  • 5.2: every action and reusable workflow is pinned to a full commit SHA, with the version in a comment, resolved from the tag currently in use. 0xPolygon/pipelines/...@main is pinned to today's main.
  • 5.1: every workflow defaults to permissions: {} and each job declares what it uses.
  • 5.4: persist-credentials: false on the remaining checkouts. pnpm-format commits back through 0xsequence/actions/git-commit, which clones with its own token.
  • 5.5/5.8: the pnpm format label workflow:
    • passes only GH_TOKEN_GIT_COMMIT instead of secrets: inherit;
    • removes the label with gh api and env: instead of interpolating the label name and token into a curl command.
  • 5.6: timeouts at roughly 2–3× the slowest run in the last 25: install 30, build 20, tests 30, Claude 60, format 15 minutes.

New checks

  • 7.3: dependency-review.yml fails a PR that adds a dependency with a high-severity advisory or a licence outside the allowlist.
  • §8: zizmor.yml lints workflow changes on PRs and weekly, with SARIF going to code scanning.
  • 5.2/7.1: dependabot.yml adds GitHub Actions version updates with a 7-day cooldown, so the pins stay current.

Not in this PR (need a decision)

  • 5.3: claude.yml runs on issue_comment in a public repo, and claude-code-action checks out the PR head itself. It only runs for commenters with write access, but it still processes fork code with an API key in the job. A safer trigger design is a separate change.
  • 6.4/6.5: the snapshot job stages from workflow_dispatch with a dist-tag from inputs.snapshot_tag. The standard only allows next/latest derived from package.json. That's a policy question for the standard, not a mechanical fix.
  • 7.2: .npmrc ignore-scripts=true is not added. pnpm 10 already blocks dependency build scripts, and the setting would also skip the root postinstall (lefthook install). The release jobs keep --no-frozen-lockfile, which is documented in the workflow.
  • 6.6: build-provenance attestation is not added.

Checks: zizmor (medium+) goes from 8 medium / 13 high findings to 1 high, the claude.yml trigger above. Only .github/ changes, so no changeset is needed.

After review

  • Licences (Tolga): allow-licenses now includes the permissive licences GitHub reports for packages already in the tree: BlueOak-1.0.0, CC-BY-4.0, Python-2.0, BSD-2-Clause-Views and others. The 13 @img/sharp-* packages (LGPL, pulled in by next → sharp) are exempted by name in allow-dependencies-licenses. A bump of an existing dependency now passes, while a new dependency under a copyleft licence still fails. The list was checked against this repo's dependency-graph SBOM with the spdx-satisfies version the action uses.
  • Composite action (Patryk 1): Dependabot now scans .github/actions/* too, so the install-dependencies pins get bumped.
  • Node 20 (Patryk 3): the remaining v4 pins move to the versions the release workflow already uses: checkout v7.0.1, setup-node v7.0.0, pnpm/action-setup v6.0.9, plus cache v5.1.0. pnpm/action-setup now takes the version from packageManager; v4+ rejects a version: input that disagrees with it.
  • zizmor nit: the job no longer requests contents/actions: read, since the repo is public.
  • Pipelines (Patryk 2): no change here. apps-changeset-check.yml still calls upsert-changeset-comment@main inside 0xPolygon/pipelines. That's being raised with pipelines alongside the proposal to centralise pinned CI versions there.

taylanpince and others added 3 commits November 2, 2026 17:46
setup-node no longer restores the shared pnpm cache in the release and
snapshot jobs, which hold id-token: write for npm trusted publishing,
and the snapshot job no longer persists the checkout token.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pin every action and reusable workflow to a full commit SHA with its
version in a comment, default workflows to no permissions and grant
each job what it uses, stop persisting the checkout token, and give
each job a timeout above its slowest recent run.

The pnpm-format label workflow passes only the secret it needs instead
of inheriting all of them, and removes the label through env variables
instead of interpolating the event into the shell script.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dependency review fails PRs that add a dependency with a high-severity
advisory or a licence outside the allowlist. zizmor lints workflow
changes on PRs and weekly. Dependabot keeps the pinned action SHAs
current, with a 7-day cooldown before a new release is proposed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@taylanpince
taylanpince marked this pull request as ready for review November 3, 2026 11:23
@taylanpince
taylanpince requested a review from a team November 3, 2026 11:23
@taylanpince
taylanpince requested a review from a team as a code owner November 3, 2026 11:23
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-03T11:25:42.542951Z 16b27bf Draft marked ready
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

tolgahan-arikan
tolgahan-arikan previously approved these changes Nov 3, 2026

@tolgahan-arikan tolgahan-arikan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, thanks. Non-blocking: the dependency-review licence allowlist will flag packages already in the lockfile the first time a PR bumps them. Examples: caniuse-lite (CC-BY-4.0); lru-cache@11, glob@13, minimatch@10, path-scurry (BlueOak-1.0.0); argparse@2 (Python-2.0); @img/sharp-libvips-* (LGPL-3.0-or-later). It passes now only because this PR changes no dependencies. Could add BlueOak-1.0.0, CC-BY-4.0 and Python-2.0 to allow-licenses and exempt sharp/libvips via allow-dependencies-licenses, or switch to a deny-licenses list. Fine as a follow-up.

@patrislav patrislav 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.

1. Dependabot won't see the composite action

With directory: /, Dependabot only scans .github/workflows/* and a root action.yml (docs). The pins in .github/actions/install-dependencies/action.yml won't get bumped, and that's what tests and pnpm-format install through.

  - package-ecosystem: github-actions
    directories: ["/", "/.github/actions/*"]

2. The pipelines pin still floats underneath

apps-changeset-check.yml at 3c69da7 calls 0xPolygon/pipelines/.github/actions/upsert-changeset-comment@main, so that step still runs whatever is on pipelines main. And since the comment is # main rather than a tag, Dependabot won't bump this SHA; it's a manual edit on every pipelines change. Nothing to change here, but worth raising with pipelines: pin its internal @main refs and cut tags.

3. The v4 pins are on a deprecated runtime

This PR's CI logs warn that checkout v4.4.0 targets Node 20 and is "being forced to run on Node.js 24"; same for setup-node v4.4.0 and cache v4.3.0. The release workflow is already on checkout v7.0.1, setup-node v7.0.0 and pnpm/action-setup v6.0.9. Aligning the rest now avoids a three-major-version jump in the first grouped Dependabot PR.

Nit: the zizmor job's contents: read and actions: read are only needed on private repos.

taylanpince and others added 2 commits November 3, 2026 13:44
Dependency review only passed because no dependency changed. Add the
permissive licences GitHub reports for packages already in the tree
(BlueOak-1.0.0, CC-BY-4.0, Python-2.0, BSD-2-Clause-Views, Zlib, ...)
and exempt by name the packages already present under copyleft or
unparsed licence data, so bumping them doesn't fail the check while a
new dependency with such a licence still does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
checkout, setup-node, cache and pnpm/action-setup run on the deprecated
Node 20 runtime at the versions pinned so far; pin the releases the
release workflow already uses. pnpm/action-setup now takes the version
from packageManager. Dependabot also scans .github/actions, which
directory: / leaves out. zizmor no longer requests contents and actions
read, which only private repositories need.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@tolgahan-arikan tolgahan-arikan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, thanks for addressing the licence allowlist, the composite-action scanning and the Node 20 pins.

@taylanpince
taylanpince merged commit ccd24a1 into master Nov 3, 2026
12 checks passed
@taylanpince
taylanpince deleted the ci-security-standard branch November 3, 2026 13:42
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.

4 participants