Skip to content

Commands

All commands are available via 0sec <command>. You can also skip the subcommand and let auto-detect figure it out (see Getting Started).

Probe AI/LLM apps, web apps, or MCP servers for vulnerabilities. A REST API is scanned as a web target; --api-spec pre-loads its endpoints (see below).

Live network targets require --scope <file>. The CLI refuses an unscoped live target before making a request. Local source review and package audit commands do not need a network-target scope.

Terminal window
# Scan an LLM API
0sec scan --target https://api.example.com/chat --scope ./scope.json
# Scan a traditional web app
0sec scan --target https://example.com --mode web --scope ./scope.json
# Deep scan with Claude Code CLI
0sec scan --target https://api.example.com/chat --scope ./scope.json --depth deep --runtime claude
# Authenticated scan using a bearer token
0sec scan --target https://api.example.com --scope ./scope.json \
--auth '{"type":"bearer","token":"eyJhbGciOi..."}'
# Scan an API with an OpenAPI spec pre-loaded
0sec scan --target https://api.example.com --scope ./scope.json --api-spec ./openapi.yaml
# Run 5 attack strategies in parallel — first to succeed wins
0sec scan --target https://example.com --mode web --scope ./scope.json --race
# Evidence-Gated Attack Tree Search (EGATS)
0sec scan --target https://example.com --mode web --scope ./scope.json --egats
# Abort cleanly if the scan exceeds a USD ceiling
0sec scan --target https://example.com --mode web --scope ./scope.json --cost-ceiling 5
# Export findings to GitHub Issues
0sec scan --target https://example.com --mode web --scope ./scope.json \
--export github:myorg/myrepo
# Generate an HTML report (auto-opens in browser)
0sec scan --target https://example.com --mode web --scope ./scope.json \
--format html

Key flags:

FlagDescriptionDefault
--target <url>The URL or mcp:// endpoint to scan(required)
--scope <file>JSON engagement scope for a live network target(required for live targets)
--depth <depth>Scan depth: quick, default, deepdefault
--runtime <rt>Runtime: auto, api, claude, codex, geminiauto
--format <fmt>Output format: terminal, json, md, html, sarif, pdfterminal
--timeout <ms>Request timeout in milliseconds30000
--api-key <key>API key for the LLM provider(from env)
--model <model>Specific LLM model to useprovider default
--repo <path>Local source code path for white-box scanning(none)
--auth <json>Authenticated scanning credentials (see below)(none)
--api-spec <path>Path to an OpenAPI 3.x / Swagger 2.0 spec (JSON or YAML)(none)
--export <target>Export findings to an issue tracker, e.g. github:owner/repo(none)
--raceBest-of-N: run 5 attack strategies in parallel, first-to-succeed winsfalse
--egatsEvidence-Gated Attack Tree Search (beam search over hypothesis tree)false
--cost-ceiling <usd>Hard USD ceiling; aborts cleanly with partial findings preserved if exceeded(none)
--db-path <path>Path to SQLite database~/.0sec/0sec.db
--verboseShow animated attack replay and detailed agent reasoningfalse
--replayReplay the last scan’s results without re-runningfalse

The --auth flag accepts either an inline JSON string or a path to a JSON file. Four credential types are supported:

Terminal window
# Bearer token
--auth '{"type":"bearer","token":"eyJhbGciOi..."}'
# Session cookie
--auth '{"type":"cookie","value":"session=abc123; csrf=def456"}'
# HTTP Basic auth
--auth '{"type":"basic","username":"admin","password":"hunter2"}'
# Custom header (e.g. API key)
--auth '{"type":"header","name":"X-API-Key","value":"sk_live_..."}'
# Or load from a file
--auth ./auth.json

Point --api-spec at an OpenAPI 3.x or Swagger 2.0 document (JSON or YAML). 0sec will parse the spec, extract all endpoints with their parameter schemas and auth requirements, and seed the recon phase with that knowledge so the agent starts pentesting with full endpoint awareness instead of having to crawl.

Terminal window
0sec scan --target https://api.example.com --scope ./scope.json --api-spec ./openapi.yaml

With --race, 0sec spawns 5 attack strategies in parallel against the same target. The first agent to confirm a finding wins; the others are terminated. Ideal for hard targets where a single linear attack plan gets stuck.

Section titled “--egats — Evidence-Gated Attack Tree Search”

EGATS performs a beam search over a tree of attack hypotheses, pruning branches that fail evidence checks. Slower than --race but much more thorough.

Set a hard per-scan USD ceiling:

Terminal window
0sec scan --target https://example.com --mode web --scope ./scope.json --cost-ceiling 5

If cumulative estimated spend exceeds the ceiling, 0sec:

  • preserves findings collected so far
  • exits with status code 4
  • emits exit_reason: "cost_ceiling_exceeded" in the machine-readable result line

The CLI flag overrides 0SEC_COST_CEILING_USD.

Pushes every confirmed finding to a GitHub repo as an issue, with severity labels, evidence blocks, and reproduction steps. Requires GITHUB_TOKEN in the environment with repo scope.

Install and security-audit a package with static analysis and AI review.

Terminal window
0sec audit express --version 4.18.2
0sec audit requests --ecosystem pypi
0sec audit serde --ecosystem cargo
0sec audit alpine:3.20 --ecosystem oci
0sec audit react --depth deep --runtime claude
0sec audit left-pad --format html

The package is installed in a sandbox, scanned with the selected static scanner, checked against dependency advisories, and then reviewed by an AI agent that traces data flow and looks for supply-chain vulnerabilities.

