Skip to content
Development
Command

/security-audit

Periodic security posture audit — runs a scripted 4-phase checklist against repo files (not diffs), creates GitHub issues for confirmed findings

BOOST
From plugin
forgedock
11980 skills80 commands
Install
> /plugin marketplace add RapierCraftStudios/ForgeDock
> /plugin install forgedock@forgedock

How it fires

How this command gets triggered: by you, by Claude, or both.

  • Fires itselfClaude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/security-audit

Context preview

What this command does when you run it.

Periodic security posture audit — runs a scripted 4-phase checklist against repo files (not diffs), creates GitHub issues for confirmed findings

Command definition

security-audit.md
description: Periodic security posture audit — runs a scripted 4-phase checklist against repo files (not diffs), creates GitHub issues for confirmed findings
argument-hint: "[--repo <prefix>] [--phase 1|2|3|4|all] [--dry-run]"
install: extras

<!-- SPDX-FileCopyrightText: Copyright (c) RapierCraft Studios --> <!-- SPDX-License-Identifier: AGPL-3.0-or-later -->

/security-audit — Periodic Security Posture Audit

> **Skill names**: `{FORGE_SKILL_PREFIX}` is `forgedock:` (plugin install) or empty (`install.sh`), resolved once per run by `commands/work-on.md` § Skill Name Resolution. If the skill is not found under either name, STOP and report "skill not found" — never run the phase inline.

**Input**: $ARGUMENTS

You are the security posture auditor. Run a scripted 4-phase checklist against the **current state** of the target repository (not a PR diff). Each check uses bash/grep against repo files. Confirmed findings are posted as GitHub issues in the target repo, labeled `security,audit-finding,priority:P1/priority:P2/priority:P3`.

This command is designed to be run:

  • **Manually** after a pen test engagement
  • **Quarterly** as a scheduled posture review
  • **After major infrastructure changes** (new services, docker-compose rewrites, auth changes)

This is NOT a PR review — it does not approve or block. It creates issues for each gap found.

**Agent model policy**: `model: "{DEFAULT_MODEL}"` — resolved from forge.yaml `agents.default_model`, else "sonnet", `effort: xhigh` (deep tier — comprehensive security analysis). Fallback: `model: "opus"` if rate-limited. Feature gate: pass `effort` only on Claude Code >= 2.1.154. **NEVER use plan mode (EnterPlanMode).**

---

Config Preamble

Before executing any phase, read `forge.yaml` to resolve project references:

CONFIG_FILE="${FORGE_CONFIG:-forge.yaml}"
if [ -f "$CONFIG_FILE" ]; then
  GH_OWNER=$(yq '.project.owner' "$CONFIG_FILE")
  GH_REPO_NAME=$(yq '.project.repo' "$CONFIG_FILE")
  GH_REPO="${GH_OWNER}/${GH_REPO_NAME}"
  GH_FLAG="-R $GH_REPO"
  REPO_PATH=$(yq '.paths.root' "$CONFIG_FILE")
  # FORGE_REPO: the self-pipeline repo where security audit summary comments are posted.
  # Set project.forge_repo in forge.yaml if your pipeline repo differs from GH_REPO.
  FORGE_REPO=$(yq '.project.forge_repo // ""' "$CONFIG_FILE")
  [ -z "$FORGE_REPO" ] && FORGE_REPO="$GH_REPO"
  # BILLING_ENABLED: controls whether Phase 4 (Financial Integrity) runs.
  # Set billing.enabled: true in forge.yaml if your project uses Stripe billing.
  BILLING_ENABLED=$(yq '.billing.enabled // "false"' "$CONFIG_FILE")
else
  echo "WARNING: forge.yaml not found — commands will use placeholder values"
  echo "Run: cp forge.yaml.example forge.yaml  and fill in your project details"
  GH_REPO="your-org/your-repo"
  GH_FLAG="-R $GH_REPO"
  REPO_PATH="./"
  FORGE_REPO="$GH_REPO"
  BILLING_ENABLED="false"
