Automated vulnerability scanner for agent platforms. Performs dependency scanning (npm audit, pip-audit), multi-database CVE lookup (OSV, NVD, GitHub Advisory), SAST analysis (Semgrep, Bandit), and agent-specific static hook inspection for OpenClaw hooks.
58
68%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Fix and improve this skill with Tessl
tessl review fix ./skills/clawsec-scanner/SKILL.mdComprehensive security scanner for agent platforms that automates vulnerability detection across multiple dimensions:
npm audit and pip-audit with structured JSON output parsingInstall with the Vercel Skills CLI for this harness:
npx skills add prompt-security/clawsec --skill clawsec-scanner -a openclaw -yThe scanner orchestrates four complementary scan types to provide comprehensive vulnerability coverage:
Dependency Scanning
npm audit --json and pip-audit -f json as subprocessesCVE Database Queries
Vulnerability schemaStatic Analysis (SAST)
--config auto or --config p/security-auditpyproject.toml configurationeval, exec), path traversal, unsafe deserializationDynamic Analysis (DAST)
HOOK.md metadataAll scan types emit a consistent ScanReport JSON schema:
{
scan_id: string; // UUID
timestamp: string; // ISO 8601
target: string; // Scanned path
vulnerabilities: Vulnerability[];
summary: {
critical: number;
high: number;
medium: number;
low: number;
info: number;
}
}Each Vulnerability object includes:
id: CVE-2023-12345 or GHSA-xxxx-yyyy-zzzzsource: npm-audit | pip-audit | osv | nvd | github | sast | dastseverity: critical | high | medium | low | infopackage: Package name (or 'N/A' for SAST/DAST)version: Affected versionfixed_version: First version with fix (if available)title: Short descriptiondescription: Full advisory textreferences: URLs for more infodiscovered_at: ISO 8601 timestampAutomated continuous monitoring via hook:
agent:bootstrap and command:new eventsevent.messages array with severity summaryCLAWSEC_SCANNER_INTERVAL environment variableVerify required binaries are available:
# Core runtimes
node --version # v20+
npm --version
python3 --version # 3.10+
# Scanning tools
pip-audit --version # Install: uv pip install pip-audit
semgrep --version # Install: pip install semgrep OR brew install semgrep
bandit --version # Install: uv pip install bandit
# Utilities
jq --version
curl --versionnpx clawhub@latest install clawsec-scannerset -euo pipefail
VERSION="${SKILL_VERSION:?Set SKILL_VERSION (e.g. 0.1.0)}"
INSTALL_ROOT="${INSTALL_ROOT:-$HOME/.openclaw/skills}"
DEST="$INSTALL_ROOT/clawsec-scanner"
BASE="https://github.com/prompt-security/clawsec/releases/download/clawsec-scanner-v${VERSION}"
TEMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TEMP_DIR"' EXIT
# Pinned release-signing public key
# Fingerprint (SHA-256 of SPKI DER): 711424e4535f84093fefb024cd1ca4ec87439e53907b305b79a631d5befba9c8
cat > "$TEMP_DIR/release-signing-public.pem" <<'PEM'
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAS7nijfMcUoOBCj4yOXJX+GYGv2pFl2Yaha1P4v5Cm6A=
-----END PUBLIC KEY-----
PEM
ZIP_NAME="clawsec-scanner-v${VERSION}.zip"
# Download release archive + signed checksums
curl -fsSL "$BASE/$ZIP_NAME" -o "$TEMP_DIR/$ZIP_NAME"
curl -fsSL "$BASE/checksums.json" -o "$TEMP_DIR/checksums.json"
curl -fsSL "$BASE/checksums.sig" -o "$TEMP_DIR/checksums.sig"
# Verify checksums manifest signature
openssl base64 -d -A -in "$TEMP_DIR/checksums.sig" -out "$TEMP_DIR/checksums.sig.bin"
if ! openssl pkeyutl -verify \
-pubin \
-inkey "$TEMP_DIR/release-signing-public.pem" \
-sigfile "$TEMP_DIR/checksums.sig.bin" \
-rawin \
-in "$TEMP_DIR/checksums.json" >/dev/null 2>&1; then
echo "ERROR: checksums.json signature verification failed" >&2
exit 1
fi
EXPECTED_SHA="$(jq -r '.archive.sha256 // empty' "$TEMP_DIR/checksums.json")"
if [ -z "$EXPECTED_SHA" ]; then
echo "ERROR: checksums.json missing archive.sha256" >&2
exit 1
fi
ACTUAL_SHA="$(shasum -a 256 "$TEMP_DIR/$ZIP_NAME" | awk '{print $1}')"
if [ "$EXPECTED_SHA" != "$ACTUAL_SHA" ]; then
echo "ERROR: Archive checksum mismatch" >&2
exit 1
fi
echo "Checksums verified. Installing..."
mkdir -p "$INSTALL_ROOT"
rm -rf "$DEST"
unzip -q "$TEMP_DIR/$ZIP_NAME" -d "$INSTALL_ROOT"
chmod 600 "$DEST/skill.json"
find "$DEST" -type f ! -name "skill.json" -exec chmod 644 {} \;
echo "Installed clawsec-scanner v${VERSION} to: $DEST"
echo "Next step: Run a scan or set up continuous monitoring"SCANNER_DIR="${INSTALL_ROOT:-$HOME/.openclaw/skills}/clawsec-scanner"
# Scan all skills with JSON output
"$SCANNER_DIR/scripts/runner.sh" --target ./skills/ --output report.json --format json
# Scan specific directory with human-readable output
"$SCANNER_DIR/scripts/runner.sh" --target ./my-skill/ --format text
# Check available flags
"$SCANNER_DIR/scripts/runner.sh" --helpCLI Flags:
--target <path>: Directory to scan (required)--output <file>: Write results to file (optional, defaults to stdout)--format <json|text>: Output format (default: json)--check: Verify all required binaries are installedEnable automated periodic scanning:
SCANNER_DIR="${INSTALL_ROOT:-$HOME/.openclaw/skills}/clawsec-scanner"
node "$SCANNER_DIR/scripts/setup_scanner_hook.mjs"This creates a hook that:
agent:bootstrap and command:new eventsCLAWSEC_SCANNER_INTERVAL rate limiting (default: 86400 seconds / 24 hours)Restart the OpenClaw gateway after enabling the hook, then run /new to trigger an immediate scan.
# Optional - NVD API key to avoid rate limiting (6-second delays without key)
export CLAWSEC_NVD_API_KEY="your-nvd-api-key"
# Optional - GitHub OAuth token for Advisory Database queries
export GITHUB_TOKEN="ghp_your_token_here"
# Optional - Scanner hook interval in seconds (default: 86400 / 24 hours)
export CLAWSEC_SCANNER_INTERVAL="86400"
# Optional - Allow unsigned advisory feed during development (from clawsec-suite)
export CLAWSEC_ALLOW_UNSIGNED_FEED="1"Each scan type is an independent module that can run standalone or as part of unified scan:
scripts/runner.sh # Orchestration layer
├── scan_dependencies.mjs # npm audit + pip-audit
├── query_cve_databases.mjs # OSV/NVD/GitHub API queries
├── sast_analyzer.mjs # Semgrep + Bandit static analysis
├── dast_runner.mjs # Static hook inspection orchestration
└── dast_hook_executor.mjs # Static hook source inspection helper
lib/
├── report.mjs # Result aggregation and formatting
├── utils.mjs # Subprocess exec, JSON parsing, error handling
└── types.ts # TypeScript schema definitions
hooks/clawsec-scanner-hook/
├── HOOK.md # OpenClaw hook metadata
└── handler.ts # Periodic scan triggerThe scanner prioritizes availability over strict failure propagation:
Critical failures that exit immediately:
All external tools run as subprocesses with structured JSON output:
import { spawn } from 'node:child_process';
// Example: npm audit execution
const proc = spawn('npm', ['audit', '--json'], {
cwd: targetPath,
stdio: ['ignore', 'pipe', 'pipe']
});
// Handle non-zero exit codes gracefully
// npm audit exits 1 when vulnerabilities found (not an error!)
proc.on('close', code => {
if (code !== 0 && stderr.includes('ERR!')) {
// Actual error
reject(new Error(stderr));
} else {
// Vulnerabilities found or success
resolve(JSON.parse(stdout));
}
});"Missing package-lock.json" warning
npm audit requires lockfile to runnpm install in target directory to generate"NVD API rate limit exceeded"
CLAWSEC_NVD_API_KEY environment variable"pip-audit not found"
uv pip install pip-audit or pip install pip-auditwhich pip-audit"Semgrep binary missing"
pip install semgrep OR brew install semgrepreturntocorp/semgrep"DAST static coverage finding"
info-level static coverage findings."Concurrent scan detected"
/tmp/clawsec-scanner.lockCheck scanner is working correctly:
# Verify required binaries
./scripts/runner.sh --check
# Run unit tests
node test/dependency_scanner.test.mjs
node test/cve_integration.test.mjs
node test/sast_engine.test.mjs
node test/dast_harness.test.mjs
# Validate skill structure
python ../../utils/validate_skill.py .
# Scan test fixtures (should detect known vulnerabilities)
./scripts/runner.sh --target test/fixtures/ --format text# All tests (vanilla Node.js, no framework)
for test in test/*.test.mjs; do
node "$test" || exit 1
done
# Individual test suites
node test/dependency_scanner.test.mjs # Dependency scanning
node test/cve_integration.test.mjs # CVE database APIs
node test/sast_engine.test.mjs # Static analysis
node test/dast_harness.test.mjs # DAST static hook inspection# JavaScript/TypeScript
npx eslint . --ext .ts,.tsx,.js,.jsx,.mjs --max-warnings 0
# Python (Bandit already configured in pyproject.toml)
ruff check .
bandit -r . -ll
# Shell scripts
shellcheck scripts/*.shCreate custom rules in .semgrep/rules/:
rules:
- id: custom-security-rule
pattern: dangerous_function($ARG)
message: Avoid dangerous_function - use safe_alternative instead
severity: WARNING
languages: [javascript, typescript]Update scripts/sast_analyzer.mjs to include custom rules:
const proc = spawn('semgrep', [
'scan',
'--config', 'auto',
'--config', '.semgrep/rules/', // Add custom rules
'--json',
targetPath
]);The scanner works standalone or as part of the ClawSec ecosystem:
Install the full ClawSec suite:
npx clawhub@latest install clawsec-suite
# Then use clawsec-suite to discover and install clawsec-scannerCritical/High severity findings should be addressed immediately:
Medium/Low severity findings can be addressed in normal sprint cycles:
Info findings are advisory only:
Found a security issue? Please report privately to security@prompt.security.
For feature requests and bug reports, open an issue at: https://github.com/prompt-security/clawsec/issues
AGPL-3.0-or-later
See LICENSE file in repository root for full text.
c6194eb
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.