Key flags:

FlagDescriptionDefault
<package>Package name(required)
--ecosystem <e>Package ecosystem: npm, pypi, cargo, ocinpm
--version <v>Specific version to auditlatest
--depth <d>Audit depth: quick, default, deepdefault
--runtime <rt>Runtime: auto, api, claude, codex, geminiauto
--format <fmt>Output format: terminal, json, md, html, sarif, pdfterminal
--timeout <ms>AI agent timeout in milliseconds600000
--api-key <key>API key for the LLM provider(from env)
--model <model>Specific LLM model to useprovider default
--cost-ceiling <usd>Hard USD ceiling; aborts cleanly with partial findings preserved if exceeded(none)
--db-path <path>Path to SQLite database~/.0sec/0sec.db
--verboseDetailed agent outputfalse

Deep source code security review of a local repo or GitHub URL.

Terminal window
# Review a local directory
0sec review ./my-ai-app
# Review a GitHub repo (cloned automatically)
0sec review https://github.com/user/repo
# Diff-aware review against a base branch
0sec review ./my-repo --diff-base origin/main --changed-only
# Profile a userspace C/C++ library for memory-safety + integer bugs
0sec review --target c-library ./libfoo
# Equivalent backward-compatible profile form
0sec review ./libfoo --profile c-library
# Profile a Linux kernel source tree for kernel-aware static review
0sec review --target linux-kernel ./linux

Key flags:

FlagDescriptionDefault
<repo>Local path or git URL(required)
--depth <d>Review depth: quick, default, deepdefault
--format <fmt>Output format: terminal, json, md, html, sarif, pdfterminal
--runtime <rt>Runtime: auto, api, claude, codex, geminiauto
--target <t>Review target alias: app, default, c-library, linux-kernel(none)
--profile <p>Review profile: default, c-library, linux-kerneldefault
--diff-base <ref>Git base ref for diff-aware review(none)
--changed-onlyRestrict static scanner leads + prioritization to changed filesfalse
--timeout <ms>AI agent timeout in milliseconds600000
--api-key <key>API key for LLM provider(from env)
--model <model>Specific LLM model to useprovider default
--cost-ceiling <usd>Hard USD ceiling; aborts cleanly with partial findings preserved if exceeded(none)
--db-path <path>Path to SQLite database~/.0sec/0sec.db
--verboseDetailed agent outputfalse

The --target alias selects the review workflow while preserving the older --profile flag for scripts. --target app and --target default both map to the default application profile. If both flags are present, they must select the same workflow. The default profile is for application code (web / JS / TS / Python / Go business logic) and is what you want for an AI app, an SaaS backend, or a typical npm package.

c-library — userspace C/C++ memory-safety review. Tunes the agent toward integer-overflow on allocation paths, signed/unsigned conversion at memcpy length args, off-by-one parser bounds checks, use-after-free across error paths, format-string sinks. Pairs with the tier-1/2/3 harness ladder: a single-function libFuzzer harness compiled with -fsanitize=address,undefined is the baseline validator; tier-2 (multi-component link) and tier-3 (QEMU full-stack) escalate when reachability requires it. Every finding must be backed by a sanitizer log from a harness that actually trips — static reasoning alone is recorded as a hypothesis, not a finding.

linux-kernel — kernel-aware static review. Tunes the agent toward kernel-specific failure modes: missing copy_from_user length validation, signed/unsigned int comparison on user-controlled length, UAF across __free_pages/kfree_skb error paths, refcount races (get_task_struct without matching put_task_struct), TOCTOU on inode->i_* fields, unsafe unsafe_get_user/unsafe_put_user outside a user_access_begin/user_access_end block, and skb cow/share violations (the Dirty Frag class — in-place AEAD/cipher on a shared frag without skb_cow_data / skb_unshare). The agent first verifies the tree is actually a kernel tree (MAINTAINERS, Kconfig, KERNELRELEASE, arch/) and refuses if not. Findings are tagged with the same subsystem labels (fs/nfsd, net/tcp, mm, …) used by the kernel-crash ingest pipeline so the two streams line up.

Non-goal: this is static review, not exploit reproduction. The linux-kernel profile produces hypothesis-grade findings grounded at file:line and accompanied by a syzkaller-program or C-syscall reproducer SHAPE — it does not compile or boot the kernel. A libFuzzer harness does not apply (kernel state isn’t reachable from a libFuzzer process). For machine-checkable verification, see issues #271 (kernel oracle) and #272 (syzkaller harness scaffold). Static-only findings are flagged confidence: 0.4 with hypothesis: true until the verification phase lands.

Generate a narrowly-scoped patch for one independently reproduced local source finding, validate it in an isolated Git worktree, and optionally apply it.

The command is intentionally stricter than remediation guidance:

  • <repo> must be the clean root of a local Git worktree;
  • the finding or --verification-result input must establish verification_result.status: "reproduced";
  • the finding must have a code-only verificationSpec that describes the vulnerable source state;
  • --test-command is required and runs after every candidate patch;
  • by default the original checkout is unchanged;
  • --apply modifies the original checkout only after the candidate invalidates the vulnerable-source contract and the regression command succeeds.
Terminal window
# Generate and validate a candidate; keep the original checkout unchanged.
0sec fix ./my-app \
--finding ./finding.json \
--test-command "pnpm test" \
--verification-result ./verification.json \
--output ./candidate-fix.patch
# Apply only a candidate that passed the isolated re-check and regression run.
0sec fix ./my-app \
--finding ./finding.json \
--test-command "pnpm test" \
--verification-result ./verification.json \
--apply

