Skip to content

Security overview

How ci-parity treats the repositories it reads, and how the project protects its code, releases and CI. To report a vulnerability, follow SECURITY.md.

ci-parity runs in CI on files that may come from an untrusted pull request. Its inputs are workflows, composite actions, runner files, .ci-parity.yml and the baseline.

  • No execution. It never runs the commands it reads, the task runner, or a shell; it parses them. The code has no os/exec or network imports outside tests.
  • No network at check time. Results depend only on the files and -C.
  • Escaped output. The github format escapes workflow-command characters, so a crafted step name or message can’t inject a workflow command; JSON and SARIF are encoded as data.
  • Bounded reading. Includes, imports and modules are followed to depth 10, and cycles are cut.
  • Writes only on fix, only to discovered workflow files inside the repository, and only where the expected text is still in place.
  • Every input reaches the scripts through env:, never pasted into them, so an input can’t inject shell code.
  • The binary comes from the pinned release with gh release download and is checked against checksums.txt before it runs.
  • Three Go dependencies in the binary and three more for tests only, each recorded with its reason; govulncheck checks them and the standard library in CI.
  • Every third-party action is pinned to a full commit SHA; zizmor and actionlint check the workflows.
  • Dev tools are pinned in mise.toml; mise’s npm provenance check is not bypassed.
  • The release job uses no caches, so a cache written elsewhere can’t reach the binaries.
  • The docs site’s npm packages are pinned in site/pnpm-lock.yaml, install no scripts unless site/pnpm-workspace.yaml allows them, and never reach the binary. The Pages deploy builds without caches, and only its deploy job can write to Pages.
  • gitleaks scans the history on every pull request and push, and runs in the pre-commit hook. A hit is fixed, never allowlisted.
  • main takes only squash-merged pull requests with passing checks and signed commits.
  • Workflows start with read-only or no permissions; each job that needs more asks for it.

Last reviewed: 2026-10-28