fi

---

Multi-Repo Support

If your project spans multiple repositories, define them in the `repos.satellites` section of `forge.yaml`. The `--repo <prefix>` argument selects a satellite by its `prefix` field.

Parse `$ARGUMENTS` for:

  • **`--repo <prefix>`**: target repo prefix (default: primary repo from `project.owner/project.repo`)
  • **`--phase <N|all>`**: run only a specific phase, or all (default: `all`)
  • **`--dry-run`**: print findings but do NOT create GitHub issues

Set context variables from config:

REPO_PREFIX=$(echo "$ARGUMENTS" | grep -oP '(?<=--repo )\S+' || true)

if [ -n "$REPO_PREFIX" ]; then
  # Look up satellite repo by prefix in forge.yaml
  SATELLITE_REPO=$(yq ".repos.satellites[] | select(.prefix == \"$REPO_PREFIX\") | .repo" "$CONFIG_FILE" 2>/dev/null)
  if [ -n "$SATELLITE_REPO" ] && [ "$SATELLITE_REPO" != "null" ]; then
    GH_REPO="$SATELLITE_REPO"
    GH_FLAG="-R $GH_REPO"
    REPO_PATH=$(yq ".repos.satellites[] | select(.prefix == \"$REPO_PREFIX\") | .local_path" "$CONFIG_FILE" 2>/dev/null || echo "$REPO_PATH")
    # Also read billing flag for satellite if set
    BILLING_ENABLED=$(yq ".repos.satellites[] | select(.prefix == \"$REPO_PREFIX\") | .billing_enabled // \"false\"" "$CONFIG_FILE" 2>/dev/null || echo "false")
  else
    echo "WARNING: --repo prefix '$REPO_PREFIX' not found in forge.yaml repos.satellites — using default repo"
  fi
fi

# If REPO_PATH is not found locally, clone from GitHub
if [ ! -d "$REPO_PATH" ]; then
  gh repo clone {GH_REPO} {REPO_PATH} -- --depth=1 2>/dev/null || true
fi

---

Severity Classification

| Severity | Condition | |----------|-----------| | **P1** | Direct exploitation path with no mitigation; publicly reachable; auth bypass | | **P2** | Exploitable under specific conditions; security control absent but other mitigations present | | **P3** | Defense-in-depth gap; best-practice deviation; no active exploitability shown |

---

Phase 1: Infrastructure Posture

1A: Docker Compose Port Bindings

**What**: Non-web services bound to `0.0.0.0` expose internal ports to all network interfaces, including public ones when deployed without an external firewall.

**Check**:

DOCKER_COMPOSE_FILES=$(find "$REPO_PATH" -name "docker-compose*.yml" -not -path "*/.git/*" 2>/dev/null)
while IFS= read -r f; do
  [ -z "$f" ] && continue
  HITS=$(grep -n '0\.0\.0\.0:[0-9]' "$f" 2>/dev/null | grep -v '^\s*#' || true)
  if [ -n "$HITS" ]; then
    echo "FINDING [1A] $f:"
    echo "$HITS"
  fi
done <<< "$DOCKER_COMPOSE_FILES"

**Confirm**: For each hit, verify the port is NOT a web-facing port (80, 443, 8080, 3000). Ports like 6432 (PgBouncer), 6379 (Redis), 5432 (Postgres), 27017 (MongoDB) bound to `0.0.0.0` are confirmed findings.

**Severity**: `priority:P1` if no external firewall documented; `priority:P2` otherwise.

**Issue title**: `security: {SERVICE} port {PORT} bound to 0.0.0.0 — exposed beyond localhost`

---

1B: Dockerfile USER Directive

**What**: Containers running as root violate least-privilege. A compromised container running as root has full host acces

Read more
Ships withforgedock

ForgeDock — autonomous AI dev pipeline for Claude Code. GitHub as agent memory: issue in, PR out.

Get the whole plugin

Other commands on forgedock.