fix currently supports source-only verification contracts. A live behavioral re-test needs a provisioned target and remains outside this command’s contract; do not treat a source fix as proof that an unrelated deployed target has already been remediated.

FlagDescriptionDefault
<repo>Clean local Git worktree with the affected sourcerequired
--finding <path>Finding JSON with a code-only verificationSpecrequired
--verification-result <path>Optional 0sec verify JSON when the finding does not already carry a reproduced result
--test-command <command>Explicit regression command run in the candidate worktreerequired
--runtime <runtime>auto or apiauto
--model <model>Model identifier for the selected runtimeprovider default
--timeout <ms>Per-model-call timeout600000
--test-timeout <ms>Regression-command timeout300000
--max-attempts <n>Candidate patch attempts; capped at 33
--applyApply only the patch that passed both gatesfalse
--output <path>Persist the validated apply_patch DSLstdout only

Run foxguard-backed kernel advisory variant hunting against a Linux source tree.

Terminal window
# Scan a kernel tree with a foxguard rule family
0sec kernel variant-hunt \
--tree ./linux \
--advisory dirty-frag.md \
--rules ./foxguard/rules/kernel/dirty-frag-class \
--output json
# Render an existing foxguard SARIF file as 0sec findings
0sec kernel variant-hunt --tree ./linux --sarif-input ./foxguard.sarif

This command is orchestration only: foxguard owns the structural rules, and 0sec maps SARIF hits into normal Finding objects with kernel subsystem labels, confidence, evidence text, and SARIF/JSON/terminal output. A hit is a variant-hunt candidate, not a confirmed crash; use kernel triage, Coccinelle/CodeQL, fuzzing, or 0sec ingest --verify when crash evidence exists.

Key flags:

FlagDescriptionDefault
--tree <path>Linux source tree to scan(required)
--advisory <url-or-file>Advisory provenance attached to each finding(none)
--rules <path>Foxguard rule directory, such as rules/kernel/dirty-frag-classfoxguard default
--foxguard <path>Foxguard binary path or command nameauto-detect
--sarif-input <path>Use existing foxguard SARIF instead of invoking foxguard(none)
--timeout <ms>Foxguard timeout in milliseconds120000
--output <fmt>Output format: terminal, json, sarifterminal
--verboseInclude per-finding analysis in terminal outputfalse

Mine and adversarially rerank syzbot’s abandoned queue:

Terminal window
0sec kernel syzbot-mine --subsystems net,xfrm,crypto,vsock,nfc --limit 30 --details 15 --detail-delay 750

--details bounds the detail/reproducer enrichment pass. 0sec records the requested sandbox and harness setup. It also inspects the syz program for mounts, TUN/qdisc/XFRM administration, synthetic devices, BPF setup, and call-level fault injection before reranking privileged, one-shot, stale, and incomplete leads. Missing enrichment is explicit; it is never treated as evidence of unprivileged reachability. --detail-delay paces requests to the public dashboard; HTTP throttling still fails closed.

Treat syzkaller campaign lanes separately: sandbox=none is privileged discovery, while sandbox=setuid is only zero-cap-plausible configuration evidence. Neither proves zero-cap reachability. That label requires runtime attestation showing non-root real and effective UIDs and an empty effective capability set for the reproducing execution, bound to a hashed artifact. The execution boundary must also attest no_new_privs.

Import kernel crash reports and optionally verify them against attached reproducers.

Terminal window
# Parse one crash report into findings
0sec ingest ./crashes/report.log
# Parse a directory of syzbot-style reports and reproducers
0sec ingest ./crashes --output json
# Validate reports against attached reproducers
0sec ingest ./crashes --verify --output json
# Run a standalone C reproducer through the kernel VM oracle
0sec ingest --reproducer ./poc.c --kernel-tree ~/src/linux --config kasan --output json
# Run a raw syzkaller program when the guest image provides syz-execprog
0sec ingest --syz ./program.syz --kernel-tree ~/src/linux --config kasan --output json
# Pivot each known-subsystem crash into source review for sibling bugs
0sec ingest ./crashes --review-subsystem --tree ~/src/linux --output json

For directory ingest, reproducers are attached by matching filename prefix:

  • crash001.log + crash001.c
  • bug-42.report + bug-42.syz

When --verify is enabled, the command returns a richer result object per crash:

  • sourcePath
  • reproducerPath
  • finding
  • verification

Without a configured kernel VM, verification falls back to static consistency and reproducer analysis only.

When --reproducer or --syz is used, ingest skips crash-report parsing and runs that program directly through the kernel VM oracle. --kernel-tree resolves a KASAN VM build/cache entry; if 0SEC_KERNEL_QEMU_KERNEL and 0SEC_KERNEL_QEMU_DISK already point at built artifacts, those are reused as the fastest cache hit.

When --review-subsystem is enabled, ingest keeps the original crash finding and appends review-derived sibling findings. Each sibling finding carries relatedFindingId pointing back to the crash finding that triggered the source hunt. Crashes with unknown subsystem, or subsystems that do not resolve under --tree, are reported in the JSON skipped list.

Key flags:

