Table of Contents
- Overview
- Setup
- Extension Types
- Writing a JavaScript Extension
- Writing a YAML Extension
- Quick Checks
- Snippets
- Context Objects Reference
- API Reference
- Testing Your Extension
- Configuration Reference
- Tips and Best Practices
Overview
Extensions plug into the scanner pipeline at four points:
All four types are supported in JS, YAML, and (for active/passive) as quick checks or snippets. YAML is simpler for straightforward pattern matching. JS gives you full access to HTTP requests, regex, encoding utilities, the database API, OAST (out-of-band) testing, and optional AI-augmented analysis. Quick checks and snippets are even lighter, ideal for agent-generated or ad-hoc checks.
Setup
1. Enable extensions in your config
Add or uncomment theextensions block under dynamic-assessment in your vigolium-configs.yaml:
2. Place your extension file
Drop any.js or .vgm.yaml file into your extension_dir. Vigolium discovers them automatically on the next scan.
3. Verify it loaded
Extension Types
Module export contract (JS)
Every JS extension must export amodule.exports object. Required fields:
Writing a JavaScript Extension
JS extensions run inside an embedded Sobek (ES2015+) VM. The globalvigolium object provides all APIs.
Active Module (JS)
Active modules send modified requests to probe for vulnerabilities. Declare which scan granularity you need inscanTypes:
per_insertion_point: called once per parameter (query, body, header, cookie)per_request: called once per request/response pairper_host: called once per unique hostname
null if nothing found.
Each finding object:
Passive Module (JS)
Passive modules analyze existing request/response pairs without making new requests. Add ascope field to limit to "request", "response", or "both" (default).
Pre-Hook (JS)
Pre-hooks run before each request is sent to a module. Return the modified request, a headers-only patch, ornull to skip the request entirely.
Skip static assets example:
Post-Hook (JS)
Post-hooks receive each emitted finding. Return the (possibly modified) result, ornull to suppress the finding.
Writing a YAML Extension
YAML extensions (.vgm.yaml) are a declarative alternative for common patterns. They require no programming knowledge and are compiled to the same internal module interface as JS extensions.
Active Module (YAML)
Userules to define match-then-emit pairs. Each rule specifies a match condition and the finding to emit when it matches.
Use
rules when different patterns should emit different findings. Use matchers + finding when all conditions must be true together.
Matcher types:
Passive Module (YAML)
Passive YAML modules use the samerules structure but do not send new requests:
rules[].match:
Pre-Hook (YAML)
Pre-hooks in YAML support header injection, extension skipping, and conditional skipping. Inject headers:
Template functions available in header values:
Post-Hook (YAML)
Post-hooks in YAML can escalate severity or drop findings based on URL patterns. Escalate severity for critical paths:Quick Checks
Quick checks are the lightest extension format, declarative JSON objects that define “send payload, check response” patterns with zero JavaScript. They’re ideal for agent-generated checks and rapid iteration.Per Insertion Point
Inject payloads into each parameter and check the response:Per Request / Per Host
Send specific requests and check responses:Match Fields
Match conditions use OR logic:Rules
idmust be lowercase with hyphens (e.g."ssti-jinja2")scanis one of:per_insertion_point,per_request,per_hostseverityis one of:critical,high,medium,low,info- Quick checks are automatically wrapped into full extension modules at runtime
Snippets
Snippets are a middle ground between quick checks and full extensions, you write just the function body (no boilerplate), and it gets wrapped in a module scaffold automatically. Use snippets when you need custom logic orvigolium.* API access.
Format
Available Variables
Inside the snippet body, you have access to:Rules
idmust be lowercase with hyphensscanis one of:per_insertion_point,per_request,per_hostbodycontains the function body as a string (newlines escaped as\n)- The return value follows the same convention as full extensions: array of findings or
null
Context Objects Reference
ctx: passed to all active/passive module functions
insertion: second arg to scanPerInsertionPoint
ctx.record: current HTTP record context
API Reference
vigolium.log
vigolium.utils
Encoding:
Hashing:
Random:
Regex:
File I/O:
URL utilities:
Parameter utilities:
Diff and similarity:
HTML:
Token extraction:
JWT:
Multipart:
Anomaly detection:
Other:
vigolium.parse
vigolium.http
Basic requests:
Sessions:
Session objects expose:
get(), post(), request(), send(), setHeader(), removeHeader(), getHeaders(), getCookies(), setCookie(), cloneAs(), onRequest(), onResponse(), setAutoRefresh().
Batch and replay:
Multi-step workflows:
Auth testing:
Retry and caching:
GraphQL:
vigolium.scan
vigolium.ingest
vigolium.source
vigolium.agent (AI-augmented)
vigolium.oast (Out-of-Band Testing)
vigolium.db
Records:
Findings:
Comparison:
vigolium.payloads(type)
Returns built-in payload wordlists by vulnerability type. Types:"xss", "sqli", "ssti", "ssrf", "lfi", "path_traversal", "xxe", "cmdi", "open_redirect", "crlf".
vigolium.config
Read-only config values from thevariables block in vigolium-configs.yaml:
Testing Your Extension
Run only the extension phase
The fastest way to test your extension against already-ingested traffic without running a full scan:Test against a live target
To ingest fresh traffic and immediately run only extensions:Use a one-off config with a custom extension path
You don’t need to copy files to~/.vigolium/extensions/. Use custom_dir to point directly at your file:
my-test-config.yaml:
Verify your extension loads
Before running a scan, check your extension is discovered and parsed correctly:Browse the built-in API reference
Install preset examples to learn from
Configuration Reference
Fullextensions block options in vigolium-configs.yaml:
Tips and Best Practices
Returnnull, not []: returning an empty array is treated the same as null, but null is the conventional no-finding signal.
Check for nil before accessing properties:
vigolium.utils.randomString for canaries to avoid collisions between concurrent extension invocations.
Keep pre-hooks fast: they run on every request before any module sees it. Avoid HTTP calls inside pre-hooks.
YAML vs JS vs quick check decision guide:
- Use quick checks when you need simple payload-and-match patterns with no logic
- Use snippets when you need
vigolium.*API access but don’t want full boilerplate - Use YAML when you need regex/header/status matching with a fixed finding output
- Use JS when you need: conditional logic, multiple HTTP requests, encoding/decoding, database lookups, session management, or AI-augmented analysis
scope: "response" if you only need response data. This avoids unnecessary invocations.
Use vigolium.config.* for secrets and environment-specific values instead of hardcoding them:
--only extension and a small known dataset so your module’s console.log output is easy to read.