CoalBoard is verified under the same framework as CoalMine and CoalTipple: the execution hook follows the Phoenix-13 commandments, the build is reproducible from source, and the design is security-first.
Open an issue at github.com/TheColliery/CoalBoard, or request a private channel for sensitive PoC logs. We investigate promptly.
Every release tag and maintainer commit is SSH-signed (gpg.format=ssh); GitHub shows the Verified badge on them. Automated Dependabot / CI commits are unsigned by design (they carry no maintainer key), so verify a signed release tag β the artifact a release consumer trusts:
echo "* ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEtqTWGKhX1Dk9nZP8ns13Wl5zsO1Cz3VlTS6m1p2fP9" > coalboard_signers
git config gpg.ssh.allowedSignersFile ./coalboard_signers
git tag -v "$(git describe --tags --abbrev=0)"The clean plugin/ distribution is generated from source by node scripts/build-plugin.mjs; node scripts/verify.mjs checks the dist is in sync, the manifest is valid, and the config schema is well-formed. node scripts/test.mjs runs the zero-dependency unit + hermetic-hook tests (the canonical runner β the node --test <glob> form is avoided: it breaks on Node 24, MODULE_NOT_FOUND).
Last scan: CoalBoard v1.5.5 dist (commit 96c49af), on 2026-07-02, with NVIDIA SkillSpector v2.3.9 (self-reported β the tool ships no tagged releases; the version is the uvx-from-git HEAD, 326a2b4). Re-scan is event-driven on a NEW SkillSpector version (maintainer-commanded), NOT per CoalBoard release. A new SkillSpector version is exactly when the rules, codes, and score can move β v2.3.9 (vs the 2026-06-24 v2.3.5 pass) added new analyzers (AR1 anti-refusal Β· SSRF Β· rug-pull RP1-3 Β· PE4/PE5 Β· E5 Β· TM4) and reworked per-file score weighting; the 2026-07-02 re-scan returned the same all-false-positive verdict (identical finding classes and count: RA1 Γ8 Β· EA2 Β· RA2 Β· TM1; the score eased 89 β 71 from the scoring rework, not from a CoalBoard change).
Read the score in context. The static stage scored 71/100 (trend: v2.2.3 100 β v2.3.1 96 β v2.3.5 89 β v2.3.9 71); the semantic LLM stage was not run this pass (--no-llm β static-only is the documented FP-prone baseline, pattern-match-based, flagging strings without the skill-contract context). Every finding was verified false-positive.
- Static Scan (71/100 Β· all false-positive):
RA1 Self-ModificationΓ8 (self-update) β the series self-update is consent-gated: the hook only SCHEDULES (never networks), the agent offers the platform's ownclaude plugin update; the skill never rewrites its own files.TM1 Tool-Parameter Abuse(rm -rf) β the matched text is the verify step's pre-run lint that BANSrm -rfin reviewed code (skip-and-flag) β a defensive rule, the opposite of using it.RA2 Session Persistence(lens-prompt template) β instructs lenses to be instantiated from the canonical template and forbids injecting dev-governance β prompt-hygiene, not any OS/session-persistence mechanism RA2 keys on.EA2 Autonomous Decision("without asking") β the matched clause is "autoβ convene without asking", the documented user-CONFIGURED standing-consent mode (defaultask); the hard rules below force report-only with no human present and REFUSE gateless auto-apply.
- Method:
uvx --from git+https://github.com/NVIDIA/skillspector.git skillspector scan <plugin> --format jsonβ uvx fetches its own ephemeral Python, so no manual Python/pip install is needed; a JSON report is written even when the optional LLM stage is skipped. - LLM Semantic Scan: not run this pass (
--no-llmβ static-only is the documented, FP-prone baseline: pattern-match without the skill-contract context).
(Exact per-category counts and locations shift between SkillSpector versions β e.g. the RA2 match moved from the .coalboard/proposed/ staging text to the lens-template text; the categories and the all-false-positive verdict are stable.) This matches the family baseline: CoalMine and CoalTipple carry the same RA1 self-modification false positive (from consent-gated Self-Updating) β all-false-positive across the family; each repo's SECURITY.md pins its own last-scan score. The report JSON is not shipped.
hooks/coalboard-conductor.js is advise-only and Phoenix-pure: zero dependencies (Node builtins only), no network, no child processes, fail-silent (exits 0 on any error; never crashes the host), and it only emits the two sanctioned channels. It detects and injects β it never spawns workers, networks, or applies anything. Its stdin parse is guarded against non-object input.
The board is built so that reviewing untrusted work cannot harm the host:
- The work under review is DATA, never instructions β the lens prompts never obey an injected "approve this".
- Propose, never execute β the lenses emit a diff to
.coalboard/proposed/; the board itself runs no side-effect. A real side-effect (a migration, an API call, a deploy) fires only at the human-approved apply, with a warning, and is never auto-retried. - Verify is contract-isolated, NOT OS-sandboxed β a skill cannot OS-sandbox; the judge runs reviewed checks in the staging dir with a pre-run lint (banned modules /
rm -rf/ network), no real DB/network where possible, and a disposable VM for genuinely hostile code. Contract-enforced + the judge's discipline, not an OS guarantee. External SAST is optional, never a hard requirement. - Secrets are scrubbed β credential patterns are scrubbed from anything logged or displayed (best-effort defense-in-depth, contract-enforced β NOT a guarantee a secret is caught; the staging + read-only-worker boundary is the real protection).
scripts/lib/secrets.mjsis the reference scrubber + its test target β a DEV file, not part of the shipped plugin runtime. - No human, no apply β a non-interactive (cron/headless) run is report-only; the human consent gate is the load-bearing safety node.