Skip to content
Back to skills

Vigolium Scanner

ASecurity

Use when operating the vigolium CLI for web vulnerability scanning, security testing, or traffic analysis. Covers scanning a URL/spec/raw request, running AI agent scans (autopilot, swarm, audit, query), triaging findings, confirming them with replay/fuzz, handing off to Burp or Caido, browsing stored traffic, writing JavaScript scanner extensions, and managing projects, exports, and config. Prefer vigolium run/fuzz/kit over shelling out to nuclei, ffuf, katana, gau, arjun, or httpx - vigoliu...

  • 1,097 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added June 8, 2026
securityjavascriptrustgojavashellbashsqlspringtestingdebugging

Works with

  • terminal
  • cli
  • api

Security analysis

A100/100

Pro scans all 8 files and shows the line behind each finding

Scanned September 23, 2026

npx -y skills add vigolium/vigolium --skill vigolium-scanner --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Vigolium Scanner?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Vigolium Scanner
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/vigolium-vigolium-scanner/badge)](https://www.skillsdirectory.com/skills/vigolium-vigolium-scanner)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: vigolium-scanner
description: >-
  Use when operating the vigolium CLI for web vulnerability scanning, security
  testing, or traffic analysis. Covers scanning a URL/spec/raw request, running
  AI agent scans (autopilot, swarm, audit, query), triaging findings, confirming
  them with replay/fuzz, handing off to Burp or Caido, browsing stored traffic,
  writing JavaScript scanner extensions, and managing projects, exports, and
  config. Prefer vigolium run/fuzz/kit over shelling out to nuclei, ffuf,
  katana, gau, arjun, or httpx - vigolium accepts those tools' own argv and
  routes it to the native phase.
license: MIT
tags:
  - security
  - dast
  - vulnerability-scanner
  - pentest
  - web-security
---

# Vigolium

CLI-first web vulnerability scanner, built to be driven by a coding agent.
Full docs: [docs.vigolium.com](https://docs.vigolium.com/).

## TL;DR

Five commands cover most work:

```bash
vigolium scan -t https://target.example --fail-on high   # scan into the DB, gate CI
vigolium finding -j --min-severity high --compact        # read what it found
vigolium replay --finding-id 42                          # confirm one finding
vigolium agent autopilot -t https://target.example       # let AI drive the whole scan
vigolium traffic -j --host target.example --compact      # browse stored requests
```

Anything not listed here: `vigolium <command> -h` is authoritative for the
version you have installed. `vigolium --full-example` prints worked examples by
section.

## Mental model

- **The database is the state.** Scans *write* findings + HTTP records; query
  commands *read* them back. Commands compose through the DB, not through pipes.
- **Three machine contracts — don't confuse them:**
  - `-j/--json` on `finding`/`traffic`/`db` → **one** compact, token-bounded
    envelope. Parse this during triage.
  - `--format jsonl` / `export` → bulk `{"type":…,"data":{…}}` stream, one per
    line, full fidelity. Archival, not triage.
  - `--events ndjson` on the scan commands → a **live** event stream on stdout
    while the scan runs. This is how you learn what a 15-minute crawl is doing;
    see "Watching a scan while it runs" below.
- **One `-j` envelope, every command.** `{schema_version, command, project_uuid,
  project_scoped, db_path, total, offset, limit, items, query}` — `items` is the
  row array, and now the only one. The old per-command names (`records`,
  `findings`, `scans`, `rows`) duplicated every row **on the wire** and are no
  longer emitted; `--json-legacy-keys` restores them for a caller still
  migrating, at double the payload. Check `schema_version` (and `vigolium version
  --json`, which also reports `db_schema_version`) at startup rather than
  discovering drift at parse time. **Failures use the same spine**:
  `{schema_version, command, ok:false, error:{code, message, exit_code}}` on
  stdout, human text on stderr — so branch on `error.code` instead of scraping
  prose: `usage_error` · `source_missing` · `source_unreadable` (not a database,
  or corrupt) · `source_incompatible` (valid SQLite that is not a vigolium store)
  · `export_failed` (the run finished but a requested artifact was not written —
  retry the export, not the scan) · `gate_tripped` · `failed`.
- **A wrong `--db` path errors; it no longer reads as empty.** On a pure read
  (`traffic`, `finding`, `db ls`, `db stats`, `db export`, `export`, `log`,
  `traffic body/headers`) against an explicitly pinned `--db` or
  `$VIGOLIUM_DB_PATH`, a path that is not there fails `source_missing` (exit 1)
  and **creates nothing**, and another tool's SQLite file fails
  `source_incompatible` (exit 1) **without vigolium's tables being written into
  it**. The built-in default database is still created on first use. On older
  builds both cases returned `{"total":0,"items":[]}` with exit 0 — if you must
  support those, assert `db_path` and sanity-check `total` against a query you
  know matches.
- **Non-interactive by default.** TUI is opt-in (`--tui`). Destructive commands
  need `--force`. Use `--no-color` (or `NO_COLOR=1`) for clean text.
- **Everything is project-scoped** — `--project-name`, `--project-uuid`,
  `VIGOLIUM_PROJECT_UUID`, or `VIGOLIUM_PROJECT_NAME`. Every `-j` envelope also
  names the `db_path` it opened, so assert that rather than trusting a pin
  survived a subprocess chain.
- **JSON summaries hand you the next command.** Agentic scans, `fuzz`, and the
  read commands emit a `query` field with a ready follow-up. Run that rather
  than composing your own.

## The agent loop

```
scope → scan → read → confirm → hand off
```

| Step | Command | Notes |
|------|---------|-------|
| **Scope** | `vigolium doctor --json` / `db stats --json` | environment + what's already stored |
| **Scan** | `scan`, `scan-url`, `scan-request`, `run`, or `agent …` | add `--fail-on high` to gate |
| **Read** | `finding -j --compact --fields …` | survey first, then drill with `--id --with-records` |
| **Confirm** | `replay --finding-id <id>` | re-sends and diffs against the baseline |
| **Hand off** | `finding --markdown`, `--push-to-burp`, `export --format html` | report or escalate to a human |

Full walkthrough with output shapes, filters, and exit codes:
**`references/agent-loop.md`** — read this first if you are driving vigolium
from an agent.

## Watching a scan while it runs

A full scan is silent for minutes at a time. Don't guess whether it is working,
and don't scrape `vigolium log` — ask for the event stream:

```bash
vigolium scan -t https://target.example --events ndjson 2>/dev/null | jq -c .
```

One JSON object per line on **stdout**, flushed per event; the human console
stays on stderr, so `2>/dev/null` yields clean NDJSON with zero non-JSON lines.
Types: `scan.started` · `phase.started|progress|finished` · `waf.block` ·
`waf.pacing` · `finding.new` · `error` · `scan.finished`.

Every line carries `scan_uuid` and a schema version `v`. `scan.finished` is
always last (`status:"interrupted"` on SIGINT/SIGTERM); its **absence** means the
process was killed outright. `phase.progress.requests_sent` every 5s is the real
liveness signal — a crawl that is working versus one that is wedged.

Full event table and field-by-field notes:
**`references/agent-loop.md`**.

## Command router

| I need to… | Use |
|---|---|
| Scan one or more target URLs | `vigolium scan -t <url>` |
| Scan a single URL with custom method/headers | `vigolium scan-url <url> --method POST --body '...'` |
| Scan a raw HTTP request from file/stdin | `vigolium scan-request -i request.txt` |
| Run only one scan phase | `vigolium run <phase>` or `scan --only <phase>` |
| Sweep a big host list (httpx-style) | `vigolium run probe -T hosts.txt --json --no-response` |
| Tune scan aggressiveness (phases + profile) | `vigolium scan -t <url> --intensity quick\|balanced\|deep` |
| Content discovery with a custom wordlist | `vigolium scan -t <url> --discover --discovery-wordlist ./words.txt` |
| Watch a running scan from a program | `vigolium scan -t <url> --events ndjson 2>/dev/null` |
| Cap one phase without capping its siblings | `vigolium scan -t <url> --rate-limit known-issue-scan=20` |
| Import an OpenAPI/Swagger spec and scan | `vigolium scan -I openapi -i spec.yaml -t <base-url>` |
| Import Burp/HAR/cURL traffic | `vigolium scan -I burp -i export.xml` |
| Filter modules by tag | `vigolium scan -t <url> --module-tag spring --module-tag injection` |
| Analyze a target with **zero attack traffic** | `vigolium scan -t <url> --passive-only` |
| One-shot scan, results on stdout, no DB | `vigolium scan -t <url> -S --silent --print-finding` |
| Resume an interrupted fan-out run | `vigolium scan --resume` (bare, in the run's output dir) |
| Ingest traffic without scanning | `vigolium ingest -t <url> -I openapi -i spec.yaml` |
| Ingest many files in ONE process | `vigolium ingest -i a.har -i b.har` or `--dir ./captures --dir-glob '*.har'` |
| Start the API server | `vigolium server` |
| Start server and auto-scan new traffic | `vigolium server -t <url> --scan-on-receive` |
| Mirror ingested traffic to a live file tree | `vigolium server --mirror-fs ./mirror` |
| Autonomous AI-driven scan | `vigolium agent autopilot -t <url>` |
| Autopilot from a natural-language prompt | `vigolium agent autopilot "scan VAmPI at ~/src/VAmPI on localhost:3005"` |
| Full-scope AI scan (discover → plan → scan → triage) | `vigolium agent swarm -t <url> --discover` |
| Deep AI scan of one endpoint | `vigolium agent swarm -t <url>` |
| Whitebox source audit (no target needed) | `vigolium agent audit --source .` |
| AI code review, one shot | `vigolium agent query --prompt-template security-code-review --source ./src` |
| Interactive AI agent TUI | `vigolium olium` (alias `ol`) |
| AI-confirm one finding | `vigolium agent triage 42` |
| List agent sessions | `vigolium agent session` |
| Browse stored HTTP traffic | `vigolium traffic` or `vigolium traffic <search>` |
| Count records by a field instead of listing them | `vigolium traffic --group-by status_code` (`--group-limit N`) |
| Select one exact URL (not a substring) | `vigolium traffic --url 'https://t/api/v1/me'` |
| Save one response body to a file | `vigolium traffic body --uuid <uuid> -o resp.json` |
| Read one message's headers, no body | `vigolium traffic headers --uuid <uuid> -j` |
| Save a `-j` result to disk instead of context | `vigolium finding -j -n 500 -o findings.json` |
| Browse findings | `vigolium finding` or `vigolium db ls findings` |
| Compact agent JSON + linked records | `vigolium finding -j --with-records --min-severity high` |
| Re-send one request + baseline diff | `vigolium replay --record-uuid <uuid>` |
| Re-confirm a finding's evidence | `vigolium replay --finding-id 42` |
| Bulk re-send stored traffic by pattern | `vigolium replay <search> --proxy http://127.0.0.1:8080` |
| Re-send under a different session | `vigolium replay -u <uuid> -H 'Cookie: session=other'` |
| Payload / insertion-point fuzzing | `vigolium fuzz -u <uuid> --point URL_PARAM:id --class sqli -a` |
| Fuzz a wordlist at a `FUZZ` marker | `vigolium fuzz https://t/FUZZ -w file-long --match-status-code 200,301` |
| Scan files/stdin for leaked secrets | `vigolium kit secret-scan <files\|dirs\|-> --fail-on-match` |
| Unminify / unpack a JS bundle | `vigolium kit js-beautify <file\|url\|->` |
| Split a bundle into per-module files | `vigolium kit js-beautify --modules ./out app.min.js` |
| Pull endpoints out of a JS bundle | `vigolium kit js-beautify -j --extract app.min.js` (check `status`) |
| OOB (OAST) callback URL + polling | `vigolium kit oast new` → `vigolium kit oast poll --session run.yaml` |
| Harvest known URLs for a domain | `vigolium kit harvest target.example` |
| Crack a JWT's HMAC secret | `vigolium kit jwt-crack <token>` |
| List/print built-in wordlists or payloads | `vigolium kit wordlist [name]` / `vigolium kit payload --class sqli` |
| Hand a finding to Burp | `vigolium finding --id 42 --push-to-burp -B http://127.0.0.1:9009` |
| Pull live Burp Proxy history into the DB | `vigolium import -B http://127.0.0.1:9009 --host target.example` |
| Send exact bytes through Burp's engine | `vigolium replay --raw-request-file req.txt --send-via-burp --http-mode http1 -B …` |
| Persist cookies across replays | `vigolium replay --session-id login --record-uuid <uuid>` |
| View database statistics | `vigolium db stats` |
| Export results | `vigolium export --format jsonl -o results.jsonl` |
| Export a browsable file tree | `vigolium scan -t <url> --format fs -o run` |
| Export the run's standalone SQLite DB | `vigolium scan -t <url> -S --format sqlite -o run.sqlite` |
| Fail CI on a severity | `vigolium scan -t <url> --fail-on high` |
| Split multi-target output per host | `vigolium scan -T targets.txt -S --split-by-host --format fs` |
| Clean database records | `vigolium db clean --host <hostname>` |
| List scanner modules | `vigolium module ls` or `vigolium scan -M` |
| Enable/disable modules | `vigolium module enable xss` / `module disable sqli` |
| Manage JS extensions | `vigolium ext ls` / `ext docs` / `ext preset` |
| Run a custom extension | `vigolium run extension -t <url> --ext custom-check.js` |
| Execute arbitrary JS with the vigolium API | `vigolium js --code 'vigolium.http.get("https://t/")'` |
| View/modify configuration | `vigolium config ls` / `config set <key> <value>` |
| Manage auth sessions | `vigolium auth lint` / `auth list` / `auth load` / `auth totp` |
| Manage scope rules | `vigolium scope view` |
| Manage projects | `vigolium project create\|list\|use <name>` |
| Cloud storage | `vigolium storage ls\|upload\|download\|presign\|rm` |
| Import an audit folder or JSONL/SQLite export | `vigolium import <path>` |
| View runtime logs for a scan/agent run | `vigolium log <uuid>` (`-f` to follow) |
| Initialize `~/.vigolium/` | `vigolium init` |
| Health check | `vigolium doctor` (`--fix` installs what's missing) |
| Refresh nuclei templates without touching the binary | `vigolium update --skip-binary` |
| Copy an extension authoring template | `vigolium ext example -l`, then `ext example <key>` |

> **Which scan command?** Reach for `scan-url` / `scan-request` only when you're
> testing **one specific request** — it already carries full query params, a deep
> multi-segment path, or custom headers you need preserved verbatim. Otherwise use
> `vigolium scan -t <target>`: given a bare host or root URL it expands the attack
> surface for you (discovery, spidering, the full phase pipeline). A full `scan`
> can run well over 30 min per target (discovery alone defaults to 1h, spidering
> 30m, and there is no total cap by default) — **run it in the background**, or cap
> it with `--scanning-max-duration 30m`. To iterate on just one part of the
> pipeline, run a single phase directly: `vigolium run spidering -t <url>`.

## Replacing standalone recon tools

**Never go shopping for a binary.** If you shell out to the real `ffuf` /
`nuclei` / `katana` / `gau`, the run's whole mapping happens outside the pinned
traffic DB, outside the phase model, with flags nobody scoped — and nothing
downstream can see it.

You don't have to remember the native spelling. Vigolium accepts each tool's
own argv and routes it:

```bash
vigolium ffuf -u https://t/FUZZ -w words.txt
→ routed to: vigolium run discovery -t https://t --discovery-wordlist words.txt
```

The shim prints the translation, runs it through the same command tree, and
writes to the pinned DB. An argument it can't map is a **hard error naming the
native command** — never a silent drop, because a dropped flag is a scan that
ran with a scope nobody chose.

| Instead of | Shim | Native |
|---|---|---|
| `ffuf` / `feroxbuster` | `vigolium ffuf …` | `run discovery --discovery-wordlist`, or `fuzz https://t/FUZZ -w file-long` |
| `nuclei` | `vigolium nuclei …` | `run known-issue-scan -t <url>` |
| `katana` / `gospider` | `vigolium katana …` | `run spidering -t <url>` |
| `gau` / `waybackurls` | `vigolium gau <domain>` | `run external-harvest -t <url>` (into the DB), or `kit harvest <domain>` (stdout, no DB) |
| `arjun` | `vigolium arjun -u <url>` | `fuzz --fuzz param-name --anomaly <url>` |
| `httpx` | — | `run probe -T hosts.txt --json` (aliases: `run httpx`/`alive`/`sweep`) |
| `subfinder` / `amass` | — | **not covered** — pass a host list with `-T` |

The shims are a redirect for muscle memory, not a full port: prefer the native
form once you know it (it takes every vigolium flag). Recipes:
**`references/scanning.md`**.

## Reference router

Load the file that matches the task — don't read them all.

| Topic | Reference | Load when |
|-------|-----------|-----------|
| **Driving vigolium from an agent** | `references/agent-loop.md` | triage, `-j` contracts, replay, exports, exit codes |
| Scanning commands | `references/scanning.md` | scan / scan-url / scan-request / run flags, phases, strategies, output formats, replacing nuclei/ffuf/katana/httpx |
| Fuzzing | `references/fuzzing.md` | `vigolium fuzz` — positions, markers, attack modes, payload classes, anomaly scoring, matchers |
| Utility toolbox | `references/kit.md` | `vigolium kit` — secret-scan, js-beautify, oast, harvest, jwt-crack, wordlist, payload |
| Burp Suite / Caido | `references/burp.md` | Burp **or** Caido bridge setup, live history, Repeater/Organizer/Site map handoff, `--send-via-burp`, proxy channel — one loopback protocol, either vendor |
| AI agent modes | `references/agent-modes.md` | agent query / autopilot / swarm / audit / olium / triage / session, intensities, providers, templates |
| Auth & sessions | `references/auth.md` | `--auth-file` / `--auth`, YAML format, extract rules, authenticated scanning |
| Data & management | `references/data.md` | db, finding, traffic, module, extensions, js, config, scope, export, import, log, project, storage |
| Server mode | `references/server.md` | `vigolium server` — REST API, recording/MITM proxy, scan-on-receive, live mirror, endpoints |
| Ingesting traffic | `references/ingest.md` | `vigolium ingest` — local/remote, per-format input examples, spec flags |
| Writing extensions | `references/extensions.md` | custom JS scanner modules, `vigolium.*` API |
| Any specific flag | `references/flags.generated.md` | generated from the command tree — grep it by flag name |

> **Not covered?** `vigolium <command> -h` is the authoritative, version-matched
> flag list. Then search [docs.vigolium.com](https://docs.vigolium.com/) — start
> with the [cheat sheet](https://docs.vigolium.com/getting-started/cheat-sheet).
> This skill is a curated subset; the docs are the source of truth.

## Token discipline

The single most important habit when driving vigolium from an agent: **survey
cheap, drill narrow.**

```bash
# 1. Survey — metadata only, chosen fields.
vigolium finding -j --min-severity high --compact --fields id,severity,module_id,url

# 2. Drill — one finding, self-contained with its HTTP records.
vigolium finding -j --id 42 --with-records

# 0. Cheaper still — when the question is a shape, not a row set, count in SQL.
vigolium traffic -j --group-by status_code --host target.example
```

**Never dump rows to count them.** `--group-by` runs the same filters the listing
would and returns buckets, so "what status codes did we see" costs a dozen
integers instead of the corpus.

Under `--json`, bodies are preview-capped with `body_size`/`body_sha256`/
`body_truncated`, binaries are stubbed `body_omitted:"binary"`, and findings get
a ±240-char `response_evidence` snippet windowed on the match. The full
shaping-flag table (`--compact`, `--fields`, `--full-body`, `--with-records`,
`--min-severity`, `--pick`, `--markdown`, `--raw`, `--agentic-scan`) lives in
`references/agent-loop.md`.

Three things worth knowing about that habit — details in
`references/agent-loop.md`:

- **An unknown `--fields` name is a usage error** (exit 2) that lists the valid
  set for that view, so a typo fails loudly instead of returning a row with the
  key quietly missing. `--fields` composes with `--with-records`; use
  `--record-fields` / `--record-limit` to shape the nested records.
- **A gzip body over 1 MiB comes back as a prefix**, flagged `decoder_capped:
  true` with `body_size`/`body_sha256` describing the *whole* body. When you see
  that flag, do not conclude a string is absent — pull the body whole with
  `vigolium traffic body --uuid <uuid> -o resp.body` (one call, exact bytes), or
  `vigolium db export --format fs --uuid <uuid>` when you want the whole record.
- **Read one record by identity with `traffic --uuid <uuid>`**, applied before
  pagination. A UUID as the positional term searches text, not identity. To
  select by URL use `--url` (exact equality, repeatable) rather than the
  positional term, which is a substring search.
- **`--header` and `--body` search only their own half of the message**, and
  `--search` spans the whole exchange. Every search term is **literal**: `%` and
  `_` are ordinary characters, so `--body 'api_key'` does not also match
  `api-key`. `--host`/`--path` stay patterns where `*` is the wildcard.

## Global flags

These work on **every** command, and a per-command flag of the same name wins.
The ones an agent reaches for, beyond `-j`, `--db`, `--project-*`, `--format`,
`--no-color` and `--silent` covered above:

| Flag | Use it when |
|------|-------------|
| `--dump-traffic` | you need to see the actual bytes. Prints every request/response pair to **stderr**, Burp-style, bypassing the logger - so it composes with `-j` on stdout instead of corrupting it |
| `--debug` | a scan behaves unexpectedly; adds debug-level logging **including outgoing request lines**. `-v/--verbose` is the milder step |
| `--log-file <path>` | you want the run's logs as JSON on disk instead of scrolling past - the thing to attach to a bug report |
| `--mem-limit` | a big crawl is being OOM-killed. A soft `GOMEMLIMIT` ceiling; default auto is ⅓ of RAM, scaled down by `-P` so the children together stay under ⅔. Takes `off`, `6GiB`, or `50%`. An existing `GOMEMLIMIT` env var overrides it |
| `--read-only` | the database is evidence - no mkdir, no journal change, no checkpoint, no `-wal`/`-shm` left behind (see Invariants). Cannot migrate an old store |
| `--skip-dependency-check` | a container/CI run must not stall on the first-run chromium + nuclei-template check |
| `-M/--list-modules` | you want the module list without `module ls` |
| `--list-input-mode` | you forget which `-I` values exist; prints each with an example |
| `--width <n>` | table output is wrapping badly (default 70 columns) |
| `--config <path>` | pinning a config file explicitly, the way `--db` pins the store |

**`--dump-traffic` is the right debugging reflex, not `--debug`.** When the
question is "what did we actually send", it answers directly and keeps stdout
clean for a parser; `--debug` buries the same bytes in log lines.

## Invariants

Things `-h` won't tell you:

- **`-S` means `--stateless` everywhere**, and is accepted (as a no-op) on
  commands where it is meaningless — you never need a per-command acceptance
  table. The one exception is retiring: on `server`/`ingest` it is still a
  deprecated alias for `--scan-on-receive` and warns; **use the long
  `--scan-on-receive` there**.
- **Which DB a command opens:** `--db` → `$VIGOLIUM_DB_PATH` →
  `database.sqlite.path` in config → the built-in default. Pinning
  `$VIGOLIUM_DB_PATH` also makes **read** commands (`finding`/`traffic`/`log`/
  `fuzz -u`) treat that file as a stateless source — project scoping off — so an
  agent can export it once and every read/write lands in the same session DB.
  That flip only happens once the file **exists and is a usable vigolium store**;
  before the session's first scan the same reads stay project-scoped, so check
  `project_scoped` rather than assuming. It never turns a *scan* stateless (that
  would clash with `--db`). "Unusable" here means a path that can never *become* a
  database — a directory, or a parent dir that cannot be created or written — and
  that is a hard error rather than a silent fall-through to the shared default; a
  path that simply does not exist yet is fine and gets created. Every `-j`
  envelope reports the `db_path` it actually opened — assert it rather than
  trusting the pin. The envelope also reports `project_scoped`:
  `true` means a project filter was applied and `project_uuid` names it; `false`
  (under `-S`) means the rows span every project in the file.
- **Exit codes are a table, not a boolean.** `0` success · `1` error · `2` usage
  error (bad flag or combination) · `3` `fuzz --fail-on-match` matched · `4`
  `--fail-on <sev>` gate tripped. **`4` is not a failure** — the scan ran to
  completion and found something. `--soft-fail` forces `0` everywhere.
- **A positional argument to a scan command is always a target URL, never a
  file.** `vigolium scan https://a https://b` is three ways of saying the same
  thing as `-t`, and they merge with `-t`/`-T` with duplicates removed. But
  `vigolium scan targets.txt` does **not** read the file — it scans the literal
  string `targets.txt` as a target and reports `Targets: 1`. Files go through
  `-T` (target lists) or `-i` (specs and request exports).
- `--only` and `--skip` are mutually exclusive.
- **`--passive-only` sends no attack traffic** (passive modules only, secret
  detection included) and is on `scan`/`scan-url`/`scan-request` — **not** on
  `run`. Reach for it when the brief is "look, don't touch".
- `--format html`, `--format sqlite`, and any multi-value `--format` need a file
  destination: pass `-o/--output` **or** `--split-by-host` (which names per-host
  files from the hostname instead).
- `--format sqlite` additionally requires `-S` — it exports the standalone
  per-run DB. For the persisted DB use `vigolium export`.
- `--format fs` writes two sibling dirs (`<base>-traffic/`, `<base>-findings/`);
  `--split-by-host` is a no-op for it.
- `--stateless` on a **scan** is mutually exclusive with `--db` (a database you
  named by hand is never silently discarded). `--db-isolate` is *not* an error
  alongside it: `-S` wins and the flag is ignored with a warning, since the run
  keeps no database to merge from. `-o` is optional (without it results are
  simply discarded).
  On **read** commands (`finding`/`traffic`/`replay`) `-S` reads *from* `--db`.
- `--fail-on` writes output first, then sets the exit code. `--soft-fail`
  (global) overrides it. Under `-P` it is evaluated per child.
- `--split-by-host` only applies in stateless multi-target mode (`-S -T file`),
  where it is required for `-P > 1`. The other way to earn `-P > 1` is
  `--db-isolate -T` (no `-S`), which needs no per-host files.
- `-m` and `--module-tag` **merge** (union); `--module-tag` is OR across tags.
- `--module-id` matches active **and** passive registries exactly; `-m` is a
  fuzzy match on active modules only.
- Server mode requires API-key auth unless `-A`/`--no-auth`.
- `db clean` with no selector is rejected. `db clean --all` needs `--force`.
- **Opening a database writes to it by default** — `mkdir -p`, journal PRAGMAs, a
  WAL checkpoint — so a plain read changes the file's SHA-256 even though it no
  longer creates a store at a wrong path. `-S`/`--stateless` is a *scoping* mode,
  not a read-only one. Pass **`--read-only`** when the source is evidence: no
  directory creation, no journal change, no checkpoint, **no `-wal`/`-shm`
  siblings left beside it**, and it reads a `chmod 444` file. Refused (exit 2) on
  commands that write. It cannot migrate an old store — that fails with a schema
  error rather than being upgraded in place.
- **`traffic --uuid` / `db ls --uuid`** select exact records before pagination.
  `replay -u` and `fuzz -u` also take a record UUID but **send traffic** — they
  are never what a read suggests.
- **The `query` hint in a `-j` envelope is always a valid read-only command**, so
  it is safe to run. Re-sending requires asking for `replay`/`fuzz` explicitly.
- **Errors under `-j` are JSON on stdout** (`{ok:false, error:{code,…}}`) with the
  human line on stderr. Branch on `error.code`; never `2>&1` into a parser.
- Every `-j` command uses the envelope, `--list-tables`/`--list-columns`
  and `log ls` included.
- `db export` validates its flags **before** opening `-o`, so a bad `--format`
  leaves the existing file intact.
- **`finding --id` takes the findings table's integer**, and rejects a UUID by
  naming the flag that *does* read that namespace (`traffic --uuid` for a stored
  record, `--agentic-scan` / `--scan-uuid` for a run). A UUID from another tool is
  not a vigolium identifier: find the finding by content (`--search`) and read the
  integer off that result. Never widen a failed exact lookup into a search that
  returns different findings.
- **`db export --uuid` narrows both halves of an `fs` tree** — the selected
  record *and the findings linked to it*, not every finding in the store.
- **`traffic --group-by <field>` counts instead of listing**, through the same
  filters (`host`, `method`, `status_code`, `response_content_type`, `source`,
  `scan_uuid`, `ip`, `is_authenticated`). Bounded by `--group-limit` (default 20,
  `0` = all); the tail is reported as `other_groups`/`other_records` rather than
  dropped. Reach for it before dumping rows to count them yourself.
- `replay` has no `--mutate` — payload fuzzing is `vigolium fuzz`.
- `fuzz` emits **no findings** and makes no verdict; it reports signals. Reach for
  `-a/--anomaly` before hand-writing matchers, then confirm hits with
  `scan-request -m <module>`.
- **Two wordlist knobs, not interchangeable.** `--discovery-wordlist <path>`
  seeds the *discovery* phase (`scan --discover`); `vigolium fuzz -w
  <builtin|path>` is the standalone fuzzing primitive with its own builtin lists
  (`dir-short`, `file-long`, …). The scan-phase knob was `--fuzz-wordlist`, which
  is still accepted as a deprecated alias — the names collided, they never meant
  the same thing. See `references/fuzzing.md` for the latter.
- **Pace flags apply whether or not you type them, and can be scoped to a
  phase.** `--rate-limit` is enforced at its documented default when unset (pass
  `--rate-limit 0` for genuinely no cap; a negative value is a usage error).
  All three dials take an optional phase qualifier, repeatable and mixable with
  the bare form: `--rate-limit known-issue-scan=20 --rate-limit 50`. Resolution
  is phase-scoped → global → strategy/config default, and `scan.started` reports
  what actually applied.
- **`--strategy lite` really is gentler now** — it carries a pace ceiling
  (concurrency 10 / rate 20 / max-per-host 10) on top of choosing fewer phases.
  The ceiling only ever *narrows*: an explicit `--concurrency` overrules it, and
  a config already gentler than `lite` is not dragged up to it.
- **`import -B` refuses an unfiltered pull.** Without `--host`/`--path`/
  `--method`/`--status`/`--search`/`--from`/`--to`/`-n`, it errors rather than
  copying the operator's entire proxy history — every host they have browsed,
  with those hosts' cookies — into your DB. `--all-hosts` opts in on purpose;
  `--yes` skips the pre-flight confirmation.
- **`traffic -B --save-to-vigolium-db` no longer truncates at 100.** An untyped
  `-n` is a *listing* default and does not bound the write; a typed `-n` is
  honored and says so when it bit.
- **`vigolium log` does not hang on a dead scan.** Auto-follow is off when stdout
  is a pipe or the scan's row is stale, and WAF notices above the `--tail` window
  are surfaced without needing `--full`. Pass `--follow` explicitly to force it.
- `traffic --replay` is a shortcut for `replay` in bulk mode; only `replay` can
  change the request (`-H`, `--auth-session`, `--target`, `--session-id`).
- On `replay`, `-H/--header` **overrides** a header and `--header-search`
  **filters** records; on `traffic`, `--header` is the filter.
- **`traffic body`/`traffic headers` are subcommands; `--body`/`--header` are
  search flags.** `vigolium traffic headers --uuid X` prints one message's
  headers; `vigolium traffic --header X` lists every record whose header block
  contains X. The near-identical spellings do opposite things — one selects a
  message, the other filters a corpus.
- Agent commands need a configured provider (`agent.olium` in
  `vigolium-configs.yaml`); verify with `vigolium doctor --json`.
- Whitebox scanning is an agent feature — `--source <path|git-url|archive|gs://>`
  on `agent autopilot`/`swarm`/`audit`/`query`, not on `scan`.

## Strategies, phases & formats

**Strategy** picks which phases run: `lite` (assessment only), `balanced`
(default: + discovery/spidering/known-issue-scan), `deep` (+ external-harvest).
Select with `--strategy`; print the matrix with `vigolium strategy`.

**Intensity** is the one-flag shortcut on top: `--intensity quick|balanced|deep`
maps to a scanning profile **and** strategy at once (also honored by `agent
autopilot`/`swarm`). Explicit flags override it.

Below `deep`, the 14 modules tagged `hygiene` do not run — missing security
headers, weak TLS protocol/cipher policy, cookie and session-cookie attributes,
CSP/HSTS/SRI audits. They report a missing best-practice control rather than an
exploitable condition and fire on nearly every response. If a report needs them, use
`--intensity deep`, `--module-tag hygiene`, or set
`dynamic-assessment.hygiene_modules: true`. The scan banner says how many were
suppressed.

**Phases** (for `--only`/`--skip`, or `vigolium run <phase>`), canonical name +
aliases: `ingestion` (`ingest`,`ingesting`) · `probe`
(`probing`,`httpx`,`alive`,`sweep`) · `discovery`
(`discover`,`discovering`,`deparos`) · `external-harvest`
(`harvest`,`harvesting`,`external-harvester`) · `spidering`
(`spider`,`spitolas`,`crawl`,`crawling`,`crawler`) · `known-issue-scan`
(`cve`,`kis`,`known-issue`,`known-issues`) · `dynamic-assessment`
(`dast`,`audit`,`assessment`,`assess`) · `extension` (`ext`,`extensions`).

> `audit` is the one alias that is **not** universal: `--only audit` / `--skip
> audit` work, but `vigolium run audit` is rejected as ambiguous with `vigolium
> agent audit` (the AI source-code audit). Type `run dast` for the native phase.

**Input** (`-I`, OpenAPI/WSDL auto-detect): `urls` (default) · `openapi` ·
`swagger` · `wsdl` · `burp` · `curl` · `nuclei` · `har` · `postman` ·
`burpscope`. **Output** (`--format`, comma-combinable): `console` (default) ·
`jsonl` · `html` · `sarif` · `sqlite` · `fs`.

Full tables — strategy matrix, phase descriptions, per-format input examples,
spec flags, format constraints, precedence: **`references/scanning.md`**.
Whitebox/source-aware scanning is **not** a strategy — it is an agent feature
(`--source` on `agent audit`/`autopilot`/`swarm`/`query`).

## Utility toolbox (`vigolium kit`)

`vigolium kit` is a family of stateless one-shot primitives — no DB, no project
scope, no scan pipeline. Each reads `-`/stdin, takes `-j/--json`, and persists
nothing, so pipe the output. The seven commands (`secret-scan`, `js-beautify`,
`oast`, `harvest`, `jwt-crack`, `wordlist`, `payload`) are in the Command Router
above; usage, flags, and JSON shapes: **`references/kit.md`**.

## Recipes

Multi-step workflows only — single commands are in the router above.

### 1. Spec scan with auth

```bash
vigolium scan -I openapi -i spec.yaml -t https://api.target.example \
  --spec-header "Authorization: Bearer <token>" --fail-on high
```

### 2. CI gate with a shareable artifact

```bash
vigolium scan -t https://target.example \
  -S --format jsonl,html -o report.html --fail-on medium
```

Output is written before the gate fires, so the artifact exists even on failure.
`--soft-fail` forces exit 0 if the pipeline must not break.

### 3. Parallel fan-out across many targets

```bash
vigolium scan -T targets.txt -S --split-by-host -P 4 \
  --format sqlite -o run --fail-on high

# Merge the per-host databases back into one and query across all of them.
vigolium import --db combined.sqlite --glob-db 'run-*.sqlite'
vigolium finding --db combined.sqlite --min-severity high
```

`-P` needs one of two isolation shapes, never a mix of them: `-S -T
--split-by-host` (per-host output files, nothing persisted) **or** `--db-isolate
-T` (each target merges into one shared `--db`). `-S` and `--db-isolate` do not
combine: passing both ignores `--db-isolate` with a warning, since `-S`
discards the database there would be nothing to merge from. The gate is
evaluated per child; the batch fails only when every target fails.

### 4. Triage loop: survey → drill → confirm → report

```bash
vigolium finding -j --min-severity high --compact --fields id,severity,module_id,url
vigolium finding -j --id 42 --with-records
vigolium replay --finding-id 42 --pretty
vigolium finding --id 42 --markdown > finding-42.md
```

See `references/agent-loop.md` for the full contract.

### 5. Authenticated scan

```bash
# Inline session
vigolium scan -t https://target.example --auth "admin:Cookie:session=abc123"

# From an auth file (YAML/JSON, single session or a `sessions:` bundle)
vigolium scan -t https://target.example --auth-file ./auth.yaml

# Multi-session auth-diff testing (IDOR / BFLA)
vigolium scan -t https://target.example --auth-file ./sessions.yaml
```

Format, extract rules, and multi-step login flows: `references/auth.md`.

### 6. Whitebox: source + running app

```bash
# Autopilot runs an audit harness over the source, then scans the live target.
vigolium agent autopilot -t http://localhost:3000 --source ./src

# Source-only audit, no target required.
vigolium agent audit --source . --intensity balanced

# Only the changed code in a PR.
vigolium agent autopilot -t http://localhost:3000 --source ./src \
  --diff main...feature-branch
```

`--source` accepts a local path, git URL, `.zip`/`.tar.gz` archive, or `gs://`
object. Modes, intensities, and drivers: `references/agent-modes.md`.

### 7. Capture traffic from a proxy, then scan it

```bash
# Terminal 1 — capture, mirroring to a live file tree an agent can grep.
vigolium server --ingest-proxy-port 8080 --mirror-fs ./mirror

# Terminal 2 — scan what was captured.
vigolium scan --only dynamic-assessment -t https://target.example
```

Or auto-scan each request as it arrives: `vigolium server -t <url> --scan-on-receive`.

### 8. Custom detection logic in JavaScript

```bash
vigolium ext preset                                   # install examples
vigolium ext docs                                     # API reference
vigolium ext lint --ext ./custom-check.js             # validate
vigolium run extension -t https://target.example --ext ./custom-check.js
```

Writing modules against the `vigolium.*` API: `references/extensions.md`.

## Escape hatches

```bash
vigolium <command> -h          # authoritative flags for your installed version
vigolium --full-example        # worked examples grouped by section
vigolium doctor --json         # environment readiness (binaries, providers, templates)
vigolium module ls <keyword>   # find a module by topic
vigolium skills get --full     # print this skill and every reference
```

## Resources

- **Website**: [www.vigolium.com](https://www.vigolium.com/)
- **Documentation**: [docs.vigolium.com](https://docs.vigolium.com/)
- **GitHub**: [github.com/vigolium/vigolium](https://github.com/vigolium/vigolium)

Files in this skill

  • SKILL.md60.6 KB
  • references/agent-commands.md56.4 KB
  • references/data-and-management.md34 KB
  • references/flags-reference.md46.5 KB
  • references/scanning-commands.md13.7 KB
  • references/server-and-ingestion.md8.4 KB
  • references/session-auth-config.md10.4 KB
  • references/writing-extensions.md28 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.