`WRITE_PERMISSION_PATTERN` in `validate-workflow-security.js`
enumerates named GitHub Actions scopes (`contents: write`,
`issues: write`, etc.) to decide whether a workflow needs to:
- disable `persist-credentials` on `actions/checkout`
- pass `--ignore-scripts` to `npm ci`
The pattern misses the top-level shorthand `permissions:
write-all`, which is the strictly broader form — it grants every
named scope write access in a single line. As a result, a
workflow that opts into write-all currently slips both gates.
Reproduced on `main` before this commit:
$ cat /tmp/bad.yml
name: bad
on: [push]
permissions: write-all
jobs:
do:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
$ ECC_WORKFLOWS_DIR=/tmp node scripts/ci/validate-workflow-security.js
Validated workflow security for 1 workflow files
$ echo $?
0
Expected: at least two violations (missing `persist-credentials:
false`, missing `--ignore-scripts`).
Actual: passes silently.
Fix: add a sibling pattern `WRITE_ALL_PATTERN` that matches
`^\s*permissions:\s*write-all\b` and OR it with
`WRITE_PERMISSION_PATTERN` at the single gate. Both top-level
and job-level `permissions:` blocks satisfy the `^\s*` prefix.
After this commit the reproduction above exits 1 with:
ERROR: bad.yml:8 - workflows with write permissions must disable checkout credential persistence
ERROR: bad.yml:9 - workflows with write permissions must install npm dependencies with --ignore-scripts
Three new regression tests in `tests/ci/validate-workflow-security.test.js`:
- rejects write-all + credential-persisting checkout
- rejects write-all + `npm ci` without `--ignore-scripts`
- allows write-all when both gates are satisfied (no over-block)
Test count: 14 → 17 in this file; full `yarn test` still green.
A separate `refs/pull/N/merge` bypass under `pull_request_target`
exists in the same validator and is fixed in the next commit.
Salvages the useful parts of #1897 without generated .caliber state or stale counts.
- adds a deterministic command registry generator and drift check
- commits the current command registry for 75 commands
- validates the rc.1 README catalog summary against live counts
- adds a single Ubuntu Node 20 coverage job instead of running coverage in every matrix cell
Co-authored-by: jodunk <jodunk@users.noreply.github.com>
Add a repo-level supply-chain incident response playbook for npm/GitHub Actions package-registry incidents, anchored on the May 2026 TanStack compromise and prior Shai-Hulud-style npm incidents.
- add `docs/security/supply-chain-incident-response.md` with exposure checks, immediate response steps, workflow rules, publication rules, and escalation triggers
- link the playbook from `SECURITY.md`
- reject `pull_request_target` workflows that restore or save shared dependency caches
- add a regression test for the new `pull_request_target + actions/cache` guardrail
Validation:
- node tests/ci/validate-workflow-security.test.js (12 passed, 0 failed)
- node scripts/ci/validate-workflow-security.js (validated 7 workflow files)
- npx markdownlint-cli 'SECURITY.md' 'docs/security/supply-chain-incident-response.md'
- npx markdownlint-cli '**/*.md' --ignore node_modules
- git diff --check
- node tests/run-all.js (2377 passed, 0 failed)
- GitHub CI for #1848 green across Ubuntu, Windows, and macOS
No release, tag, npm publish, plugin tag, marketplace submission, or announcement was performed.
Require npm registry signature verification wherever workflow npm audit checks run.
- add npm audit signatures to CI Security Scan and maintenance security audit jobs
- teach the workflow security validator to reject npm audit without signature verification
- keep the repair and Copilot prompt tests portable across Windows path/case and CRLF frontmatter behavior
Validation:
- node tests/run-all.js (2376 passed, 0 failed)
- CI current-head matrix green on #1846
Adds GitHub Copilot VS Code instruction and prompt files for ECC workflows, with VS Code prompt frontmatter/settings aligned to current docs and tests covering the surface.
Co-authored-by: Girish Kanjiyani <girish.kanjiyani5040@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- run non-test workflow installs with npm ci --ignore-scripts where lifecycle scripts are not needed\n- reject plain npm ci in workflows with write permissions\n- reject actions/cache in id-token: write workflows to reduce OIDC publish cache-poisoning risk
- add Vite and Redis pattern skills from closed stale PRs
- add frontend-slides support assets
- port skill-comply runner fixes and LLM prompt/provider regressions
- harden agent frontmatter validation and sync catalog counts
* fix(ci): flag SKILL.md frontmatter defects in validate-skills
Issue #1663 reported two SKILL.md frontmatter defects (missing `name:`
on skill-stocktake; literal block-scalar `description: |-` on
openclaw-persona-forge) that PR #1664 addresses at the data level.
This change is complementary: it extends `scripts/ci/validate-skills.js`
to catch the same class of defect statically going forward, so the
frontmatter-vs-renderer problems do not silently reappear as new skills
land.
## Checks added
- Frontmatter must declare a `name:` field.
- Frontmatter `description:` must not use a literal block scalar
(`|` / `|-` / `|+`) — these preserve internal newlines and break
flat-table renderers keyed off `description`. Folded (`>`) and inline
strings are accepted.
## Behavior
- Frontmatter findings default to WARN (exit 0) so this PR does not
break CI while the two known offenders are still on main. Pass
`--strict` or set `CI_STRICT_SKILLS=1` to promote them to ERROR
(exit 1). Structural findings (missing / empty SKILL.md) remain
errors as before.
- Today against main, the validator reports exactly two warnings —
the same two files called out in #1663 — and exits 0. When #1664
lands, the validator reports zero warnings, at which point strict
mode can be enabled in CI.
## Parser notes
- Bespoke frontmatter parser mirrors the style of `validate-agents.js`
(tolerant of UTF-8 BOM and CRLF; no new npm dependency).
- Block-scalar continuation lines are skipped so keys inside a block
scalar are not mistaken for top-level keys.
- Hidden directories (`.something/`) under skills/ are now skipped.
## Tests
Adds five focused tests to `tests/ci/validators.test.js`:
- warns when frontmatter is missing `name` (default mode)
- errors when frontmatter is missing `name` (--strict mode)
- warns on literal block-scalar description (|-)
- accepts folded (>) and inline descriptions under --strict
- skips hidden directories under skills/
## Docs
Adds two bullets to the `Skill Checklist` in CONTRIBUTING.md covering
the two rules now surfaced by the validator.
Refs #1663. Complements (does not compete with) #1664.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(ci): harden SKILL.md frontmatter checks after bot review
Address findings from CodeRabbit, Greptile, and cubic on #1669:
- Guard empty or whitespace-only `name:` values. Previously
`name: ` silently passed because the presence check only
tested key-set membership; now inspectFrontmatter captures
trimmed values and validate flags an explicit 'name is empty'
WARN/ERROR.
- Broaden block-scalar detection to cover YAML 1.2 indent
indicators (`|2`, `|-2`, `>2-`) and trailing comments
(`|- # note`). The old regex required a bare `|`/`>` with
optional `+`/`-`, which let valid-but-disallowed forms slip
through.
- Update CONTRIBUTING.md checklist to list `|+` alongside `|`
and `|-` for parity with the validator.
- Extend runSkillsValidator to accept env overrides and add four
regression tests: empty name, |+ description, |-2 + comment, and
CI_STRICT_SKILLS=1.
* fix(ci): address round-2 review on validate-skills frontmatter
- Tighten extractFrontmatter closing delimiter to require a newline or
end-of-file after the closing `---`, so body lines beginning with
`---text` are not parsed as frontmatter (CodeRabbit).
- Strip both trailing and comment-only values in inspectFrontmatter, so
`name: # todo` is surfaced as empty rather than silently passing
(cubic P2).
- Extract validateSkillDir helper so the per-directory validation
block moves out of validateSkills, keeping both functions under the
50-line guideline (CodeRabbit nit).
- Hoist runSkillsValidator to module scope in the test harness and
share the spawnSync import with execFileSync so the helper stops
re-requiring child_process on every invocation (CodeRabbit nit).
- Add regression tests: comment-only `name:` values must fail strict
mode; `---trailing` body lines must not be parsed as frontmatter.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Update tests/ci/validators.test.js
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
The command cross-reference regex /^.*`\/(...)`.*$/gm only captured the
LAST command ref per line due to greedy .* consuming earlier refs.
Replaced with line-by-line processing using non-anchored regex to
capture ALL command references.
New tests:
- 4 validate-commands multi-ref-per-line tests (regression)
- 8 evaluate-session threshold boundary tests (new file)
- 6 session-aliases edge case tests (cleanup, rename, path matching)
The validator was matching example/template content inside fenced code
blocks as real cross-references, causing false positives for evolve.md
(example /new-table command and debugger agent).
- Strip ``` blocks before running cross-reference checks
- Change evolve.md examples to use bold instead of backtick formatting
for hypothetical outputs
All 261 tests pass.
- hooks.schema.json: add async (boolean) and timeout (number) properties
to hookItem definition, matching fields used in hooks.json
- validate-hooks.js: validate async and timeout types when present
- hooks.test.js: add SessionEnd to required event types check
- session-manager.js: fix getSessionStats path detection to handle
Windows paths (C:\...) in addition to Unix paths (/)
- package-manager.js: add try-catch to setPreferredPackageManager for
consistent error handling with setProjectPackageManager
- validate-hooks.js: extract duplicated hook entry validation into
reusable validateHookEntry() helper
- Update .d.ts JSDoc for both fixes