From claude-team-toolkit
Brakeman + bundler-audit combined for Rails security. Use for SQL injection/XSS/CSRF + Gemfile.lock CVE scans. Diff mode shows only NEW issues vs base branch (git worktree, non-destructive).
npx claudepluginhub tuannv14/claude-team-toolkit --plugin claude-team-toolkitThis skill is limited to using the following tools:
Combined Rails security scan. No credentials. Subcommands:
Prevents silent decimal mismatch bugs in EVM ERC-20 tokens via runtime decimals lookup, chain-aware caching, bridged-token handling, and normalization. For DeFi bots, dashboards using Python/Web3, TypeScript/ethers, Solidity.
Share bugs, ideas, or general feedback.
Combined Rails security scan. No credentials. Subcommands:
vulns, cves, audit, diff, ignore, update.
gem install brakeman bundler-audit
If a tool is missing, the relevant subcommand is skipped with a clear message.
brakeman_cmd() {
if [ -f "${1:-.}/Gemfile" ] && grep -q "brakeman" "${1:-.}/Gemfile" 2>/dev/null; then
echo "bundle exec brakeman"
else
echo "brakeman"
fi
}
vulns [path] [--severity high|medium|low|all] — Brakeman scanPATH_ARG="${1:-.}"; SEV="${SEV:-medium}"
mapfile -t CMD < <(brakeman_cmd "$PATH_ARG" | tr ' ' '\n')
"${CMD[@]}" -p "$PATH_ARG" -f json -o /tmp/brakeman.json --no-progress 2>/dev/null
jq -r --arg sev "$SEV" '
.warnings[] | select(
($sev=="all") or
($sev=="high" and .confidence=="High") or
($sev=="medium" and (.confidence=="High" or .confidence=="Medium")) or
($sev=="low" and true))
| "[\(.confidence)] \(.warning_type): \(.message)\n \(.file):\(.line)"
' /tmp/brakeman.json
jq -r '.warnings | group_by(.confidence) | .[] | "\(.[0].confidence): \(length)"' /tmp/brakeman.json
cves [path] — bundler-audit CVE scanPROJ="${1:-.}"
[ -f "$PROJ/Gemfile.lock" ] || { echo "No Gemfile.lock" >&2; return 1; }
bundle-audit update --quiet 2>/dev/null || true
(cd "$PROJ" && bundle-audit check --format json) > /tmp/bundler-audit.json 2>/dev/null
jq -r '
.results[]? | "[\(.advisory.criticality // "unknown" | ascii_upcase)] \(.gem.name) \(.gem.version)
CVE: \(.advisory.cve // .advisory.id) Fix: upgrade to \(.advisory.patched_versions | join(", "))
\(.advisory.title)"
' /tmp/bundler-audit.json
audit [path] — both + pre-PR gate (exit non-zero on HIGH or any CVE)"$0" vulns "$1"; echo ""; "$0" cves "$1"
HIGH_BR=$(jq -r '[.warnings[] | select(.confidence=="High")] | length' /tmp/brakeman.json 2>/dev/null || echo 0)
CVES=$(jq -r '(.results // []) | length' /tmp/bundler-audit.json 2>/dev/null || echo 0)
[ "$HIGH_BR" -gt 0 ] || [ "$CVES" -gt 0 ] && {
echo "GATE: $HIGH_BR HIGH Brakeman + $CVES CVEs"
return 1
}
diff [base-branch] — only NEW issues vs base (non-destructive)Uses git worktree add — your working tree is NEVER modified.
BASE="${BASE:-main}"
WT="$(mktemp -d)/rails-security-base"
trap "git worktree remove --force $WT 2>/dev/null; rm -rf $WT" EXIT INT TERM
git worktree add --quiet "$WT" "$BASE" || { echo "Cannot worktree at $BASE" >&2; return 1; }
mapfile -t CMD < <(brakeman_cmd "." | tr ' ' '\n')
(cd "$WT" && "${CMD[@]}" -f json -o /tmp/brakeman-base.json --no-progress 2>/dev/null) || true
"${CMD[@]}" -f json -o /tmp/brakeman-head.json --no-progress 2>/dev/null
echo "=== NEW Brakeman ==="
jq -s '(.[0].warnings|map(.fingerprint)) as $b | .[1].warnings | map(select(.fingerprint as $f | $b | index($f) | not)) | .[] | "[\(.confidence)] \(.warning_type) — \(.file):\(.line)"' /tmp/brakeman-base.json /tmp/brakeman-head.json
(cd "$WT" && bundle-audit check --format json) > /tmp/ba-base.json 2>/dev/null || echo '{}' > /tmp/ba-base.json
bundle-audit check --format json > /tmp/ba-head.json 2>/dev/null || echo '{}' > /tmp/ba-head.json
echo ""; echo "=== NEW CVEs ==="
jq -s '(.[0].results//[]|map(.advisory.id)) as $b | (.[1].results//[]) | map(select(.advisory.id as $id | $b | index($id) | not)) | .[] | "\(.gem.name) \(.gem.version) — \(.advisory.cve // .advisory.id)"' /tmp/ba-base.json /tmp/ba-head.json
Why worktree, not stash: stash is destructive on Ctrl-C/OOM, swallows merge conflicts. Worktree creates isolated checkout in temp dir.
ignore brakeman <fingerprint> [note] / ignore cve <CVE-ID> [note]# Brakeman:
mkdir -p config; [ -f config/brakeman.ignore ] || echo '{"ignored_warnings":[]}' > config/brakeman.ignore
jq --arg fp "$FP" --arg note "${NOTE:-no reason given}" \
'.ignored_warnings += [{fingerprint:$fp, note:$note}]' config/brakeman.ignore > config/brakeman.ignore.tmp \
&& mv config/brakeman.ignore.tmp config/brakeman.ignore
# CVE:
[ -f .bundler-audit.yml ] || echo "ignore: []" > .bundler-audit.yml
echo "Edit .bundler-audit.yml to add: $CVE_ID # ${NOTE:-add reason}"
ALWAYS require a reason — without it future maintainers can't audit decisions.
update — refresh advisory DBbundle-audit update # hits GitHub; fallback: bundle-audit check --no-update
brakeman.ignore and .bundler-audit.yml MUST be committed (audit trail of accepted-risk decisions).diff mode for PR review — only see NEW issues, drastically cuts noise.