Skip to content

Security: TheColliery/CoalTipple

SECURITY.md

Verifying CoalTipple

CoalTipple is verified under the same framework as CoalMine: all execution hooks follow the Phoenix-13 commandments, builds are fully reproducible from source, and security scans run periodically (event-driven).


πŸ”’ Reporting a Vulnerability

Report a vulnerability via GitHub private vulnerability reporting β€” Security β†’ Report a vulnerability. Do not open a public issue for a security finding.

  • In scope: the conductor hook's routing/sensitive never-down gate, the config-cascade merge-safety clamp, the installer's file-write and self-target paths, .claude/.coaltipple/proposed//damage-control, and anything else that could make the skill route, spend, or write somewhere it shouldn't.
  • Out of scope: a SkillSpector false positive, a style nit, or anything without a security impact β€” those go through the project's normal (public) issue flow instead.
  • What to expect: acknowledged promptly, triaged, and coordinated disclosure once a fix ships β€” no fixed SLA is committed today.

πŸ”‘ Commit & Tag Signatures

Every release tag and maintainer commit is SSH-signed (gpg.format=ssh); GitHub shows the Verified badge on them. Automated Dependabot / CI commits are not signed with the maintainer key (GitHub signs these with its own), so verify a signed release tag β€” the artifact a release consumer trusts:

echo "* ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEtqTWGKhX1Dk9nZP8ns13Wl5zsO1Cz3VlTS6m1p2fP9" > coaltipple_signers
git config gpg.ssh.allowedSignersFile ./coaltipple_signers
git tag -v "$(git describe --tags --abbrev=0)"

πŸ“¦ Dist Integrity

CoalTipple is distributed as source (human-auditable skill Markdown). The plugin distribution is generated at publish time:

  • Pre-commit/Pre-push Gates: node scripts/verify.mjs automatically verifies config schema matching, files presence, ensures the conductor is in sync with scripts/lib/keywords.mjs, and flags a detectable config key documented on a user-facing surface (SKILL.md, its references, README, and the conductor's notice regions) that no longer resolves in the schema β€” to prevent silent drift.
  • Reproducible Builds: Run node scripts/build-dist.mjs to regenerate the plugin distribution from source, then node scripts/verify.mjs to gate it against source β€” the parity check matches byte-for-byte, except .js/.json/.md files (today's shipped extensions) are compared EOL-normalized: a CRLF-vs-LF checkout of identical content is not flagged as drift, but any other content difference still is.
  • Test Suite: Run node scripts/test.mjs to execute zero-dependency unit tests.

πŸ”¬ Independent Scanning β€” NVIDIA SkillSpector

CoalTipple is evaluated against NVIDIA SkillSpector v2.3.9 (self-reported; the tool ships no tagged releases β€” the version is the uvx-from-git HEAD, 326a2b4). Last scan: CoalTipple v1.0.23 (commit ce0ebc0), 2026-07-02. Scanning is event-driven (a new SkillSpector version, or a genuinely new attack surface) β€” this pins the last version actually verified.

  • Static Scan (51/100 Β· 9 issues, all false-positive): consent-gated Self-Updating (v1.0.13) is flagged by the static RA1 self-modification rule Γ—8 (the /coaltipple:update command + the conductor's self-update scheduler + self-update comments; two of the eight are case-variant matches on one conductor line) β€” the hook only SCHEDULES (no network), the agent offers the platform's own claude plugin update; the skill never rewrites its own files. The 9th is HIGH Β· AR1 Anti-Refusal (the /coaltipple:update command text, a new v2.3.9 analyzer) β€” it matched "Always answer"; the sentence is "Always answer in the user's language" β€” a localization rule, not refuse-suppression. (Score trend on the same finding classes: v2.2.3 100 β†’ v2.3.1 51 β†’ v2.3.5 43 β†’ v2.3.9 51 β€” the rise is scanner-side, the new analyzer + a per-file scoring rework: the unchanged v1.0.20 dist moved 43 β†’ 51 across scanner versions; v1.0.23 scores the same.)
  • 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).

πŸ›‘οΈ Structural Safety (Phoenix-13)

The primary security assurance is structural. The coaltipple-conductor.js hook follows the Phoenix-13 rules:

  • Zero Dependencies & No Network: Runs 100% locally with no third-party libraries.
  • No Child Processes: Does not execute external terminal shell commands.
  • Fail-Silent: Exits 0 on any error, preventing execution blockages in the host agent.
  • No Secrets: Never reads, logs, or stores hardcoded API keys or credentials.
  • Damage Control: Writes proposals to a local .claude/.coaltipple/proposed/ sandbox or isolated git worktree before main merges them.

There aren't any published security advisories