Please report security issues privately through GitHub security advisories rather than by opening a public issue.
This action installs software onto a CI runner, so a compromise of the action is a compromise of every job that uses it. The design keeps that surface small:
- Fixed sources. The repositories, the Homebrew tap and the npm registry the action downloads
from are compile-time constants (
src/constants.ts). No workflow input can point the action at a different host, so an attacker who controls an input cannot make a job install foreign software. - Verified downloads. The emulator Debian package is verified against the SHA-256 digest
published by the GitHub releases API, or against the
machine-checksuminput when the workflow pins one. The kernel and rootfs images are verified against the digests in the emulator release'sdependencies.lock. If no digest is available, the action reports the digest it computed and emits a warning instead of trusting the file silently. - Validated inputs. Versions, checksums and every value read from
dependencies.lockare matched against strict patterns before they reach a URL, a filesystem path or a command line. Subprocesses are spawned with argument arrays, never through a shell, so input cannot be interpreted as shell syntax. - Narrow Homebrew trust. Homebrew requires third-party tap formulae to be trusted before it will
load them. The action trusts the individual
cartesi/tapformulae it installs rather than runningbrew trust cartesi/tap, so trust does not extend to formulae the tap may add in the future. - No lifecycle scripts. The Cartesi CLI is installed with
npm install --ignore-scriptsinto a private prefix, sopostinstallscripts anywhere in its dependency tree do not execute on the runner, and the install needs no elevated privileges. - Minimal privileges. Root is used only to install the Debian package with
apt-getand to copy the images into/usr/share/cartesi-machine/images.sudo -nis used, so a runner without passwordless sudo fails immediately rather than waiting on a prompt. - Token handling.
github-tokenis only sent to the GitHub API host, is registered as a secret so it is masked in logs, and is never passed to a subprocess. It needs no more thancontents: read.
- Pin the action to a full commit SHA rather than a tag if your threat model requires it:
uses: cartesi/setup-action@<sha>. - Pin
machine-versionandcli-versionto exact versions for reproducible jobs, and setmachine-checksumwhen you want the emulator package pinned by content as well. - Give the job the least privilege it needs, typically
permissions: contents: read.