agentsclimarketplace

Bash ast permission validator

Skill kjuhwa/skills-hub/skills/agent-sdk/bash-ast-permission-validator

Validate agent bash commands by parsing them into an AST (bash-parser) and evaluating each subcommand of a pipeline/&&/|| chain against an allowlist, instead of regex-matching strings.From its SKILL.md

Install
npx -y skills add kjuhwa/skills-hub --skill bash-ast-permission-validator

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.6 KB, 708 tokens by cl100k_base, as published. Nobody here has run it

Bash AST permission validator

When to use

  • Agent has a Bash tool and you want fine-grained allow/deny in "Explore" / read-only mode.
  • Regex matching on the raw string keeps letting dangerous constructs through (command substitution, process substitution, redirects).
  • Need to show the user WHY a compound command was blocked, pointing at the specific subcommand.

How it works

  1. Parse with bash-parser (npm) -> AST with nodes like Command, LogicalExpression (&&/||), Pipeline (|), Subshell, Redirect, CommandExpansion ($(...)), ParameterExpansion (${var}).
  2. Walk the AST; classify each node:
    • Command: look up name.text in the safe-command allowlist. OK if name + flags are allowed.
    • LogicalExpression or compound: ALL children must be allowed.
    • Pipeline: block entirely in safe mode (writes to network / side effects via the pipe target).
    • Redirect: block anything except < (input redirect).
    • CommandExpansion, ProcessSubstitution, ParameterExpansion (with unsafe defaults): block.
    • Background &: block.
  3. Return a BashValidationResult with: allowed, primary reason (typed discriminated union), and subcommandResults[] so the UI can highlight the offending subcommand.
  4. In "compound partial fail", report both passed + failed lists so the user can trim the command and retry.

Example

import bashParser from 'bash-parser';

function validate(cmd: string, allowlist: CompiledBashPattern[]): BashValidationResult {
  const ast = bashParser(cmd);
  const results: SubcommandResult[] = [];
  walk(ast, (node) => {
    if (node.type === 'Command') {
      const ok = allowlist.some(p => p.matches(node.name.text, node.suffix));
      results.push({ command: renderCommand(node), allowed: ok,
        reason: ok ? undefined : 'not in allowlist' });
    } else if (node.type === 'Pipeline') {
      results.push({ command: renderCommand(node), allowed: false,
        reason: 'pipelines blocked in explore mode' });
    } // etc.
  });
  const allowed = results.every(r => r.allowed);
  return allowed ? { allowed } : {
    allowed: false,
    reason: { type: 'compound_partial_fail',
      failedCommands: results.filter(r => !r.allowed).map(r => r.command),
      passedCommands: results.filter(r => r.allowed).map(r => r.command) },
    subcommandResults: results,
  };
}

Gotchas

  • bash-parser can throw on malformed input - wrap in try/catch and return { allowed: false, reason: { type: 'parse_error', error } }. Don't default-allow on parse failure.
  • Don't forget Windows: this validator is bash-only; for PowerShell you need a parallel powershell-validator.ts that shells out to the PS parser or parses with a separate grammar.
  • $(foo) command substitution must be blocked even if foo alone would pass - the substituted result is used as part of another command.
  • Keep subcommand rendering in sync with the AST nodes so error messages show the actual text the user typed.

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.