FlagDescriptionDefault
<path>Crash report file or directory of reports(required)
--format <fmt>Input hint: auto, kasan, ubsan, oops, syzkaller, genericauto
--output <fmt>Output format: terminal, json, sarifterminal
--verifyRun the kernel oracle for each parsed reportfalse
--reproducer <path>Run a standalone C reproducer through the kernel VM oracle(none)
--syz <path>Run a standalone syzkaller .syz program through the kernel VM oracle(none)
--kernel-tree <path>Linux source tree for kernel VM build/cache resolution(none)
--config <profile>Kernel VM config profile for --kernel-tree; currently kasankasan
--kernel-cache-dir <path>Override kernel VM build cache directory~/.cache/0sec/kernel-vm
--force-kernel-buildRebuild kernel VM artifacts even if a cache entry existsfalse
--review-subsystemRun linux-kernel source review against each crash subsystemfalse
--tree <path>Linux source tree required by --review-subsystem(none)
--runtime <runtime>Review runtime for --review-subsystem: auto, claude, codex, gemini, apiauto
--model <model>Model for --review-subsystem(runtime default)
--cost-ceiling <usd>Hard cost ceiling for --review-subsystem(none)
--verboseInclude extra crash-analysis detail in terminal outputfalse

Set 0SEC_KERNEL_QEMU=1 to enable VM-backed execution. The runner expects a bootable guest image with:

  • a boot path that mounts the osecshare 9p share and executes /mnt/0sec/runner.sh
  • a working C toolchain (gcc)
  • a linker toolchain (ld, provided by binutils)
  • permission to read kernel logs via dmesg

For the maintained Docker build recipe, exact guest contract, and troubleshooting steps, see Kernel VM Verification.

Required environment variables:

Terminal window
export 0SEC_KERNEL_QEMU=1
export 0SEC_KERNEL_QEMU_KERNEL=/path/to/bzImage
export 0SEC_KERNEL_QEMU_DISK=/path/to/rootfs.img

Useful optional variables:

Terminal window
export 0SEC_KERNEL_QEMU_APPEND='console=ttyS0 root=/dev/vda rw nokaslr panic=-1 init=/sbin/0sec-init'
export 0SEC_KERNEL_QEMU_BOOT_TIMEOUT_SEC=120
export 0SEC_KERNEL_QEMU_TIMEOUT_SEC=60
export 0SEC_KERNEL_QEMU_ACCEL=kvm
export 0SEC_KERNEL_QEMU_SHARE_TAG=osecshare
export 0SEC_KERNEL_QEMU_ARTIFACT_DIR=/tmp/0sec-kvm-runs

If the VM is not configured, 0sec does not claim a reproduced crash; it reports static-only verification with capped confidence.

Triage findings and manage learned false-positive memories. Every time you mark a finding as a false positive, 0sec stores a pattern that future verify passes will consult — think Semgrep’s nosemgrep but learned automatically.

Terminal window
# Create a memory from an existing finding
0sec-cli triage memory add --finding NF-001 --reason "test fixture, not reachable in prod"
# List all memories
0sec-cli triage memory list
0sec-cli triage memory list --scope target --category xss
# Delete a memory
0sec-cli triage memory remove <memory-id>
# Mark a finding as FP and auto-create a memory
0sec-cli triage mark-fp NF-042 --reason "known sandbox echo endpoint"

triage memory add

FlagDescriptionDefault
--finding <id>Finding ID (full or prefix) to derive the memory from(required)
--reason <text>Why this finding is a false positive(required)
--scope <scope>Memory scope: global, target, packagetarget
--scope-value <v>Scope identifier (target URL or package name)(inferred)
--db-path <path>Path to SQLite databasedefault

triage memory list

FlagDescription
--scope <scope>Filter by scope: global, target, package
--category <cat>Filter by vulnerability category
--db-path <path>Path to SQLite database

triage memory remove <id> — deletes a memory by its ID.

triage mark-fp <finding-id> — flips a finding’s triage status to suppressed and auto-creates a memory.

FlagDescriptionDefault
--reason <text>Why this finding is a false positive(required)
--scope <scope>Memory scopetarget
--scope-value <v>Scope identifier(inferred)

Enable memory injection into the verify pipeline with 0SEC_FEATURE_TRIAGE_MEMORIES=1 (see Configuration).

The interactive operator console: one conversational surface that drives the whole tool registry (recon, web pentest, source/package scan, variant hunt, verify, patch-gen). It is what you get by running the binary with no arguments, and it is also reachable explicitly.

Terminal window
# Full console — bare invocation launches straight into chat
0sec
0
# Explicit, with an engagement target and a scope file
0sec console --target https://api.example.com --scope ./scope.json
# Start in Co-pilot: approve every non-read-only tool call
0sec console --autonomy copilot --scope ./scope.json
# Expose the generic-scanner wrappers (sqlmap/nikto/…)
0sec console --scope ./scope.json --allow-scanners
FlagDescriptionDefault
--target <url>Engagement target the tools operate against; can also be named in chat(none)
--scope <file>Initial authorization scope. Required for YOLO and for the Node fallback(none)
--model <id>Override the LLM model idprovider default
--role <role>Tool set to expose: audit, review, discovery, attack, verify, reportaudit
--autonomy <mode>standard, copilot, or yolostandard
--max-tool-calls <n>Safety cap on tool-call rounds per operator message20
--allow-scannersExpose generic-scanner tool wrappersoff

Two front-ends exist. Under Bun with a TTY on both stdin and stdout you get the full OpenTUI console described below. Otherwise 0sec console falls back to a plain readline REPL, which requires --scope — it has no approval surface, so it cannot grant session-only scope extensions and denies them outright.

Anything starting with / is handled locally and never reaches the model; an unrecognised one produces a local notice. Everything else is sent to the engine as an operator message.

