--auth and --auth-file flags. This enables scanning behind login walls and detecting authorization bypass vulnerabilities (IDOR/BOLA).
The
--auth / --auth-file flags were previously named --session / --session-file, and a single bundle file holding multiple sessions used the separate --auth-config flag. The old names still work as deprecated aliases (--session → --auth, --session-file → --auth-file), and --auth-file now also accepts the multi-session sessions: bundle that used to require --auth-config. Update your commands to the new names..json) or by content sniffing (leading { or [).
Separate from configured sessions, the browser crawler can also try a short list of common default credentials (
admin:admin, …) against a confirmed local login form during spidering, so the crawl reaches authenticated areas without an --auth session. It’s off by default and auto-enabled at balanced/deep intensity, negative-control gated, and never a brute-force. See Default-credential login attempts.When
--spider runs, any session the browser establishes — cookies from a cleared WAF/bot challenge plus its User-Agent — is carried forward into the discovery and scanning phases (per host), so later probes reuse the cleared session. It’s on by default; disable with --no-carry-browser-session, and your own -H/--header overrides always win. See Session carry-forward.Quick Start
Authentication Flags
Both flags can be combined. If no session is explicitly marked as
primary, the first session loaded is used as the primary.
Session Roles
Each session has a role that determines how it is used during the scan:primary: The main session. Used for discovery, spidering, and as the default requester during the audit phase. There should be exactly one primary session.compare: Comparison sessions for IDOR/BOLA testing. During the audit phase, every request made by the primary session is replayed with each compare session’s credentials. If a compare session can access resources it shouldn’t, theauthz-comparemodule flags it.
Inline Sessions
The--auth flag accepts sessions in name:Header:value format:
Session Files
For sessions with multiple headers or login flows, use files. Both YAML and JSON formats are supported.Static Headers
YAML:session_dir (default ~/.vigolium/sessions/) if the path is not absolute. See Session Strategy Configuration below.
Login Flows
Session files can define automated login flows. The scanner executes the login request at scan start and extracts credentials from the response. YAML:Login Request Headers
Added in v0.5.3.login.headers adds request headers to every request the login sends — the single request, each step of a multi-step flow, or the OAuth2 token request. A step’s own headers are applied after the flow’s, so a step header wins on a clash. Values take {name} step variables and the templates below, exactly like url and body; a Host header sets the request’s Host.
Templates: environment variables and TOTP
Added in v0.5.3. Loginurl, body, header values and the OAuth2 fields accept function templates, evaluated every time the login runs — including an in-scan re-login — so a TOTP code is always current and a secret never has to live in the file.
Templates expand before
{name} step variables, so a value the server returned is never itself treated as a template.vigolium auth lint reports an unknown template function or malformed name as an error, and warns when {{totp:…}} holds what looks like a literal base32 secret rather than the name of a variable — the easy mistake. vigolium auth totp prints the code a template would produce, so you can check it against your authenticator before a scan depends on it.The older ${NAME} syntax still works; it is expanded once, when the file is loaded, which is why it cannot carry a rotating code.OAuth2 token endpoints
Added in v0.5.3.type: oauth2_client_credentials and type: oauth2_refresh_token log in against an OAuth2 token endpoint instead of a login form.
The access token is sent as
Authorization: <token_type> <access_token> (Bearer for a bearer token).
The token is refreshed before it expires, not after a 401. The response’s
expires_in becomes the session’s expiry, and during a native scan the token is renewed shortly ahead of it — a tenth of its lifetime, between 5 s and 60 s, at most half of it — without waiting for a rejection and without holding scan traffic, even when the session has no check block. A refresh token the server rotates replaces the configured one for the next refresh.auth load -j reports the expiry as expires_at. A token-endpoint error (invalid_client, invalid_grant, …) fails the login with that error. auth lint checks the required fields, the token_url scheme and auth_style, and warns about request-flow fields (url, method, body, extract, …) that an OAuth2 login ignores.Extraction Sources
The
apply_as field defines how the extracted value is applied as a request header. Use {value} as a placeholder. apply_as: "var:<name>" instead stores the value as a step variable for a later step to reference as {<name>}.
Multi-Session Bundle File
A bundle file defines all sessions in one place under asessions key, and is loaded with --auth-file (this is what the removed --auth-config flag used to do).
YAML Format
JSON Format
When to Use JSON
JSON is a good choice when:- AI agents generate session configs: most LLMs produce cleaner JSON than YAML, and agent modes (swarm, autopilot) already output session config as JSON natively.
- Programmatic generation: scripts, CI pipelines, or tools that build session configs are often simpler in JSON.
- Embedding in other JSON payloads: e.g., the REST API
POST /api/agent/run/swarmbody includes session config as a nested JSON object.
Format Detection
The format is detected automatically:- File extension:
.jsonfiles are parsed as JSON;.yaml/.ymlas YAML. - Content sniffing: if the extension is ambiguous (or missing), content starting with
{or[(after whitespace trimming) is parsed as JSON. - Fallback: everything else is parsed as YAML.
Session Config Schema Reference
Both YAML and JSON use the same field names. Here is the full schema:headers, login, or login_request can be set per session. check and reauth were added in v0.5.3; scanning_strategy.session.validate_url, reauth_on_status and reauth_interval fill check.url, check.logged_out.status and check.interval for every session that leaves them unset.
Logged-in check and in-scan re-login
check block is kept live for the whole scan (v0.5.3). This matters because a long scan routinely outlives its own session, and every request after that point tests the logged-out surface while reporting nothing wrong.
- Sampling. Every response received with the session’s credentials is matched against
logged_out:statusandredirect_regex(againstLocation) on all of them,body_regexon one insample_every(first 64 KiB). Cached responses are not fresh evidence and are not sampled. - Confirming. A match marks the session suspect and emits
auth.session_suspect. With acheck.url, one probe goes out with the current credentials — if it is still logged in, the session stays valid, which is the common case of a module that provoked a 401 on purpose. Without acheck.url, three matches within 10 s confirm the logout. - Re-login. The login flow runs again on a copy of the session, through the same login transport and the egress gate’s priority lane, so it never queues behind the scan’s own traffic. Up to
reauth.max_attempts, waitingbackoffafter the first failure and doubling it. Success publishes the new credentials as the next generation and emitsauth.reloginwithok: true. - One login per expiry. However many workers see the 401 at once, only the first confirms and re-logs-in. A response to an older generation’s credentials is never evidence against the new ones.
- Pausing. With
pause_traffic: true(the default) this session’s requests wait from the first logged-out match through the re-login — at most the 2-minute login budget — and leave with the new credentials. Only requests already in flight come back logged out. - Proactive probe.
check.intervalre-runs the probe at most that often even when nothing looked logged out. - Expiry. When the login reported when its credentials expire (an OAuth2
expires_in), the session is kept live even without acheckblock, and renews shortly before that time — no confirm probe, no paused traffic, since the old token is still good.
--require-auth (or spidering.require_auth, v0.5.2) makes a failed initial login fatal for that target, rather than silently scanning it anonymously. Credential-stripped requests — the authorization-differential modules’ anonymous replays — are never sampled, so their deliberate 401s cannot trigger a re-login. A header you set explicitly with -H is never taken over by a session.All login flows together are bounded by a 2-minute budget (v0.5.2), and login flows now honour --proxy and the scan’s TLS stance like every other request — they used to ignore both.Managing Sessions with the auth Command
The --auth/--auth-file flags load sessions for a single scan. The vigolium auth subcommand manages reusable, persisted sessions and provides helpers for validating configs and automating 2FA.
List stored sessions
Load sessions into the database
auth load persists sessions so subsequent scans pick them up automatically. It accepts a native config file, an agent-produced session-config.json, stdin, or even a raw HTTP login request (which it sends, then auto-discovers tokens from the JSON body, Set-Cookie, and auth headers):
load executes each login flow once to verify the credentials work; pass --no-validate to skip. Agent format is auto-detected when the path contains agent-sessions/ (or force it with --agent-format). The hostname is derived from the first login URL when --host is omitted. --force stores a session whose login failed anyway, and --timeout bounds the round-trip.
Lint a session config
Catch mistakes before a scan — missing/invalid fields, bad extract rules, unknown login or extract types, multiple primary sessions, or duplicate names:-j (one item per file, with each issue’s severity, line, column, message and rule; ok is false exactly when there are errors). auth load, auth lint and --auth-file share one session-file parser, so a file that lints clean is a file the scan can load.
Check that a session really authenticates
--proxy, the scan’s TLS stance, --timeout), then requests the URL twice through the scan’s HTTP stack — once with the session’s credentials and once without — following no redirects. The two responses decide the verdict:
The URL is
--url, else check.url, else validate_url; a path resolves against the login URL’s origin. It exits 0 only when every checked session is authenticated, otherwise 1 with error.code login_failed (the login itself did not work) or not_authenticated (any other verdict) — so it drops straight into CI ahead of the scan.
-j gives one item per session: session, url, method, verdict, authenticated, reason, signals (name, side, detail), similarity, auth_response and anon_response (status, length, location, error), and login.
The database has no columns for
check / reauth, so a stored session is checked with --url (or validate_url) and the heuristics alone.Generate a TOTP code for 2FA
For automating two-factor login flows,auth totp turns a base32 secret into the current code:
--secret-env, --secret-file and --secret - were added in the same release so the secret never appears in ps output or shell history. In a session file, prefer the {{totp:NAME}} template over shelling out at all — it re-derives the code on every re-login, which a value captured once cannot do.
Environment Variables
Session files (both YAML and JSON) support${VAR} syntax for secrets. This keeps credentials out of config files:
${VAR} references are expanded from the environment at load time, before format parsing.
IDOR/BOLA Testing
To test for authorization bypass vulnerabilities, define at least two sessions, one primary and one or more compare sessions. YAML:authz-compare module automatically activates when compare sessions are present. It replays primary session requests with compare session credentials and flags responses that indicate broken access control.
How Detection Works
- The primary session makes a request and gets a response (e.g.,
GET /api/users/42-> 200 OK with user data). - The same request is replayed with each compare session’s credentials.
- If a compare session also receives a successful response with similar content, the module reports a potential IDOR/BOLA finding with High severity.
Filtering to Auth Modules Only
To run only authorization testing without other active modules:How Sessions Affect Scan Phases
Session Strategy Configuration
Session behavior is configured underscanning_strategy.session in vigolium-configs.yaml (see public/vigolium-configs.example.yaml for the full annotated example).
Field Reference
Session Directory Resolution
When--auth-file receives a bare name (no path separators), the scanner resolves it from session_dir. Extensions are tried in order: .yaml, .yml, .json.
.yaml is appended as the default. Absolute paths and relative paths with directory separators (e.g. ./sessions/myapp.json) bypass session_dir and are used as-is.
To change the lookup directory:
Common Patterns
Unauthenticated discovery, authenticated scanning:authz-compare module stays inactive.
Long-running scan with token refresh:
validate_url confirms credentials work after each login before resuming scanning.
Team shared sessions directory:
--auth-file staging-admin resolves the same file for everyone.
Scanning profiles (~/.vigolium/profiles/) can also override session strategy values, useful for having a “quick unauthenticated” profile alongside a “deep authenticated” profile.
Using Session Config with Agent Modes
Agent modes (swarm, autopilot) can auto-generate session configs from source code analysis. The generated configs are always written as JSON to the session directory.
When running agent swarm with --source, the source-analysis phase discovers authentication flows in the codebase and produces a session-config.json and auth-config.yaml in the session directory. This config is then fed into subsequent scan phases automatically.
Since v0.5.3 both agent swarm and agent autopilot take --auth-file, so a session bundle you already lint, check and version-control drives an agentic run exactly as it drives a native scan — no prompt engineering, no credentials in a transcript.
Swarm additionally accepts a pre-built bundle via its own --auth-config flag (it skips browser/CLI auth synthesis and uses the file verbatim). You can still put credentials, roles, login URL and browser requirements in --prompt (or the positional prompt) for either command; browser tooling is always available and the intent parser extracts the auth signals:
credentials, credential_sets, auth_required, requires_browser, browser_start_url, and focus_routes fields. Their removal applies to the autopilot/swarm CLI flags only.
