@secureci/cli 0.5.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -15
- package/dist/advisories.js +603 -0
- package/dist/cli.js +263 -38
- package/dist/config.js +23 -1
- package/dist/init.js +12 -5
- package/dist/parser/allow-comments.js +113 -0
- package/dist/parser/dangerous-triggers.js +163 -0
- package/dist/parser/injection.js +281 -0
- package/dist/parser/permissions.js +145 -0
- package/dist/parser/pipeline-contract-parser.js +70 -0
- package/dist/parser/pipeline-contract-validator.js +18 -4
- package/dist/parser/validator.js +61 -1
- package/dist/pin.js +311 -0
- package/dist/report.js +9 -2
- package/dist/runner/action-fetcher.js +100 -4
- package/dist/runner/builtin-actions.js +13 -3
- package/dist/runner/dry-run.js +57 -12
- package/dist/runner/executor.js +368 -254
- package/dist/runner/expression.js +106 -8
- package/dist/runner/job-plan.js +58 -1
- package/dist/runner/job-runtime.js +3 -3
- package/dist/runner/node-action.js +11 -3
- package/dist/runner/node-binary.js +108 -0
- package/dist/runner/scheduler.js +207 -0
- package/dist/runner/steps.js +54 -2
- package/dist/utils/env-file.js +185 -0
- package/dist/utils/logger.js +36 -7
- package/dist/version.js +56 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -16,12 +16,16 @@ of [SecureCI](https://secure-ci.dev).
|
|
|
16
16
|
|
|
17
17
|
A single CLI that understands GitHub Actions the way the runner does:
|
|
18
18
|
|
|
19
|
-
- **Run workflows locally** — jobs in `needs:` order
|
|
20
|
-
workflows, composite / JavaScript / Docker actions, and the full
|
|
19
|
+
- **Run workflows locally** — jobs in `needs:` order (independent jobs and
|
|
20
|
+
matrix combinations in parallel), matrix builds, reusable workflows, composite / JavaScript / Docker actions, and the full
|
|
21
21
|
`${{ }}` / `if:` expression language.
|
|
22
|
-
- **Validate** workflow and action files,
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
- **Validate** workflow and action files, flag **template injection**
|
|
23
|
+
(untrusted `${{ }}` input expanded into `run:` scripts), over-broad
|
|
24
|
+
`GITHUB_TOKEN` permissions and `pull_request_target` / `workflow_run` jobs
|
|
25
|
+
that run untrusted code (noting whether `actions/checkout`'s safe default
|
|
26
|
+
covers the checkout), and **check them against a pipeline contract**
|
|
27
|
+
(required/forbidden actions, ordering, minimum versions, SHA-pinning,
|
|
28
|
+
permissions, forbidden triggers and advisory severity rules).
|
|
25
29
|
- **Inventory** every action a workflow pulls in, resolve each tag to a commit
|
|
26
30
|
SHA, and **catch supply-chain drift** when a tag quietly starts pointing
|
|
27
31
|
somewhere new.
|
|
@@ -41,6 +45,45 @@ npx @secureci/cli --help
|
|
|
41
45
|
Node.js 20+ is required. To build from source instead:
|
|
42
46
|
`npm install && npm run build`.
|
|
43
47
|
|
|
48
|
+
### Standalone binary (no Node.js needed)
|
|
49
|
+
|
|
50
|
+
Each [release](https://github.com/secure-ci/cli/releases) has a single-file
|
|
51
|
+
binary for Linux (x64, arm64), macOS (Intel, Apple silicon) and Windows (x64),
|
|
52
|
+
a `SHA256SUMS` file, and a signed build-provenance attestation. Pick the asset
|
|
53
|
+
for your platform: `secureci-linux-x64`, `secureci-linux-arm64`,
|
|
54
|
+
`secureci-darwin-x64`, `secureci-darwin-arm64` or `secureci-win-x64.exe`.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# macOS / Linux (here: Linux x64)
|
|
58
|
+
asset=secureci-linux-x64
|
|
59
|
+
base=https://github.com/secure-ci/cli/releases/latest/download
|
|
60
|
+
curl -fsSL -O "$base/$asset" -O "$base/SHA256SUMS"
|
|
61
|
+
sha256sum --check --ignore-missing SHA256SUMS # macOS: shasum -a 256 --check --ignore-missing SHA256SUMS
|
|
62
|
+
gh attestation verify "$asset" --repo secure-ci/cli # optional: verify provenance
|
|
63
|
+
chmod +x "$asset" && sudo mv "$asset" /usr/local/bin/secureci
|
|
64
|
+
secureci --version
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```powershell
|
|
68
|
+
# Windows (PowerShell)
|
|
69
|
+
$base = "https://github.com/secure-ci/cli/releases/latest/download"
|
|
70
|
+
Invoke-WebRequest "$base/secureci-win-x64.exe" -OutFile secureci.exe
|
|
71
|
+
Invoke-WebRequest "$base/SHA256SUMS" -OutFile SHA256SUMS
|
|
72
|
+
$expected = (Select-String -Path SHA256SUMS -Pattern "secureci-win-x64.exe").Line.Split(" ")[0]
|
|
73
|
+
if ((Get-FileHash secureci.exe -Algorithm SHA256).Hash -ne $expected) { throw "Checksum mismatch" }
|
|
74
|
+
gh attestation verify secureci.exe --repo secure-ci/cli # optional: verify provenance
|
|
75
|
+
.\secureci.exe --version
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The binary bundles its own Node.js runtime, so it's large (~100 MB). JavaScript
|
|
79
|
+
actions still need a `node` on `PATH` when they run on the host
|
|
80
|
+
(`--container-runtime host`); in a job container they use the image's `node`.
|
|
81
|
+
The macOS binaries are ad-hoc signed and the Windows binary is unsigned, so
|
|
82
|
+
Gatekeeper or SmartScreen may ask you to confirm the first run (on macOS, a
|
|
83
|
+
`curl` download isn't quarantined).
|
|
84
|
+
|
|
85
|
+
Homebrew (coming): a `secure-ci/tap` formula is planned.
|
|
86
|
+
|
|
44
87
|
## First run
|
|
45
88
|
|
|
46
89
|
```bash
|
|
@@ -59,6 +102,9 @@ secureci init workflow
|
|
|
59
102
|
# Lock the actions you use and catch supply-chain drift (commit secureci.lock)
|
|
60
103
|
secureci inventory # bootstraps secureci.lock, then drift-checks
|
|
61
104
|
secureci inventory --check # fail on drift (use in CI)
|
|
105
|
+
|
|
106
|
+
# Pin action tags to commit SHAs in place (keeps `# v4` for Dependabot/Renovate)
|
|
107
|
+
secureci pin
|
|
62
108
|
```
|
|
63
109
|
|
|
64
110
|
## Where it shines
|
|
@@ -72,7 +118,13 @@ secureci inventory --check # fail on drift (use in CI)
|
|
|
72
118
|
- **Supply-chain visibility** — [`secureci inventory`](DOCS.md#action-inventory-and-drift-secureci-inventory)
|
|
73
119
|
with a committed lockfile turns a silently moved action tag into a failing
|
|
74
120
|
check, including tags inside the actions you use, and catches a locked
|
|
75
|
-
repository that was deleted and re-created
|
|
121
|
+
repository that was deleted and re-created, and
|
|
122
|
+
[`secureci pin`](DOCS.md#pin-actions-to-commit-shas-secureci-pin) rewrites
|
|
123
|
+
action tags to commit SHAs in place.
|
|
124
|
+
- **Known vulnerabilities** — `inventory` and `validate` flag actions with
|
|
125
|
+
published [security advisories](DOCS.md#known-security-advisories) (for
|
|
126
|
+
example GHSA-mrrh-fwg8-r2c3 in `tj-actions/changed-files`), using the GitHub
|
|
127
|
+
Advisory Database.
|
|
76
128
|
- **Machine-readable output** — `--format json|sarif` drops straight into CI and
|
|
77
129
|
GitHub code scanning.
|
|
78
130
|
- **Audit evidence** — the contract, `secureci.lock` and reports are plain files
|
|
@@ -111,6 +163,9 @@ secureci run .github/workflows/ci.yml --job build --input ref=main --var ENV=sta
|
|
|
111
163
|
# Pass a secret by name (value read from your environment, not the command line)
|
|
112
164
|
secureci run .github/workflows/deploy.yml --secret TOKEN
|
|
113
165
|
|
|
166
|
+
# Read env vars, secrets, inputs and variables from .env-style files
|
|
167
|
+
secureci run .github/workflows/deploy.yml --env-file .env --secret-file .secrets
|
|
168
|
+
|
|
114
169
|
# Validate against a central pipeline contract, recursing into called workflows
|
|
115
170
|
secureci validate .github/workflows/deploy.yml \
|
|
116
171
|
--contract contracts/platform-standard.yml --contract-recurse all
|
|
@@ -136,8 +191,10 @@ things to know:
|
|
|
136
191
|
|
|
137
192
|
- **Linux containers only.** `windows-*` / `macos-*` jobs run in a Linux image
|
|
138
193
|
with a warning.
|
|
139
|
-
- **
|
|
140
|
-
|
|
194
|
+
- **Jobs running in parallel share your working copy.** Each job has its own
|
|
195
|
+
container, but every job mounts the same directory, so jobs that write the
|
|
196
|
+
same files (e.g. `node_modules`) can collide; use `--parallel 1` to run jobs
|
|
197
|
+
one after another.
|
|
141
198
|
- **`actions/checkout` of the current repo doesn't clone** — it uses your working
|
|
142
199
|
copy as-is (so uncommitted changes are visible); `ref:`/`fetch-depth:` are
|
|
143
200
|
ignored. Other repositories check out for real and need a token.
|
|
@@ -164,10 +221,10 @@ The exact scope of each is documented in
|
|
|
164
221
|
- **No ambient environment or secrets.** On the host, steps get only a minimal
|
|
165
222
|
allowlist plus the runner's `GITHUB_*`/`RUNNER_*` vars and the workflow's own
|
|
166
223
|
`env:`; everything else is passed explicitly.
|
|
167
|
-
- **Secret masking everywhere.** Values from `--secret` or
|
|
168
|
-
redacted in all output, and in container mode never appear
|
|
169
|
-
command line (passed via a `0600` env file). Prefer
|
|
170
|
-
value stays out of your shell history too.
|
|
224
|
+
- **Secret masking everywhere.** Values from `--secret`, `--secret-file` or
|
|
225
|
+
`::add-mask::` are redacted in all output, and in container mode never appear
|
|
226
|
+
on the client command line (passed via a `0600` env file). Prefer
|
|
227
|
+
`--secret NAME` so the value stays out of your shell history too.
|
|
171
228
|
- **Tokens are handled carefully** — sent only to the GitHub host in
|
|
172
229
|
`GITHUB_SERVER_URL` / `GITHUB_API_URL` (github.com by default), never passed
|
|
173
230
|
to actions, and masked in logs.
|
|
@@ -180,9 +237,9 @@ the feature named, and none runs at install time.
|
|
|
180
237
|
| Capability | Where | Why |
|
|
181
238
|
| ------------------------ | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
182
239
|
| Shell / process spawning | `run:` steps, JavaScript actions, `docker`/`podman`/`nerdctl` | Runs workflow steps in a container (or on your host with `--container-runtime host`). `commander` also loads `child_process`, used only for executable subcommands this CLI does not use. |
|
|
183
|
-
| Network | `github.com`, `api.github.com` (or the GHES host you set) | Downloads actions and workflows,
|
|
240
|
+
| Network | `github.com`, `api.github.com` (or the GHES host you set) | Downloads actions and workflows, resolves tags to commit SHAs, and looks up security advisories for the actions you use (skipped with `--offline`). |
|
|
184
241
|
| Environment variables | `HOME`, `PATH`, `GITHUB_*`, `GITHUB_TOKEN`, `GH_TOKEN` | Builds the runner environment and authenticates GitHub downloads. |
|
|
185
|
-
| Filesystem | `~/.secureci/`, the working directory, temp dirs | Caches actions, stores artifacts and config, and reads your workflow files.
|
|
242
|
+
| Filesystem | `~/.secureci/`, the working directory, temp dirs | Caches actions and advisories, stores artifacts and config, and reads your workflow files. |
|
|
186
243
|
| Hard-coded URLs | GitHub documentation and JSON Schema URLs in messages and editor hints | Informational only; the CLI does not fetch them. |
|
|
187
244
|
|
|
188
245
|
No install scripts run for consumers. The published tarball contains only
|
|
@@ -209,7 +266,9 @@ refactor while keeping tests green.
|
|
|
209
266
|
Every pull request and push to `main` runs
|
|
210
267
|
[`ci.yaml`](.github/workflows/ci.yaml): lint, `prettier --check`, tests with the
|
|
211
268
|
coverage thresholds in `vitest.config.mts`, build, and SecureCI
|
|
212
|
-
validating its own workflow.
|
|
269
|
+
validating its own workflow. It also builds the standalone binary on each
|
|
270
|
+
platform and smoke-tests it (`npm run build && npm run build:sea` builds one
|
|
271
|
+
for your machine into `build/sea/`).
|
|
213
272
|
|
|
214
273
|
Opt-in suites:
|
|
215
274
|
|