CommandAliasesBehaviour
/help [command]/?, /commandsRenders the command list as a panel, grouped by category. An argument filters by name/alias prefix.
/statusPanel: model and provider, mode, target, scope rules (or scope on demand), tool count, turns, cumulative input→output tokens.
/toolsPanel listing the tool names registered for this session’s role.
/agentsNotice listing the subagents running right now, or “No active subagents”. It is a live view, not a catalogue.
/scopePanel: target, mode, and the in-scope rules. With no scope it says so explicitly rather than reading as permissive.
/mode [standard|copilot|yolo]With no argument, opens a picker. With an argument, switches directly. Refused while a turn is in flight; YOLO is refused — and shown greyed in the picker — when no scope is configured.
/model [id]/modelsWith no argument, opens a model picker whose header names the providers that currently hold credentials. With an id, rebuilds the session on that model and carries the conversation across; a failed rebuild leaves you on the old one. Refused mid-turn.
/providers/login, /authOpens a picker of the providers 0sec can detect, each marked configured (and via which env var) or not, with the exact env var to set. Selecting one prompts for a key, which is stored 0600 in ~/.0sec/credentials.json and exported into the running process. The value is never echoed back into the transcript.
/settings/config, /prefsOpens a picker of console display settings. Enter flips a boolean or cycles an enum, then reopens against the new values. Persisted to ~/.0sec/tui-settings.json.
/resume/sessionsOpens a picker of saved transcripts for the current working directory (newest first, up to 30). See Session persistence. Refused mid-turn.
/explain [topic]/eli5Sends a real turn asking for a plain-language explanation of the previous result, or of topic. It is a normal model call and costs tokens.
/feedback <message>Appends the message, with a timestamp, version, model and mode, to ~/.0sec/feedback.md. Nothing is transmitted anywhere.
/clear/newClears the conversation. Readline fallback only — see the caveat below.
/historyOpens the scan-history screen.
/findings/findsOpens the findings screen.
/replayOpens the replay screen.
/ops/runsOpens mission control (active and recent operations).
/launcher/homeOpens the home screen.
/doctorOpens the diagnostics screen.
/chatNo-op from the chat view; it reports that chat is already active.
/backReturns to the previous screen.
/exit/quitEnds the session and returns to the shell.

Front-end coverage. /agents, /scope, /chat, /back, /launcher, /ops, /history, /findings, /replay and /doctor are TUI-only; the readline fallback recognises them and tells you the Bun TUI is needed. Of the rest, the fallback implements /help, /status, /tools, /clear, /mode and /exit. /model, /resume, /providers, /settings, /explain and /feedback are parsed there but currently do nothing — no output, no error.

/clear caveat. It is registered, offered by the TUI’s command menu and listed by /help, but the TUI’s command router has no handler for it, so typing it there reports unknown command: /clear. It works in the readline fallback, where it calls clearConversation().

KeyAction
/Typing a leading / opens the command menu inline under the composer; it filters as you type.
Ctrl+P / Ctrl+KPuts a / in the composer, which opens the same command menu. On the non-chat screens (mission control, doctor, history, findings, replay, home) the same chord toggles that screen’s own command palette.
/ Move the selection in the command menu or in an open picker.
TabCompletes the highlighted command into the composer, appending a space when the command takes an argument.
EnterRuns the highlighted command, or sends the composer text. In a picker, commits the highlighted row. At an approval prompt, approves.
Shift+TabCycles the autonomy mode. It routes through /mode, so it inherits the same refusals, and it skips YOLO entirely when no scope is configured.
EscCloses the command menu if it is open; otherwise discards the draft and leaves the composer; otherwise goes back a screen. In a picker it closes the picker; at an approval prompt it rejects.
Ctrl+CExits, from anywhere — including modals and approval prompts.

Typing while a turn is running does not block. A plain message is parked (up to 50) and delivered in order, one per idle transition, once the turn ends. Slash commands are never queued — they run against the console immediately, and the handlers that cannot safely act mid-turn (/mode, /model, /resume, /explain) say so instead.

The mode governs which gates prompt you. It can be set at launch with --autonomy, changed live with /mode, and cycled with Shift+Tab.

ModeWhat it gates
Standard (default)Tools run automatically. A network-capable call whose destination is outside the current scope — or whose destination cannot be read at all, e.g. curl "$H" or a piped | sh — triggers a scope prompt. A filesystem-scoped tool reaching outside the approved subtree triggers a local-directory prompt. No per-tool prompts.
Co-pilotEverything Standard does, plus an approval prompt before every non-read-only tool call. Read-only tools (read_file, search_files, list_files, query_findings, the intel_* lookups, payload_lookup, list_skills, load_skill, done) are exempt.
YOLONo prompts inside an already-configured scope. It is not “no rules”: it requires a non-empty preconfigured scope, and anything outside it is a hard denial rather than a prompt. A destination the gate cannot resolve is denied on the same principle. Scope is never silently extended.

Two consequences worth knowing before you reach for YOLO. It refuses to engage without a scope — the console blocks /mode yolo, and the engine enforces the same floor for any session built directly against the API. And because the gate cannot prove a shell command is local, run_command in YOLO without a scope is denied outright; the fix is to configure a scope, or use Standard.

YOLO also lifts the scoped-source-audit allow-list without prompting. It does not lift the network scope check, the local-filesystem scope check, or the per-handler guards inside each tool.

0sec does not sandbox tool execution. The gates below are approval gates, not containment.

Four prompts can interrupt a turn. Each is answered with Enter (approve) or Esc (reject), and each grant is in-memory and session-scoped — none of them is written to a scope file or to disk.

