NuGuard CLI Reference
NuGuard ships a Typer-based CLI covering the full AI application security pipeline: SBOM generation, static analysis, policy compliance, behavioral testing, and dynamic red-team testing.
Every command accepts --help for its live, in-terminal flag list — this doc is the browsable version, kept in sync with the source.
Severity legend, used throughout this doc and in NuGuard's own terminal output:
🔴 critical 🟠 high 🟡 medium 🟢 low ℹ️ info
Command Index
Jump straight to a command. Grouped by what you're trying to do.
🚀 Core Pipeline
| Command | What it does | |
|---|---|---|
| 🧱 | nuguard init |
Scaffold a nuguard.yaml with auto-detected defaults |
| 📦 | nuguard sbom |
Generate, validate, and export an AI-SBOM |
| 🔍 | nuguard analyze |
Static risk analysis from an AI-SBOM — no running app needed |
| 🔁 | nuguard scan |
Unified pipeline: SBOM → analyze, with optional policy/redteam |
📜 Policy & Compliance
| Command | What it does | |
|---|---|---|
| 📜 | nuguard policy |
Lint a Cognitive Policy, compile it, and check it against an SBOM or compliance framework |
| ✅ | nuguard validate |
Happy-path capability probes and boundary/policy compliance checks against a live app |
🎯 Live Testing
| Command | What it does | |
|---|---|---|
| 🎭 | nuguard behavior |
Intent-aware behavioral analysis against a live AI application |
| ⚔️ | nuguard redteam |
Dynamic adversarial testing against a live AI application |
| 🛡️ | nuguard pentest |
Explicitly authorized Nuclei-based conventional HTTP/HTTPS pentest |
| 🔌 | nuguard target |
Verify target connectivity and authentication before scanning |
🧪 Test-Run Management
Not implemented yet — see Planned Commands for what's coming.
| Command | What it does | |
|---|---|---|
| 🌱 | nuguard seed |
Seed canary data into the target before a scan |
| 📄 | nuguard report |
Regenerate a report for a completed test run |
| 🔎 | nuguard findings |
List findings from a completed test run |
| ⏮️ | nuguard replay |
Deterministically replay a completed test run |
🧱 nuguard init — scaffold a nuguard.yaml
Generates a nuguard.yaml config file with sensible defaults for the current project. Auto-detects existing SBOM files, Cognitive Policy docs, and canary seeds, and pre-fills paths so the file is ready to use with minimal editing.
Also creates companion starter files (canary.example.json, cognitive-policy.md) if they do not already exist.
nuguard init # write ./nuguard.yaml
nuguard init --path ./config/nuguard.yaml # write to a specific path
nuguard init --target http://localhost:8080
nuguard init --target http://localhost:8080 --source ./src --force
nuguard init --target http://localhost:8080 --llm # LLM-drafted cognitive policy
| Flag | Short | Default | Description |
|---|---|---|---|
--path |
-p |
./nuguard.yaml |
Output path for nuguard.yaml. Accepts a file path or a directory (writes nuguard.yaml inside it) |
--target |
-t |
http://localhost:8080 |
URL of the running AI application — sets target.url |
--source |
-s |
./ |
Source code directory for SBOM generation — sets source: in the config |
--force |
-f |
false |
Overwrite files that already exist |
--llm / --no-llm |
— | false |
Use an LLM to draft cognitive-policy.md with concise, app-specific defaults (5–6 allowed and restricted topics each). Requires LITELLM_API_KEY. Without this flag a blank template is written instead |
--dir |
-d |
— | (Legacy, hidden) Directory to write all starter files into. Prefer --path |
✨ Auto-detection: if an existing SBOM (
*.sbom.json), policy (cognitive-policy.md,cognitive_policy.md,policy.md,nuguard-policy.md), or canary (canary.json) is found in the target directory, the generatednuguard.yamlpre-fills those paths and the post-init "Next steps" list skips the corresponding steps.
📦 nuguard sbom — generate, validate, and export an AI-SBOM
SBOM generation, validation, and management.
Subcommands
| Subcommand | Description |
|---|---|
🟣 generate (default) |
Scan source or a remote repo and produce an AI-SBOM JSON |
🟣 validate |
Validate a JSON file against the bundled AI-SBOM schema |
🟣 register |
Register an SBOM in the local database (~/.nuguard/nuguard.db) |
🟣 show |
Display a registered SBOM by ID |
🟣 schema |
Print the bundled aibom.schema.json to stdout |
🟣 plugin |
Run a toolbox plugin or list available plugins |
🟣 nuguard sbom generate
nuguard sbom generate --source ./my-app --output app.sbom.json
nuguard sbom generate --from-repo https://github.com/org/repo --ref main
nuguard sbom generate --source . --llm --format cyclonedx
| Flag | Default | Description |
|---|---|---|
--source, -s |
— | Local source directory to scan |
--from-repo |
— | Remote Git URL to clone and scan |
--ref |
main |
Branch, tag, or commit for --from-repo |
--token |
$GH_TOKEN / $GITHUB_TOKEN |
GitHub token for private repos |
--output, -o |
app.sbom.json |
Output file |
--llm / --no-llm |
off | Enable LLM enrichment of SBOM nodes |
--scan-images / --no-scan-images |
off | Run syft on pulled base images to record their real OS and installed packages (requires syft on PATH and registry access). Overrides sbom_generation.scan_images |
--format, -f |
json |
json | cyclonedx | cyclonedx-ext | markdown — written alongside the JSON SBOM, not instead of it |
--config |
./nuguard.yaml |
Config file path — supplies sbom_generation.llm, llm.model, and llm.api_key even when --source is passed directly |
Either --source or --from-repo is required (or source: in nuguard.yaml).
The SBOM includes container images (base image, OS, packages), deployed workloads (replicas, ports, exposure, identity), and the relationships between workloads, images, endpoints, and gateways. sbom_generation.scan_images and sbom_generation.max_image_packages (default 200) in nuguard.yaml control image scanning and the per-image package cap. See SBOM schema.
🟣 nuguard sbom validate
nuguard sbom validate --file app.sbom.json
| Flag | Short | Default | Description |
|---|---|---|---|
--file |
-f |
required | SBOM JSON file to validate against the bundled schema |
🟣 nuguard sbom register / nuguard sbom show
Register an SBOM in NuGuard's local SQLite database (~/.nuguard/nuguard.db) and retrieve it later by ID.
nuguard sbom register --file app.sbom.json
nuguard sbom show --sbom-id <id-printed-by-register>
| Command | Flag | Description |
|---|---|---|
register |
--file, -f |
SBOM JSON file to register |
show |
--sbom-id |
ID of a previously registered SBOM |
🟣 nuguard sbom schema
Print the bundled aibom.schema.json JSON Schema to stdout — no flags.
nuguard sbom schema > aibom.schema.json
🟣 nuguard sbom plugin
Run a toolbox plugin against an existing SBOM or list available plugins.
nuguard sbom plugin list
# SARIF findings export
nuguard sbom plugin run sarif_export --sbom app.sbom.json --output results.sarif
# SPDX 3.0.1 JSON-LD export
nuguard sbom plugin run spdx_export --sbom app.sbom.json --output app.spdx.json
# CycloneDX 1.6 standard BOM
nuguard sbom plugin run cyclonedx_export --sbom app.sbom.json --output app.cdx.json
# CycloneDX 1.6 with AI-specific extensions
nuguard sbom plugin run cyclonedx_ext_export --sbom app.sbom.json --output app.cdx-ext.json
# Markdown report
nuguard sbom plugin run markdown_export --sbom app.sbom.json
| Plugin name | Output | Description |
|---|---|---|
cyclonedx_export |
CycloneDX 1.6 JSON | Standard BOM with nuguard:* properties and optional VEX vulnerabilities |
cyclonedx_ext_export |
CycloneDX 1.6 JSON | Extended BOM with modelCard, services, compositions, and nuguard:* properties |
spdx_export |
SPDX 3.0.1 JSON-LD | SPDX 3.0.1 export with ai_AIPackage, dataset_Dataset, and relationship graph |
sarif_export |
SARIF 2.1.0 JSON | Vulnerability findings export for GitHub Code Scanning |
markdown_export |
Markdown text | Human-readable SBOM report |
dependency_analyze |
JSON | Dependency breakdown and freshness analysis |
license_check |
JSON | Dependency licence compliance check |
vulnerability |
JSON | Structural + CVE scan (providers: vela-rules, osv, grype, all) |
| Flag | Default | Description |
|---|---|---|
--sbom |
required | SBOM JSON file to pass to the plugin |
--output, -o |
stdout | Write plugin output to this file |
--format, -f |
json |
Format hint passed to the plugin (json | markdown) |
🔍 nuguard analyze — static risk analysis, no live app needed
Static risk analysis from an AI-SBOM — no running application required.
Runs up to seven scanners in sequence. External scanners are silently skipped when their binary is absent or there's nothing for them to scan:
| Scanner | Checks | Requires |
|---|---|---|
| NGA structural rules | AI-specific structural risks (NGA-001–030) | (built in) |
| Supply-chain threat pack | Lifecycle scripts, CI/CD publish paths, AI-agent config poisoning (NGA-SC-001–027; also mapped to the OWASP Top 10 CI/CD Security Risks) | (built in) |
| OSV | Dependency CVE lookup | (built in) |
| Grype | Package / container CVEs | grype on PATH |
| Checkov | Infrastructure-as-code misconfigurations | checkov on PATH |
| Trivy | Container / filesystem vulnerabilities | trivy on PATH |
| Semgrep | AI-security source-code patterns | semgrep on PATH |
NGA rules always run. Use --nga to run only NGA rules and skip everything else, including the MITRE ATLAS annotation pass.
nuguard analyze --sbom app.sbom.json
nuguard analyze --sbom app.sbom.json --nga # NGA rules only (fast)
nuguard analyze --sbom app.sbom.json --config nuguard.yaml # load min_severity from config
nuguard analyze --sbom app.sbom.json --format sarif --output results.sarif
nuguard analyze --sbom app.sbom.json --source . --llm
nuguard analyze --sbom app.sbom.json --no-grype --no-trivy --min-severity high
nuguard analyze --sbom app.sbom.json --supply-chain-profile full --source .
nuguard analyze --sbom app.sbom.json --format json --format markdown --output reports/analyze
| Flag | Default | Description |
|---|---|---|
--sbom |
required | Path to AI-SBOM JSON |
--config, -c |
— | Path to nuguard.yaml; supplies min_severity and nga_only defaults (CLI flags override) |
--nga |
off | NGA structural rules only (NGA-001–030); disables every other scanner |
--format, -f |
markdown |
markdown | sarif | json (repeat flag or use comma-separated values for multiple outputs) |
--min-severity |
medium |
Minimum severity to include: critical | high | medium | low | info |
--source, -s |
— | Source directory for supply-chain, Checkov, Trivy, and Semgrep scans |
--atlas / --no-atlas |
on | MITRE ATLAS native graph checks |
--osv / --no-osv |
on | OSV dependency CVE scan |
--grype / --no-grype |
on | Grype CVE scan (requires grype on PATH) |
--grype-timeout |
180 (sec) |
Per-invocation timeout for Grype |
--grype-retries |
3 |
Retry attempts when Grype times out |
--checkov / --no-checkov |
on | Checkov IaC scan (requires checkov on PATH) |
--trivy / --no-trivy |
on | Trivy container/fs scan (requires trivy on PATH) |
--semgrep / --no-semgrep |
on | Semgrep AI-security rules (requires semgrep on PATH) |
--supply-chain / --no-supply-chain |
on | Supply-chain threat pack (NGA-SC-001–027) |
--supply-chain-profile |
standard |
ci | standard | full — full adds git-history checks |
--supply-chain-verify |
off |
Artifact registry verification: off | warn | fail |
--llm |
off | LLM enrichment in the ATLAS annotation pass |
--verbose, -v |
off | Show all 30 NGA rules (pass and fail) with evidence for why each passed |
--output, -o |
stdout | Write report to this file. Required when multiple formats are requested; base path expands to per-format files (for example analyze.json, analyze.md) |
--policy |
— | Reserved — accepted but not yet wired to a policy check in this command; use nuguard policy check instead |
Source path resolution for Checkov: When --source is provided, IaC file paths found in SBOM nodes are resolved relative to that directory. If no IaC nodes exist, Checkov scans the entire source directory. The SBOM target field is used as a fallback when --source is not set.
Exit codes
| Code | Meaning |
|---|---|
0 |
No findings at or above --min-severity |
1 |
One or more findings |
2 |
Analysis error (SBOM missing, unreadable, or fails schema validation) |
🔁 nuguard scan — the unified pipeline, everything in one command
Unified pipeline that chains SBOM generation, static analysis, and optional policy and red-team validation into a single command. The default step list is sbom,analyze; add policy and redteam explicitly when you want those validations to run.
nuguard scan --source .
nuguard scan --source . --steps sbom,analyze
nuguard scan --source . --steps sbom,analyze,policy,redteam --policy cognitive_policy.md --target http://localhost:3000
nuguard scan --source . --llm --output-dir reports/
nuguard scan --source . --supply-chain-profile full
| Flag | Default | Description |
|---|---|---|
--source, -s |
. |
Application source directory |
--output-dir, -o |
nuguard-reports |
Directory for all output artifacts (report.md, findings.json, findings.sarif) |
--steps |
sbom,analyze |
Comma-separated subset: sbom,analyze,policy,redteam |
--policy |
— | Cognitive Policy Markdown path (required for the policy step; used by redteam when supplied) |
--target |
— | Live app URL for the redteam step; if omitted, NuGuard falls back to an SBOM deployment URL when available |
--container-image |
— | Container image ref for Trivy image scan (e.g. myapp:latest) |
--fail-on |
high |
Severity that triggers exit code 1: critical | high | medium | low |
--llm |
off | LLM enrichment in the ATLAS annotation pass |
--no-atlas |
— | Skip ATLAS pass |
--no-osv |
— | Skip OSV scan |
--no-grype |
— | Skip Grype scan |
--no-checkov |
— | Skip Checkov scan |
--no-trivy |
— | Skip Trivy scan |
--no-semgrep |
— | Skip Semgrep scan |
--no-supply-chain |
— | Skip the supply-chain threat pack |
--supply-chain-profile |
standard |
ci | standard | full |
--supply-chain-verify |
off |
off | warn | fail |
💡 Gotcha: supplying
--policyor--targetdoes not change the step list by itself. Add--steps sbom,analyze,policy,redteamto actually run those steps.
Exit codes
| Code | Meaning |
|---|---|
0 |
Clean |
1 |
Findings at or above --fail-on |
2 |
Any critical finding — always non-zero, regardless of --fail-on |
3 |
Scan error (SBOM generation failure, analysis crash, etc.) |
📜 nuguard policy — lint, compile, and check a Cognitive Policy
Cognitive policy linting, SBOM cross-checking, and compliance assessment. Cognitive Policies are human-readable Markdown documents that define guardrails for AI application behavior, architecture, and components — usable for documentation, internal governance, or as enforceable policies in CI or runtime gates. nuguard init creates a cognitive-policy.md template with common sections.
Subcommands
| Subcommand | Description |
|---|---|
🟣 compile |
Compile a policy Markdown file into structured JSON controls |
🟣 validate |
Lint a policy file for completeness and common mistakes |
🟣 check |
Cross-check a policy against an SBOM and/or a compliance framework |
🟣 show |
Display a stored policy by ID (not yet functional — see below) |
🟣 nuguard policy compile
Compile a Cognitive Policy Markdown document into a structured JSON controls file. The compiled JSON is consumed by policy check and behavior for faster, LLM-optional assessment.
nuguard policy compile --policy cognitive_policy.md --output policy.controls.json
nuguard policy compile --policy policy.md --llm --output policy.controls.json
| Flag | Short | Default | Description |
|---|---|---|---|
--policy |
-p |
from nuguard.yaml |
Cognitive Policy Markdown file |
--config |
-c |
./nuguard.yaml |
Config file path |
--llm / --no-llm |
— | off | LLM-assisted compilation — extracts nuanced constraints that rule-based parsing may miss |
--output |
-o |
<policy>.json alongside the .md file |
Destination JSON file for compiled controls |
🟣 nuguard policy validate
Lint a Cognitive Policy Markdown file for completeness and common mistakes.
nuguard policy validate --file cognitive_policy.md
| Flag | Short | Default | Description |
|---|---|---|---|
--file |
-f |
required | Cognitive Policy Markdown file |
Exit codes
| Code | Meaning |
|---|---|
0 |
No issues |
1 |
Warnings only |
2 |
At least one error-level issue |
🟣 nuguard policy check
Cross-check policy against SBOM, run a compliance framework assessment, or both.
# Policy vs SBOM gap analysis
nuguard policy check --policy policy.md --sbom app.sbom.json
# Compliance framework assessment
nuguard policy check --sbom app.sbom.json --framework owasp-llm-top10
# Combined with LLM enrichment
nuguard policy check --policy policy.md --sbom app.sbom.json \
--framework owasp-llm-top10 --llm
# JSON + Markdown in one run
nuguard policy check --policy policy.md --sbom app.sbom.json \
--format json --format markdown --output reports/policy-check
# Read paths from nuguard.yaml
nuguard policy check
| Flag | Short | Default | Description |
|---|---|---|---|
--policy |
-p |
— | Cognitive Policy Markdown file |
--sbom |
— | — | AI-SBOM JSON to cross-check against |
--config |
— | ./nuguard.yaml |
Config file path |
--framework |
— | — | owasp-llm-top10 | nist-ai-rmf | eu-ai-act |
--controls |
— | — | Custom controls JSON file |
--format |
— | text |
text | json | markdown (repeat flag or use comma-separated values for multiple outputs) |
--output |
-o |
stdout | Write the assessment report to this file. Required when multiple formats are requested |
--llm / --no-llm |
— | off | LLM fallback for controls that can't be assessed from SBOM alone |
--verbose |
-v / -V |
off | Show all controls, including PASS results with evidence |
🟣 nuguard policy show 
⚠️
nuguard policy show --policy-id <id>always reports "not found" — there is currently no write path that saves a policy for later lookup by ID. Usenuguard policy compileand read the output file directly instead.
✅ nuguard validate — happy-path and policy-compliance smoke test
Validate AI application happy-path behaviour and cognitive policy compliance against a live target. Runs capability probes, happy-path simulations, boundary assertions, and per-turn policy evaluations, then reports a capability map (which tools were exercised, whether each call stayed policy-compliant) alongside any findings.
Controlled by nuguard.yaml's validate.workflows list — leave it empty to run all five:
| Workflow | What it does |
|---|---|
capability_probe |
Confirms each declared tool/capability actually responds |
happy_path |
Runs a scripted core-user-journey conversation |
policy_compliance |
Per-turn Cognitive Policy compliance check |
agent_routing |
Confirms multi-agent delegation routes the way the SBOM declares |
boundary_assertion |
Checks that declared refusals hold — see below |
boundary_assertion checks are declared explicitly in nuguard.yaml under validate.boundary_assertions, each with a name, an expectation of refused, and a forbid_pattern the response must not match.
This is a faster, more deterministic sibling to nuguard behavior — useful as a quick pass/fail smoke test in CI, where behavior's richer LLM-judged intent alignment isn't needed on every run.
nuguard validate
nuguard validate --target http://localhost:8000 --policy ./policy.md
nuguard validate -c ./nuguard.yaml --output results.json --fail-on critical
| Flag | Short | Default | Description |
|---|---|---|---|
--config |
-c |
./nuguard.yaml |
Config file path |
--target |
— | from nuguard.yaml (validate.target) |
Override the target URL |
--policy |
— | from nuguard.yaml |
Cognitive Policy Markdown path |
--canary |
— | from nuguard.yaml |
Path to canary.json seed file |
--output |
-o |
stdout | Write findings to this file. Required when multiple formats are requested |
--format |
-f |
text |
text | json | markdown (repeat flag or use comma-separated values for multiple outputs) |
--fail-on |
— | high |
Exit non-zero when any finding meets this severity: critical | high | medium | low |
--baseline |
— | — | Path to a previous CapabilityMap JSON for regression detection |
--verbose / --no-verbose |
-v / -V |
off | Print detailed per-turn traces |
Exit codes
| Code | Meaning |
|---|---|
0 |
Clean |
1 |
validate.target is not set |
2 |
A finding meets --fail-on (or an invalid --format was given) |
3 |
Unexpected runtime error |
🎭 nuguard behavior — intent-aware behavioral analysis
Intent-aware behavioral analysis against a live AI application. Runs static SBOM-policy alignment checks (no running app required) and/or dynamic behavior testing with per-turn LLM judging across five dimensions.
See behavior-guide.md for a full description of the engine.
# Static + dynamic (default)
nuguard behavior --config nuguard.yaml
# Static-only alignment checks
nuguard behavior --static
# Dynamic-only with override target
nuguard behavior --dynamic --target http://localhost:8090
# Markdown report to file
nuguard behavior --policy ./policy.md --output ./behavior-report.md --format markdown
# JSON + Markdown in one run
nuguard behavior --config nuguard.yaml --format json --format markdown --output ./behavior-report
# CI gate, comparing against a previous run
nuguard behavior --mode static+dynamic --fail-on critical --compare-to ./last-run.json
| Flag | Short | Default | Description |
|---|---|---|---|
--config |
-c |
./nuguard.yaml |
Config file path |
--mode |
-m |
static+dynamic |
static | dynamic | static+dynamic |
--static |
— | off | Shorthand for --mode static |
--dynamic |
— | off | Shorthand for --mode dynamic |
--target |
— | from nuguard.yaml |
Override behavior.target URL |
--policy |
— | from nuguard.yaml |
Cognitive Policy Markdown path |
--intent |
— | from SBOM | Override app intent (one-line description) |
--canary |
— | from nuguard.yaml |
Path to canary.json seed file |
--output |
-o |
stdout | Write report to this file. Required when multiple formats are requested; base path expands to per-format files |
--format |
-f |
text |
text | json | markdown (repeat flag or use comma-separated values for multiple outputs) |
--fail-on |
— | high |
Exit code 1 when any finding meets this severity: critical | high | medium | low |
--baseline |
— | — | Path to a previous BehaviorAnalysisResult JSON for regression detection |
--compare-to |
— | — | Path to a previous behavior report JSON, checked for run-profile comparability before diffing |
--strict-report |
— | off | Fail if Markdown report validation finds structural issues |
--resume |
— | — | Path to a checkpoint file from a previous aborted run; skips already-completed scenarios and merges results |
--verbose / --no-verbose |
-v / -V |
off | Print detailed per-turn traces |
Static checks (BA-001 – BA-008) — deterministic SBOM × policy cross-checks; no running application or LLM required. Covers missing system-prompt controls, unenforced topic boundaries, over-permissioned tool edges, missing rate-limit controls, and more.
Dynamic judging — every response is scored 1–5 on five dimensions:
intent_alignment · behavioral_compliance · component_correctness · data_handling · escalation_compliance
| Score | Verdict |
|---|---|
| ≥ 3.5 | ✅ PASS |
| ≥ 2.0 | 🟡 PARTIAL |
| < 2.0 | ❌ FAIL |
Exit codes
| Code | Meaning |
|---|---|
0 / 1 |
Per the severity-threshold logic above |
2 |
Config or setup error |
3 |
Unexpected runtime error |
⚔️ nuguard redteam — dynamic adversarial testing
Dynamic adversarial testing against a live AI application. Reads the AI-SBOM to derive an attack surface, generates and executes scenarios, and produces structured findings with OWASP/MITRE mappings.
See redteam-guide.md for a complete description of how the engine works.
Subcommands
| Subcommand | Description |
|---|---|
| 🟣 (default, no subcommand name) | Run the red-team scan |
🟣 catalog-export |
Export the built-in scenario catalog to YAML for customization |
🟣 nuguard redteam (scan)
# Basic scan (app already running)
nuguard redteam --sbom app.sbom.json --target http://localhost:8000
# Full scan with policy enforcement and canary detection
nuguard redteam --sbom app.sbom.json --target http://localhost:8000 \
--policy policy.md --canary canary.json --profile full
# Auto-launch the app then scan
nuguard redteam --sbom app.sbom.json --source ./my-app --launch
# Guided adaptive conversations (requires redteam LLM)
NUGUARD_REDTEAM_LLM_MODEL=openrouter/meta-llama/llama-3.3-70b-instruct \
NUGUARD_REDTEAM_LLM_API_KEY=sk-... \
nuguard redteam --sbom app.sbom.json --target http://localhost:8000 \
--guided --guided-max-turns 15 --guided-concurrency 2
# Skip scenarios that mutate/destroy target state
nuguard redteam --sbom app.sbom.json --target http://localhost:8000 \
--scenarios non-destructive
# Scan with a custom scenario catalog
nuguard redteam --sbom app.sbom.json --target http://localhost:8000 \
--catalog ./my-catalog.yaml --profile full
# CI gate — SARIF output, fail on high+
nuguard redteam --sbom app.sbom.json --target $APP_URL \
--profile ci -f sarif -o results.sarif --fail-on high
# JSON + Markdown in one run
nuguard redteam --sbom app.sbom.json --target $APP_URL \
--format json --format markdown --output results/redteam
| Flag | Short | Default | Description |
|---|---|---|---|
--config |
-c |
./nuguard.yaml |
Config file path |
--sbom |
— | from nuguard.yaml |
AI-SBOM JSON path |
--target |
— | SBOM discovery | Live application URL (http://host:port) |
--source |
— | — | App source directory — used for .env loading and --launch |
--launch / --no-launch |
— | off | Auto-start the app from the SBOM startup command; stop it after the scan. Requires --source |
--policy |
— | from nuguard.yaml |
Cognitive Policy Markdown path |
--canary |
— | from nuguard.yaml |
Canary JSON file path |
--catalog |
— | built-in catalog | Path to a custom scenario catalog YAML. Replaces the built-in catalog. Generate with nuguard redteam catalog-export |
--profile |
— | ci |
ci (high-signal only) or full (all scenarios) |
--scenarios |
— | both | Comma-separated filter: destructive, non-destructive |
--mode |
— | concurrent (redteam.mode) |
Engine: concurrent, progressive, or campaign (conversation-reuse, coverage-first; see redteam-guide) |
--min-impact-score |
— | 0.0 |
Exclude scenarios below this pre-score [0–10] |
--guided / --no-guided |
— | on when a redteam LLM is configured | Adaptive multi-turn guided conversations (TAP + PAIR) |
--guided-max-turns |
— | 12 |
Max turns per guided conversation |
--guided-concurrency |
— | 3 |
Parallel guided conversations |
--format |
-f |
text |
text | json | markdown | sarif (repeat flag or use comma-separated values for multiple outputs) |
--output |
-o |
— | Write findings to this file. Required when multiple formats are requested; base path expands to per-format files |
--fail-on |
— | high |
Exit code 2 if any finding meets this severity |
--resume |
— | — | Path to a checkpoint file from a previous aborted run; skips already-completed scenarios and merges results |
--verbose / --no-verbose |
-v / -V |
off | Print detailed per-turn traces |
🟣 nuguard redteam catalog-export
Export the full built-in scenario catalog to a YAML file for review or customization. The exported file can be edited and passed back with --catalog to replace the built-in catalog for a scan.
# Write to a file
nuguard redteam catalog-export --output my-catalog.yaml
# Print to stdout (pipe to less or grep)
nuguard redteam catalog-export
| Flag | Short | Default | Description |
|---|---|---|---|
--output |
-o |
stdout | Write the YAML to this path instead of printing |
Common edits after exporting:
- Set
enabled: falseon a scenario to skip it entirely. - Lower
base_impactbelow the profile threshold (e.g.< 5.0for--profile ci) to exclude it from fast scans without disabling it globally. - Edit
expected_controlorsuccess_signalto match your application's specific behavior.
See Customizing the Catalog in the redteam guide for a full walkthrough.
🎯 Target URL resolution order:
--targetflag →redteam.targetinnuguard.yaml→ SBOM-discovered URLs (local → staging → production) → error.
LLM configuration (no CLI flags — use env vars or nuguard.yaml):
| Env var | YAML key | Description |
|---|---|---|
NUGUARD_REDTEAM_LLM_MODEL |
redteam.llm.model |
Attack payload generation — must be an uncensored model |
NUGUARD_REDTEAM_LLM_API_KEY |
redteam.llm.api_key |
API key for the redteam LLM |
NUGUARD_REDTEAM_EVAL_LLM_MODEL |
redteam.eval_llm.model |
Response evaluation and report generation |
NUGUARD_REDTEAM_EVAL_LLM_API_KEY |
redteam.eval_llm.api_key |
API key for the eval LLM |
Advanced YAML-only options (set in nuguard.yaml, no CLI flag):
| YAML key | Default | Description |
|---|---|---|
redteam.catalog_path |
— | Path to a custom scenario catalog YAML (same as --catalog). Relative paths resolved from the config file directory |
redteam.strict_outcome |
false |
When ≥ 80% of events are 5xx/network errors, report inconclusive_target_errors instead of no_findings |
redteam.emit_pytest |
false |
Generate pytest regression tests for HIT findings (severity ≥ medium) |
redteam.emit_pytest_dir |
tests/redteam |
Directory to write generated pytest files |
redteam.tree_breadth |
0 (off) |
TAP: number of tactic variants to branch per depth level |
redteam.tree_max_depth |
0 (off) |
TAP: maximum tree depth before pruning non-improving paths |
🛡️ nuguard pentest — explicitly authorized conventional pentest
Bounded, explicitly authorized HTTP/HTTPS application pentesting using the open-source Nuclei engine. Separate from nuguard redteam/nuguard behavior: those exercise the AI-specific chat/agent surface, pentest runs conventional web-application checks (exposed endpoints, misconfig, injection, known-CVE templates) against the app's HTTP surface directly.
See cloud-pentesting.md for the full engine/scope/authentication model.
Requires Nuclei 3.11.1+ on PATH (or --nuclei-binary) — NuGuard does not install it. Refuses to run without --acknowledge-authorization.
# Minimal authorized scan
nuguard pentest --target https://staging.example.com --acknowledge-authorization
# Target + auth from nuguard.yaml
nuguard pentest --config nuguard.yaml --acknowledge-authorization
# Opt in to DAST/fuzzing templates and headless (JS-executing) templates.
# DAST fuzzes real request shapes from an OpenAPI document: an explicit
# --openapi-spec, else the target's own live /openapi.json, else one
# synthesized from --config's SBOM endpoints.
nuguard pentest --config nuguard.yaml --acknowledge-authorization \
--allow-active-fuzzing --allow-headless-browser
# Fuzz against an explicit OpenAPI document instead
nuguard pentest --config nuguard.yaml --acknowledge-authorization \
--allow-active-fuzzing --openapi-spec ./openapi.json
# App-specific custom templates, in addition to the always-on bundled ones
nuguard pentest --config nuguard.yaml --acknowledge-authorization \
--templates-dir ./my-nuclei-templates
# CI gate — SARIF output, fail on high+, 45-minute cap
nuguard pentest --config nuguard.yaml --acknowledge-authorization \
--format sarif --output pentest.sarif --fail-on high --scan-timeout 2700
| Flag | Short | Default | Description |
|---|---|---|---|
--target |
-t |
— | Authorized http(s):// target. Repeat for multiple targets |
--target-file |
— | — | UTF-8 file, one authorized target per line |
--config |
-c |
— | Load target.url/target.auth/sbom:/pentest: from nuguard.yaml. Explicit --target never retargets configured credentials |
--acknowledge-authorization |
— | required | Confirm you own or have documented permission to test every target. Always an explicit per-invocation flag — never configurable via nuguard.yaml |
--profile |
— | safe |
safe (low/medium/high/critical only) or standard (also informational) |
--allow-active-fuzzing |
— | off | Add a second Nuclei DAST/fuzzing pass (-dast), fed an OpenAPI document (see --openapi-spec below) so it fuzzes real request shapes, and stop excluding the fuzz/intrusive tags. Materially more, more intrusive requests |
--openapi-spec |
— | — | OpenAPI 3.x document driving --allow-active-fuzzing's DAST pass. Takes priority over the target's own live spec and the SBOM-synthesized fallback |
--live-openapi / --no-live-openapi |
— | on | Probe the target for a live OpenAPI/Swagger document (e.g. /openapi.json) to drive DAST when --openapi-spec is not given |
--use-sbom-endpoints / --no-use-sbom-endpoints |
— | on when sbom: is configured |
Allow DAST's OpenAPI input to fall back to a document synthesized from --config's SBOM API endpoints when the target serves no live spec |
--bundled / --no-bundled |
— | on | Run NuGuard's bundled generic checks and OWASP VulnerableApp fixture checks as an extra pass. Includes bounded SQLi, command injection, XSS, SSTI, CRLF, path traversal, LDAP injection, JWT cookie, redirect, and loopback SSRF probes intended for authorized sandbox/staging targets. Auto-signed locally on first use |
--templates-dir |
— | — | Trusted custom Nuclei templates directory, run as its own pass alongside the standard corpus and the bundled pass. Unsigned templates are rejected — sign with nuclei -sign -t <dir> first |
--allow-headless-browser |
— | off | Run Nuclei's headless-browser (JS-executing) templates. Auto-downloads a Chromium build (~120 MB) on first use; refused when running as root |
--allow-private |
— | off | Permit RFC1918/unique-local targets. Loopback, link-local, metadata, multicast, and reserved addresses stay blocked regardless |
--allow-dynamic-auth |
— | off | Allow a bounded, same-origin login_flow POST (from target.auth in nuguard.yaml) to obtain a bearer token before scanning |
--nuclei-secret-file |
— | — | Owner-only, exact-target static Nuclei Secret File — alternative to configured target.auth |
--nuclei-binary |
— | nuclei |
Executable name or path. No arbitrary scanner arguments are accepted |
--rate-limit |
— | 25 |
Max requests/second, 1–100 |
--concurrency |
— | 10 |
Max template concurrency, 1–25 |
--retries |
— | 1 |
Max request retries, 0–2 |
--request-timeout |
— | 10 |
Per-request timeout in seconds, 1–60 |
--scan-timeout |
— | 2700 |
Whole-scan timeout in seconds, 10–3600 (45 min default — multi-target/DAST/bundled passes need real headroom) |
--stats-interval |
— | 5 |
Seconds between live Nuclei progress-stats log lines, 1–60 |
--format |
— | text |
text | json | markdown | sarif |
--output |
-o |
stdout | Write the report atomically to this owner-only file |
--remediation-output |
— | — | Write an advisory JSON remediation plan (NuGuard's common format) to a separate file |
--fail-on |
— | high |
Exit 1 when a finding meets this severity: none|info|low|medium|high|critical |
Every flag above (except --acknowledge-authorization, which is always CLI-only) can instead be set once in nuguard.yaml under a pentest: block — see nuguard.yaml.example. Precedence is CLI flag > pentest: in nuguard.yaml > built-in default.
pentest:
profile: standard
allow_active_fuzzing: true
use_sbom_endpoints: true
scan_timeout: 3600
How coverage is assembled, all in one nuguard pentest invocation:
- The standard Nuclei template corpus (always runs, unless
--templates-dirnarrows it). - NuGuard's bundled generic templates (
--bundled, on by default) — auto-signed locally and includes bounded active exploit proofs; use--no-bundledif the approved test plan excludes them. - A DAST/fuzzing pass, only with
--allow-active-fuzzing(a separate pass: Nuclei's-dastreplaces rather than adds to the normal corpus, so NuGuard runs it as its own invocation and merges findings). - Your own
--templates-dir, if given, as its own pass too.
Findings from every pass are deduplicated and merged into one report; live progress (matched/requests/errors) is logged as each pass runs, not batched at the end.
🔌 nuguard target — verify connectivity before a scan
Verify connectivity and authentication against a live AI application before running a full scan. Prints a status table covering identity, auth type, HTTP status, response time, and any error details.
🟣 nuguard target verify
# Verify using nuguard.yaml
nuguard target verify --config nuguard.yaml
# Quick spot-check with inline options
nuguard target verify --target http://localhost:8000 \
--endpoint /chat \
--auth-header "Authorization: Bearer $TOKEN"
# Verify all tenant tokens in a canary file
nuguard target verify --config nuguard.yaml --canary canary.json
# With an SBOM: enables endpoint auto-discovery + a short pre-scan
# conversation that confirms which user/account is being scanned
nuguard target verify --config nuguard.yaml --sbom app.sbom.json
| Flag | Default | Description |
|---|---|---|
--config, -c |
./nuguard.yaml |
Config file path |
--target |
from nuguard.yaml |
Base URL of the target application |
--endpoint |
from nuguard.yaml |
Chat endpoint path (e.g. /chat, /api/v1/agent) |
--auth-header |
from nuguard.yaml |
Auth header string (e.g. "Authorization: Bearer $TOKEN") |
--canary |
from nuguard.yaml |
Path to canary.json — verifies each tenant session token can authenticate |
--sbom |
from nuguard.yaml |
AI-SBOM JSON — enables the same chat-endpoint auto-discovery and pre-scan account/golden-data discovery used by behavior and redteam |
--discovery-max-turns |
redteam.discovery_max_turns, or 3 |
Max pre-scan discovery turns (only relevant with --sbom) |
--skip-discovery / --no-skip-discovery |
off | Skip the pre-scan account/golden-data discovery conversation |
✅ Run
nuguard target verifybeforenuguard redteam,nuguard behavior, ornuguard validateto catch misconfigured endpoints, expired tokens, or firewall blocks early. Exits non-zero if any non-skipped credential fails.
WebSocket chat endpoints are supported transparently — when SBOM or live discovery identifies the
chat route as a WebSocket, target verify (and behavior/redteam) automatically switch to a
persistent WebSocket connection instead of per-request HTTP POSTs. No extra flags needed; there's
currently no nuguard.yaml override for hand-configuring WebSocket auth-message/completion-key
framing — it's auto-discovery only.
🟣 nuguard target discover-browser
For target apps that authenticate via an interactive redirect/OAuth flow (Auth0 Universal Login, SSO, etc.) that no static header/Basic Auth/login_flow config can drive. Logs in with a real (headless by default) browser using the credentials in target.auth, captures the resulting session cookie, and — unless --no-sniff-chat — types a message into the chat UI to sniff the app's own outgoing request and discover any extra payload field it requires (e.g. an opaque consumer/account ID). Previews (or, with --write, applies) the corresponding update to nuguard.yaml's target.auth / target.chat_payload_extras, preserving existing comments.
Requires the browser extra: pip install "nuguard[browser]" && playwright install chromium.
# Preview what would change (default: dry-run, nuguard.yaml untouched)
nuguard target discover-browser --config nuguard.yaml
# Apply the discovered auth/config to nuguard.yaml
nuguard target discover-browser --config nuguard.yaml --write --yes
# Debug with a visible browser window, skip payload-field sniffing
nuguard target discover-browser --config nuguard.yaml --headed --no-sniff-chat
| Flag | Default | Description |
|---|---|---|
--config, -c |
./nuguard.yaml |
Config file path — must already exist, since this command writes to it |
--target |
from nuguard.yaml |
Base URL of the target application |
--headed / --headless |
--headless |
Run with a visible browser window (useful for debugging a failed login) |
--timeout-s |
30 |
Per-step browser timeout, in seconds |
--cookie-file |
./cookies.txt next to nuguard.yaml |
Output path for the captured session cookies |
--sniff-chat / --no-sniff-chat |
--sniff-chat |
Attempt to discover extra chat payload fields by sniffing a live chat request |
--chat-message |
"Hello" |
Message typed into the chat UI during payload-field sniffing |
--write / --dry-run |
--dry-run |
Apply the discovered config to nuguard.yaml (default: print the diff only) |
--yes, -y |
off | Skip the interactive confirmation prompt when --write is set (for CI) |
Login-flow selectors (which button to click, which fields to fill) use generic heuristics by default. Override them per-app under target.browser_discovery in nuguard.yaml:
target:
browser_discovery:
login_button_text: ["Log in"]
username_selector: "#auth0-username"
password_selector: "#auth0-password"
chat_input_selector: "textarea#chat-input"
send_button_selector: "button#send"
⚠️ The captured session cookie is short-lived (apps commonly expire it within ~24h) — there is no automatic refresh yet. When
nuguard target verifyreceives HTTP 401 or 403 for the saved default cookie session, it prints a refresh hint; re-runnuguard target discover-browser --write --yes.
Planned Commands
nuguard seed, nuguard report, nuguard findings, and nuguard replay are registered in the CLI and appear in nuguard --help, but each is currently a stub: running any of them prints not yet implemented and exits with code 3. They're listed here so you know what they're for — not because they work today.
What each one will do
| Command | Intended purpose | Flags already wired |
|---|---|---|
nuguard seed |
Seed canary data into the target application before red-team testing, independent of running a full scan | --target, --seed-file, --output-canary |
nuguard report |
Regenerate a markdown | sarif | json report for a completed test run by ID, without re-running the scan |
--test-id, --format |
nuguard findings |
List findings from a completed test run, filterable by severity | --test-id, --severity |
nuguard replay |
Deterministically replay a completed test run's recorded traces against a (possibly different) target | --test-id, --target |
For now, --canary on redteam/behavior/validate covers the seeding use case (seed the values into your app yourself, then pass the file), and --output/--format on each command covers ad-hoc reporting.
Configuration File
All CLI flags can be set in nuguard.yaml. Run nuguard init to generate one with auto-detected defaults.
nuguard init # writes ./nuguard.yaml
nuguard init --target http://localhost:8080 --source ./src
Priority order: CLI flags > nuguard.yaml > environment variables > built-in defaults
Secrets are never stored directly — use ${ENV_VAR} interpolation:
# ─── Target application — shared by behavior and redteam ───────────────────
target:
url: https://your-app.example.com
# Authentication — set once; both behavior and redteam inherit it.
# Override per-command with behavior.auth or redteam.auth when needed.
auth:
# Option A: Login flow (preferred when the app exposes a /login endpoint)
# type: login_flow
# login_flow:
# endpoint: /api/login
# payload:
# username: ${APP_USERNAME}
# password: ${APP_PASSWORD}
# token_response_key: access_token
# token_header: "Authorization: Bearer"
# Option B: Static Bearer token
# type: bearer
# header: "Authorization: Bearer ${TARGET_TOKEN}"
# Option C: API key in a custom header
# type: api_key
# header: "X-API-Key: ${TARGET_API_KEY}"
# Option D: HTTP Basic Auth
# type: basic
# username: ${APP_USERNAME}
# password: ${APP_PASSWORD}
# Option E: No authentication (open endpoints, local dev)
# type: none
# Option F: Captured session cookie — for apps behind an interactive
# redirect/OAuth login (Auth0, SSO) that none of the above can drive.
# Generate/refresh with: nuguard target discover-browser --config nuguard.yaml --write
# type: cookie_file
# cookie_file: ./cookies.txt
redteam:
llm:
api_key: ${NUGUARD_REDTEAM_LLM_API_KEY}
See nuguard.yaml.example for the full annotated reference, including behavior:, redteam:, analyze:, and output: sections.
Getting Help
nuguard --help
nuguard init --help
nuguard sbom --help
nuguard sbom generate --help
nuguard analyze --help
nuguard scan --help
nuguard policy --help
nuguard policy check --help
nuguard validate --help
nuguard behavior --help
nuguard redteam --help
nuguard target verify --help
nuguard target discover-browser --help