agentsclimarketplace

Validation command whitelist gate

Skill kjuhwa/skills-hub/skills/security/validation-command-whitelist-gate

Before executing any user-supplied "validation" shell command, filter it through a binary prefix whitelist, reject all command-substitution forms, reject shell operators after stripping quoted regions, and enforce a hard per-command timeout and fixed cwd — so that even a fully attacker-controlled config string cannot escape to arbitrary command execution.From its SKILL.md

Install
npx -y skills add kjuhwa/skills-hub --skill validation-command-whitelist-gate

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

3.9 KB, 764 tokens by cl100k_base, as published. Nobody here has run it

Validation Command Whitelist Gate

A reusable safety check for the common pattern where a config file (gene, capsule, manifest, skill-yaml, CI job…) carries a validation: [ "<cmd>", … ] array that the host runtime must execute. Treat every entry as hostile input.

The four-layer gate

Run all four in order; reject on first failure.

1. Binary prefix whitelist

Only allow commands whose first token is in a tiny, hard-coded set, e.g. ["node", "npm", "npx"]. No bash, no sh, no python -c, no absolute paths like /usr/bin/node. If you find yourself wanting to expand the list, you are losing the battle — create a new validator type instead.

2. No command substitution

Reject if the raw string contains backticks ` or $( anywhere. These are the two primary shell-escape vectors and false positives are effectively zero in a validation context.

3. No shell operators — on a quote-stripped view

First remove anything inside matched single or double quotes, then check the remainder for ;, &, |, >, <. Stripping quotes first prevents a legitimate literal like node -e 'console.log("a;b")' from being rejected, while still catching node x && rm -rf /.

4. Bounded execution

  • Per-command timeout: 180 s (generous for tests, small enough that a hung command doesn't wedge the loop).
  • Fixed cwd: the project root. Never inherit the caller's cwd.
  • Do not spawn through a shell — use execFile / spawn with an argv array you split yourself. That neutralizes any residual operators that slipped past the string check.

Reference predicate

function isValidationCommandAllowed(cmd) {
  if (typeof cmd !== 'string' || !cmd.trim()) return false;

  // (2) command substitution
  if (cmd.includes('`') || cmd.includes('$(')) return false;

  // (3) shell operators, with quoted regions removed
  const stripped = cmd.replace(/'[^']*'|"[^"]*"/g, '');
  if (/[;&|<>]/.test(stripped)) return false;

  // (1) prefix whitelist
  const first = cmd.trim().split(/\s+/)[0];
  return ['node', 'npm', 'npx'].includes(first);
}

Promotion-time re-audit

If the config comes from an external source (hub, marketplace, peer), re-run the same check at the moment you promote the asset into the local store, not just at execution time. Rationale: the local store is the trust boundary; once a gene is "accepted" local callers assume it's safe. Promotion requiring an explicit --validated flag makes the operator step visible in audit logs.

Why this wins over "just sanitize"

  • No regex-escape gymnastics, no allowlist of "safe flags."
  • The rules are listable on a sticky note — reviewers can verify them.
  • It composes: adding a new allowed binary is a one-line diff with obvious blast radius.

Known sharp edges

  • A whitelisted binary with its own shell-eval feature (npm run <attacker-named-script>) still needs a second layer — consider also whitelisting the sub-command for npm.
  • npx <pkg> will download and execute arbitrary code from the registry; pair with --no-install or a registry allowlist if the threat model includes the supply chain.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 326,835. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.