PromptTriggerWhat approving grants
Authorize session scopeA network-capable tool references a URL outside the current scope, or a shell construct whose destination cannot be resolved.The exact hostnames from the requested URLs are added to the in-memory scope for this session. Existing deny rules still win, and the extension is rejected outright if the resulting policy would not actually cover the request.
Authorize local directoryread_file, list_files, search_files, apply_patch, run_command or analyze_binary touches a path no approved local scope covers.That directory subtree only, for this session. The path shown is already absolute and symlink-resolved, and the engine re-canonicalises it on apply, so a symlink swapped between the prompt and the apply cannot widen the grant. Filesystem root and your home directory are refused outright — never even offered.
Co-pilot approvalAny non-read-only tool call while in Co-pilot.That one call. The next call prompts again.
Enable additional toolDuring a scoped source audit (role audit/review with a local scope), the model calls a tool outside the source-audit allow-list.That one tool name, for the rest of the session. It lifts only the allow-list; network scope, local scope and the Co-pilot gate all still apply to it.

Rejections are remembered. A declined host, a declined shell payload, a declined directory (or any path beneath it) and a declined tool are denied without re-prompting for the rest of the session, so a retrying model cannot turn a “no” into a prompt loop.

Console transcripts are stored one JSON file per session under ~/.0sec/console-sessions/, 0600 inside a 0700 directory, re-applied on every write. Nothing is transmitted anywhere.

The file holds the session’s entire message array — every prompt, every model reply, and every tool call with its full result. On a security tool that means target hostnames, approved scope, untriaged findings, raw requests and responses including any cookies or bearer tokens seen on the wire, local file contents and command output. It is stored faithfully and deliberately not scrubbed, because a partial scrub over free-form tool output would advertise a guarantee it cannot keep. Treat these files as engagement evidence. Deleting them is supported, and the store keeps only the 20 most recent by default.

/resume lists the saved transcripts whose recorded working directory matches the current one, newest first, showing the first operator prompt, the message count, the model and the save time. Picking one rebuilds the session around the stored messages and the stored model. The on-screen transcript starts empty and the turn counter resets to zero; the model still has the full history.

Current limitation. The save is wired into the turn’s error path only, so a transcript is written when a turn throws — not after a turn that completes normally. In practice /resume will only offer sessions that hit an exception. The surrounding code and the /resume empty-state message both describe save-after-every-turn, which is the intent, not today’s behaviour.

/settings toggles chrome; values persist to ~/.0sec/tui-settings.json. A hand-edited or corrupt file degrades to defaults rather than failing the session.

KeyDescriptionDefault
showStatusBarBottom bar with model, working directory, git state and token counterstrue
showComposerHintsKeyboard-hint line under the input boxtrue
showLogoBlock “0SEC” mark on an empty transcripttrue
showRuntimeNoticesSurface runtime stdout/stderr as transcript noticestrue
showTurnSummaryPer-turn “N tool calls · in→out tok” linetrue
showSubagentsList active subagents while workers runtrue
showTimestampsRelative timestamps on transcript entriesfalse
densitycomfortable (blank line between entries) or compactcomfortable
composerStyleborder, rail, or plainborder

Resume a persisted review or audit scan by its scan ID.

Terminal window
0sec resume <scan-id>

Useful when a long-running deep scan was interrupted or when you want to continue where a previous run left off.

This is unrelated to the console’s /resume, which restores a saved chat transcript rather than a scan.

Open the local verification workbench for board-based triage, evidence review, and scan provenance.

Terminal window
0sec dashboard
0sec dashboard --port 48123

The dashboard provides a Kanban-style board for triaging findings, reviewing evidence, and tracking active scans. It runs entirely locally.

Key flags:

FlagDescriptionDefault
--port <port>Port to bind48123
--host <host>Host to bind127.0.0.1
--no-openDo not auto-open a browser(opens by default)
--db-path <path>Path to SQLite database~/.0sec/0sec.db

Browse past scans with status, depth, findings count, and duration.

Terminal window
0sec history
0sec history --limit 20
FlagDescriptionDefault
--limit <n>Number of scans to show10

Export a scan’s immutable pipeline-event audit trail as a chronological, technique-mapped forensic record. Built for handing to a client’s security team to cross-reference against their own detections.

Terminal window
0sec timeline <scanId>
0sec timeline <scanId> --format json
0sec timeline <scanId> --format csv
0sec timeline <scanId> --attack-only
0sec timeline <scanId> --since 2026-09-15T09:00:00Z --until 2026-09-15T17:00:00Z
FlagDescriptionDefault
--format <format>json, csv, or markdownmarkdown
--since <iso>Only events at or after this ISO-8601 timestamp
--until <iso>Only events at or before this ISO-8601 timestamp
--attack-onlyOnly events carrying a technique mappingfalse
--db-path <path>Path to the SQLite databasedefault location

Timestamps are UTC ISO-8601. Rows carry MITRE ATT&CK and MITRE ATLAS techniques as separate fields. See Authorized Engagements for the full picture.

Read-only Microsoft Entra ID tenant posture assessment — 53 checks across privileged roles, conditional access, app registrations, service principals, federation, and token analysis. Every Graph request is hard-coded GET.

Terminal window
# Access token comes from the environment, never a command-line argument
export 0SEC_ENTRA_ACCESS_TOKEN=...
0sec identity --tenant <tenant-guid>
0sec identity --tenant <tenant-guid> --json

Offline Active Directory attack-path analysis over a BloodHound CE / SharpHound JSON export. Never collects, never authenticates, never touches the network.

Terminal window
0sec adgraph --input ./bloodhound-export/
0sec adgraph --input ./export.json --json
0sec adgraph --input ./export --domain corp.example.com
FlagDescriptionDefault
--input <path>A BloodHound JSON file, or a directory of themrequired
--jsonEmit machine-readable JSONfalse
--domain <fqdn>Restrict analysis to one AD domain
--timeout <ms>Wall-clock bound on ingest + analysis120000

Covers paths to Domain Admin, kerberoastable principals, unconstrained delegation, DCSync rights, ACL abuse chains, and ADCS escalation (ESC1, ESC3–ESC7, ESC9, ESC10, ESC13).

The Entra ID equivalent — offline attack-path analysis over an AzureHound export. Same discipline: files only, no network, no authentication.

Terminal window
0sec entragraph --input ./azurehound-export/
0sec entragraph --input ./export --json
0sec entragraph --input ./export --owned <objectId>,<objectId>
0sec entragraph --input ./export --max-depth 4
FlagDescriptionDefault
--input <path>An AzureHound JSON file, or a directory of themrequired
--jsonEmit machine-readable JSONfalse
--owned <ids>Comma-separated object ids already under operator control; these become path sources
--max-depth <n>Hop ceiling for traversalanalyzer default
--timeout <ms>Wall-clock bound on ingest + analysis120000

Covers paths to Global Administrator, service-principal escalation via added secrets, consent-grant escalation, owner-chain abuse, and guest escalation.

An export missing membership or ownership collections cannot produce paths that depend on them; entragraph says so explicitly rather than reporting an empty result as a clean tenant. See Authorized Engagements.

Query, filter, and inspect verified findings. Fresh scans keep local findings in ~/.0sec/runs/<scan-id>/state.db; 0sec findings list aggregates local run databases, while --scan <scan-id> or --db-path <path> selects one run for detailed inspection and triage. Managed findings are queried through the managed control plane, not this local store.

Terminal window
# List all findings
0sec findings list
# Filter by severity
0sec findings list --severity critical
# Filter by category and status
0sec findings list --category prompt-injection --status confirmed
# Inspect a specific finding with full evidence
0sec findings show NF-001
# Triage findings
0sec findings accept <finding-id> --note "confirmed and tracked"
0sec findings suppress <finding-id> --note "known test fixture"
0sec findings reopen <finding-id>

Finding lifecycle: discovered -> verified -> confirmed -> scored -> reported (or false-positive if verification fails).

Subcommands:

SubcommandDescription
listList findings with optional filters
show <id>Show a finding with full evidence
accept <id>Accept a finding as confirmed
suppress <id>Suppress a finding (known FP or accepted risk)
reopen <id>Reopen a previously suppressed finding

Replay structured PoC steps or a built-in deterministic fixture and emit a verification_result JSON payload. The final assertion phase does not require an LLM. See Verification Results for the stable result schema.

Terminal window
# Replay PoC steps from a finding JSON
0sec verify --finding finding.json
# Run the deterministic CLI path traversal fixture against the CLI under test
0sec verify --fixture cli-path-traversal \
--fixture-command '["paperclip","company","export","--api","{{apiUrl}}","--output","{{exportDir}}"]'
# Keep the sandbox, harness metadata, and stdout/stderr logs
0sec verify --fixture cli-path-traversal \
--fixture-command '["paperclip","company","export","--api","{{apiUrl}}","--output","{{exportDir}}"]' \
--retain-artifacts

The cli-path-traversal fixture starts a malicious local API and runs the caller-supplied CLI command against a temp export directory. The harness does not implement export behavior itself; it only supplies {{apiUrl}}, {{exportDir}}, records stdout/stderr, and checks that a marker file escapes the selected export root while staying inside the sandbox.

FlagDescriptionDefault
--finding <path>Finding JSON with pocSteps to replay
--target <path>Optional PocExecutionTarget JSON for PoC steps
--fixture <name>Built-in deterministic fixture. Supported: cli-path-traversal; this fixture requires --fixture-command
--fixture-command <json>JSON argv array for the CLI under test. Required when --fixture=cli-path-traversal. Supports {{apiUrl}}, {{exportDir}}, and {{fixtureMode}} placeholders
--fixture-mode <mode>Fixture behavior: vulnerable or patchedvulnerable
--retain-artifactsKeep the fixture sandbox and log filesfalse
--artifact-dir <path>Use a specific fixture sandbox root
--output <path>Write JSON to a file instead of stdout

Read-only HackerOne hacker-API helpers — verify credentials, browse programs, and export a program’s scope into the 0sec scope-file format.

Credentials live at ~/.0sec/h1.env (or ~/.0sec/h1/<identifier>.env) with format H1_IDENTIFIER=<token-name> and H1_TOKEN=<44-char-value>. The token is used as the password and the identifier as the username over HTTP Basic auth; nothing is ever written to logs.

Terminal window
# Verify credentials
0sec h1 auth
# List visible programs (bounty-paying only)
0sec h1 programs list --bounty --limit 50
# List public-mode VDP programs as JSON
0sec h1 programs list --vdp --state public_mode --json
# Show one program with scope summary
0sec h1 programs show flutteruki
# Export structured_scopes to ~/.0sec/scopes/<handle>.json
# (consumed by `0sec scan --scope <path>`)
0sec h1 scope dump flutteruki

Subcommands:

SubcommandDescription
authVerify HackerOne API credentials against /v1/hackers/payments/balance
programs listList visible programs. Flags: --bounty, --vdp (mutually exclusive), --state <s>, --limit <n> (max 1000), --json
programs show <handle>Show a single program’s details with a structured-scope summary
scope dump <handle>Write the program’s structured_scopes to ~/.0sec/scopes/<handle>.json (override with --out); non-network asset types and malformed identifiers are dropped with a warning

Exit codes: 0 ok · 1 user/data error · 2 auth failure (missing creds or HTTP 401) · 3 rate-limit / network error.

Live vulnerability-intelligence lookup helpers for advisory-aware audits and variant-hunt context.

Terminal window
# Build a package intel dossier with risk summary, advisories, prior-vuln playbooks, variants, and graph
0sec intel dossier formidable --ecosystem npm --package-version 3.5.2 --json
# Search package advisories through OSV/GitHub, enriched with NVD/CISA KEV
0sec intel search formidable --ecosystem npm --package-version 3.5.2
# Look up a CVE with NVD + CISA KEV context
0sec intel cve CVE-2024-1086
# Find related CVEs/advisories for variant-hunt context
0sec intel similar --cwe CWE-22 --keywords "zip slip,path traversal" --json
# Search CVEs/GHSAs already reported against the same target/project
0sec intel target-history --repository expressjs/express --ecosystem npm --package express --json
# Infer target-history hints from a local source checkout
0sec intel target-history --repo-path ./my-project --json

Audit and review agents also get intel_build_dossier, intel_search_target_history, intel_search_advisories, intel_lookup_cve, and intel_search_similar tools. They should use these before citing CVEs/GHSAs from memory; intel results are leads unless backed by deterministic package/version evidence or local verification. Target-history and dossier results include prior-vulnerability playbooks plus an auditGraph that turns matching historical bug shapes into ordered source/sink/guard/verification steps and expected-evidence nodes. In source-review contexts, intel_search_target_history can infer repository/package/product hints from the scoped repo path before querying live advisory sources.

Subcommands:

SubcommandDescription
dossier <package>Build a package-level risk dossier with prior-vulnerability playbooks. Flags: --ecosystem <e>, --package-version <v>, --ver <v>, --keywords <csv>, --similar-limit <n>, --no-similar, --offline, --cache-dir <path>, --json
search <package>Search package advisories. Flags: --ecosystem <e>, --package-version <v>, --ver <v>, --no-enrich, --offline, --cache-dir <path>, --json
cve <cve-id>Look up one CVE through NVD and CISA KEV. Flags: --offline, --cache-dir <path>, --json
similarSearch related advisories by --cwe, --keywords <csv>, optional --ecosystem, --limit <n>, --offline, --cache-dir <path>, and --json
target-history [target]Search prior CVEs/GHSAs reported against a target. Infers package/repo/product hints from local metadata when --repo-path <path> is given (reads package.json, pyproject.toml, Cargo.toml, go.mod, .git/config). Explicit flags override inferred values. Flags: --repo-path <path>, --repository <owner/repo>, --ecosystem <e>, --package <pkg>, --product <p>, --vendor <v>, --keywords <csv>, --limit <n>, --offline, --cache-dir <path>, --json

0sec-cloud authentication — login, logout, and verify a scoped CLI token against the cloud /health endpoint.

Scaffold notice (issue #303): this command is the CLI half of cloud auth. The server-side mint endpoint that issues scoped tokens after the browser-based better-auth flow lives in 0sec-cloud and is shipped in a separate PR. Until that lands, the browser flow (0sec auth login without --token) will time out. Use 0sec auth login --token <value> to paste a token directly — this is the only working path for now.

Credentials live at ~/.0sec/cloud.env (chmod 600) with format:

0SEC_CLOUD_HOST=https://cloud.0sec.ai
0SEC_CLOUD_TOKEN=<scoped-cli-token>

0SEC_CLOUD_HOST is optional and defaults to https://cloud.0sec.ai. Both keys may also be set as environment variables (0SEC_CLOUD_HOST / 0SEC_CLOUD_TOKEN), which take precedence over the file.

Terminal window
# Paste a token directly (the only path that works today)
0sec auth login --token <value>
# Browser flow (will time out until #303 server-side ships)
0sec auth login --host https://cloud.0sec.ai
# Verify the configured token against /health
0sec auth status
# Delete ~/.0sec/cloud.env
0sec auth logout

Subcommands:

SubcommandDescription
loginOpen a browser at <host>/cli-auth?session=… and poll for a minted token. Flags: --host <url>, --token <value> (escape hatch — skips the browser).
logoutDelete ~/.0sec/cloud.env. Returns 0 even if no file was present.
statusLoad credentials and GET <host>/health to verify the token is accepted.

Exit codes: 0 ok · 1 user/data error · 2 auth failure (missing creds or HTTP 401/403) · 3 network error / login timeout.

The XBOW benchmark runner lives in packages/benchmark and is invoked with pnpm --filter @0sec/benchmark xbow. It runs 0sec against the 104 XBOW validation challenges and reports pass/fail with evidence.

Terminal window
# Run the whole benchmark
pnpm --filter @0sec/benchmark xbow
# Run a specific subset of challenges
pnpm --filter @0sec/benchmark xbow --only XBEN-010,XBEN-051,XBEN-066
# Skip the first 20 challenges (useful for resuming)
pnpm --filter @0sec/benchmark xbow --start 20
# Include full finding objects in results JSON (for offline analysis)
pnpm --filter @0sec/benchmark xbow --save-findings
FlagDescriptionDefault
--only <ids>Comma-separated challenge IDs to run(all 104)
--start <n>Skip the first n challenges0
--save-findingsInclude full finding objects in the results JSONfalse