Skip to main content
Vigolium is designed for extensibility. Whether you need to add a new vulnerability check, reshape scan behavior, or integrate AI-driven analysis, there are multiple extension points — each with different trade-offs. This guide covers every customization mechanism, explains when to use each one, and helps you pick the right approach for your use case.

Table of Contents


Extension Points at a Glance

Extension PointLanguageRecompile?Best For
JavaScript ExtensionsJavaScriptNoCustom active/passive checks with full API access
YAML ExtensionsYAMLNoDeclarative pattern matching, simple payload/matcher rules
Go ModulesGoYesHigh-performance checks, deep integration with internals
Prompt TemplatesMarkdown + Go templatesNoAI-driven code review, endpoint discovery, custom analysis
Scanning ProfilesYAMLNoReusable scan presets (speed, modules, phases)
Scope RulesYAMLNoTarget filtering (hosts, paths, status codes, content types)
Pre/Post HooksJS or YAMLNoRequest mutation, finding suppression, severity escalation
Agent BackendsAny (subprocess)NoPlugging in new AI models or custom CLI tools
Config OverridesYAMLNoTuning concurrency, rate limits, database, notifications

1. JavaScript Extensions

JavaScript extensions are the most flexible way to add custom scanning logic without recompiling Vigolium. They run inside an embedded JS engine (Grafana Sobek) and have access to the full vigolium.* API — HTTP requests, database queries, parsing utilities, AI integration, and more.

What you can build

  • Active modules — send payloads to insertion points (parameters, headers, cookies, paths) and analyze responses for vulnerabilities.
  • Passive modules — analyze captured HTTP traffic without generating new requests.
  • Pre-hooks — mutate requests before they reach scanner modules (inject auth headers, skip paths).
  • Post-hooks — filter, tag, or escalate findings after detection.

Minimal example (active module)

module.exports = {
  id: "reflected-param-scanner",
  name: "Reflected Parameter Scanner",
  type: "active",
  severity: "medium",
  confidence: "firm",
  scanTypes: ["per_insertion_point"],

  scanPerInsertionPoint: function(ctx, insertion) {
    var canary = "VGNM" + vigolium.utils.randomString(8);
    var resp = vigolium.http.send(insertion.buildRequest(canary));

    if (resp && resp.body.indexOf(canary) !== -1) {
      return [{
        matched: canary,
        url: ctx.request.url,
        name: "Reflected parameter: " + insertion.name,
        severity: "medium",
        request: insertion.buildRequest(canary),
        response: resp.raw
      }];
    }
    return null;
  }
};

Available APIs

NamespacePurposeKey Methods
vigolium.httpSend HTTP requestsget, post, request, send
vigolium.scanScan controllistModules, isInScope, createFinding, startNewScan
vigolium.dbDatabase accessrecords.query, findings.query, compareResponses
vigolium.parseHTTP parsingurl, request, response, headers, json
vigolium.utilsEncoding, hashing, I/Obase64Encode, sha256, readFile, exec, detectAnomaly
vigolium.ingestImport trafficurl, curl, raw, openapi, postman
vigolium.sourceSource code accesslist, readFile, listFiles, searchFiles
vigolium.agentAI integrationask, generatePayloads, analyzeResponse, confirmFinding
vigolium.configExtension variablesRead-only access to extensions.variables
Full TypeScript definitions: pkg/jsext/vigolium.d.ts

Setup

# vigolium-configs.yaml
audit:
  extensions:
    enabled: true
    extension_dir: ~/.vigolium/extensions/
    variables:
      auth_token: "Bearer eyJ..."
Drop .js files into ~/.vigolium/extensions/ and verify with vigolium extensions ls.

Pros

  • No recompilation — drop a file and scan.
  • Full API access — HTTP, database, AI, source code, parsing, and system utilities.
  • AI-augmented scanning — use vigolium.agent.generatePayloads() and vigolium.agent.analyzeResponse() for LLM-powered detection.
  • Rapid iteration — edit, save, rescan.
  • Sandboxed execution — file I/O constrained to sandbox_dir, exec() gated behind config.

Cons

  • Slower than Go — interpreted JS engine adds overhead per invocation.
  • No Go standard library — limited to vigolium.* APIs, no arbitrary imports.
  • Single-threaded per VM — each extension instance runs in its own VM (thread-safe via pooling, but no parallelism within a single extension).
  • Limited debugging — no step-through debugger, vigolium.log.* is your main tool.

When to use

  • You need a custom vulnerability check and don’t want to recompile.
  • You want AI-augmented payload generation or response analysis.
  • You need database or source code access in your check logic.
  • You’re building organization-specific checks (e.g., custom header validation, business-logic flaws).
See the full guide: Writing Extensions

2. YAML Extensions

YAML extensions (.vgm.yaml) are a declarative alternative to JavaScript. They’re ideal for simple payload-and-matcher rules where you don’t need programmatic control flow.

Minimal example (active module)

id: error-pattern-detector
name: Error Pattern Detector
type: active
severity: low
confidence: firm
scan_types: [per_request]

payloads:
  - "'"
  - "\" OR 1=1--"

matchers:
  - type: body
    regex: "(?i)(SQL syntax|mysql_fetch|ORA-\\d{5}|SQLSTATE\\[)"
  - type: body
    regex: "(?i)(Traceback \\(most recent call last\\)|at \\w+\\.java:\\d+)"

matchers_condition: or

finding:
  name: "Error-Based Information Leak"
  description: "Application returns verbose error messages that reveal implementation details"
  severity: low

YAML hook example (pre-hook)

id: auth-header-injector
name: Auth Header Injector
type: pre_hook

add_headers:
  Authorization: "Bearer ${AUTH_TOKEN}"
  X-Request-ID: "vgm-{{random}}"

skip_when:
  url_contains: ["/health", "/metrics"]

YAML hook example (post-hook)

id: suppress-low-on-static
name: Suppress Low Findings on Static Assets
type: post_hook

drop_when:
  severity: [low, info]
  url_contains: ["/static/", "/assets/", ".css", ".js"]

escalate:
  when_url_contains: ["/admin", "/api/v1/auth"]
  bump_severity: true
  tag: sensitive_endpoint

Supported features

FeatureDescription
payloadsList of strings injected per insertion point or request
matchersBody regex/contains, header checks, status codes, or inline JS
matchers_conditionor (any matcher) or and (all matchers)
add_headersPre-hook: headers to inject
skip_whenPre-hook: conditions to skip processing
drop_whenPost-hook: conditions to discard findings
escalatePost-hook: bump severity, add tags
scriptInline JS escape hatch for complex logic

Pros

  • Zero coding — pure declarative YAML.
  • Fast to write — a payload list + matcher regex is often all you need.
  • Easy to audit — non-technical team members can review rules.
  • Same pipeline integration — loaded alongside JS extensions, same lifecycle.

Cons

  • Limited logic — no conditionals, loops, or state beyond what matchers offer.
  • No API access — no database queries, HTTP follow-ups, or AI calls (unless you use the script escape hatch, which is effectively JS).
  • No multi-step checks — can’t chain requests or compare responses across steps.
  • Coarser insertion control — payload injection is straightforward but you can’t dynamically generate payloads based on context.

When to use

  • Simple signature-based detection (error strings, header patterns, status codes).
  • Quick pre-hook rules (add auth headers, skip static assets).
  • Post-hook filtering (suppress low-severity findings on static paths).
  • When non-developers need to contribute scanning rules.
See the full guide: Writing Extensions

3. Go Modules

Go modules are the highest-performance extension point. They compile directly into the scanner binary, have full access to Go internals (HTTP client, deduplication, OAST, mutation engine), and run concurrently in the worker pool.

Module interfaces

All modules implement the base Module interface:
type Module interface {
    ID() string
    Name() string
    Description() string
    ShortDescription() string
    ConfirmationCriteria() string
    Severity() severity.Severity
    Confidence() severity.Confidence
    ScanScopes() ScanScope
    CanProcess(ctx *httpmsg.HttpRequestResponse) bool
}
Active modules add three scan methods (implement only the ones matching your declared ScanScopes()):
type ActiveModule interface {
    Module
    AllowedInsertionPointTypes() InsertionPointTypeSet
    ScanPerInsertionPoint(ctx, ip, httpClient, scanCtx) ([]*ResultEvent, error)
    ScanPerRequest(ctx, httpClient, scanCtx) ([]*ResultEvent, error)
    ScanPerHost(ctx, httpClient, scanCtx) ([]*ResultEvent, error)
}
Passive modules analyze traffic without sending new requests:
type PassiveModule interface {
    Module
    Scope() PassiveScanScope
    ScanPerRequest(ctx, scanCtx) ([]*ResultEvent, error)
    ScanPerHost(ctx, scanCtx) ([]*ResultEvent, error)
}

Creating a module

  1. Create a package under pkg/modules/active/ or pkg/modules/passive/.
  2. Embed modkit.BaseActiveModule or modkit.BasePassiveModule for defaults.
  3. Implement scan methods for your declared scopes.
  4. Register in pkg/modules/default_registry.go.
package my_check

import (
    "github.com/vigolium/vigolium/pkg/modules/modkit"
    "github.com/vigolium/vigolium/pkg/output"
    // ...
)

type Module struct {
    modkit.BaseActiveModule
}

func New() *Module {
    return &Module{
        BaseActiveModule: modkit.NewBaseActiveModule(
            "my-check",
            "My Custom Check",
            "Detailed description of what this checks",
            "One-line summary",
            "How the vulnerability is confirmed",
            severity.High,
            severity.Firm,
            modkit.ScanScopeInsertionPoint,
            modkit.AllParamTypes,
        ),
    }
}

func (m *Module) ScanPerInsertionPoint(
    ctx *httpmsg.HttpRequestResponse,
    ip httpmsg.InsertionPoint,
    httpClient *http.Requester,
    scanCtx *modkit.ScanContext,
) ([]*output.ResultEvent, error) {
    // Your scanning logic here
    return nil, nil
}

Scan scope options

ScopeInvocationTypical use
ScanScopeInsertionPointOnce per parameter (URL param, body param, header, cookie, JSON key, path segment)Injection vulnerabilities (XSS, SQLi, SSTI, command injection)
ScanScopeRequestOnce per unique requestRequest-level checks (missing headers, auth bypass, method manipulation)
ScanScopeHostOnce per unique hostHost-level checks (TLS config, server fingerprinting, path discovery)
Scopes are a bitmask — you can combine them (e.g., ScanScopeRequest | ScanScopeHost).

Pros

  • Maximum performance — compiled Go, no interpreter overhead, runs in the concurrent worker pool.
  • Full internal access — HTTP client with middleware, deduplication manager, OAST callbacks, mutation engine, baseline caching.
  • Type safety — compile-time checks, IDE support, Go testing ecosystem.
  • First-class integration — same lifecycle as built-in modules, automatic pipeline wiring.

Cons

  • Requires recompilation — every change needs make build.
  • Go knowledge required — must understand Go, the module interfaces, and internal types.
  • Slower iteration — compile-test cycle is heavier than drop-in JS/YAML.
  • Tighter coupling — changes to internal APIs may require module updates.

When to use

  • Performance-critical checks that run on every request or insertion point.
  • Checks that need deep integration with Vigolium internals (OAST, mutation engine, dedup).
  • You’re contributing to the core scanner or building a permanent module.
  • Checks requiring complex multi-step logic with full concurrency support.
See the full guide: Developing Modules

4. Custom Prompt Templates

Prompt templates drive Vigolium’s agent mode. They’re Markdown files with YAML frontmatter that define what an AI agent should analyze and how it should report results. Templates support Go template syntax and are automatically enriched with context from the database, module registry, and source code.

Template format

---
id: my-custom-review
name: My Custom Review
description: What this template does
output_schema: findings    # or: http_records
variables:
  - SourceCode
  - Language
  - PreviousFindings
---

You are a security engineer. Analyze the following code for {{.Language}} vulnerabilities.

{{if .PreviousFindings}}
Previous findings to verify:
{{.PreviousFindings}}
{{end}}

Source code:
```
{{.SourceCode}}
```

Respond with JSON: {"findings": [...]}

Available template variables

VariableSourceDescription
SourceCodeGathered from --repo/--filesConcatenated source code
LanguageAuto-detectedPrimary language (Go, Python, JS, etc.)
Framework--framework flagFramework hint
FilePathGatheredPrimary file path
RepoPath--repo flagRepository root path
TargetURL--target flagTarget URL
HostnameDerived from targetHostname for DB lookups
Endpoints--endpoints flagPre-discovered endpoints
PreviousFindingsDatabase (JSON)Prior findings for context
DiscoveredEndpointsDatabase (JSON)HTTP records from DB
ModuleListModule registry (JSON)Available scanner modules
ScanStatsDatabase (JSON)Aggregate scan statistics
AvailableCommandsHardcoded referenceCLI commands the agent can invoke
Extra--extra flagCustom key-value pairs
Only variables listed in the frontmatter variables array trigger database queries, keeping prompts fast.

Output schemas

findings — for code review, vulnerability detection:
{
  "findings": [{
    "title": "SQL Injection in login handler",
    "severity": "critical",
    "confidence": "certain",
    "file": "auth/login.go",
    "line": 42,
    "snippet": "db.Query(\"SELECT * FROM users WHERE id=\" + userID)",
    "cwe": "CWE-89",
    "tags": ["sqli"]
  }]
}
http_records — for endpoint discovery, API input generation:
{
  "http_records": [{
    "method": "POST",
    "url": "https://api.example.com/users",
    "headers": {"Content-Type": "application/json"},
    "body": "{\"name\": \"test\"}",
    "notes": "Create user endpoint"
  }]
}

Preset templates

Vigolium ships with 15 built-in templates:
TemplateSchemaPurpose
security-code-reviewfindingsGeneral OWASP-focused code review
injection-sinksfindingsIdentify injection sinks (SQLi, cmd, SSRF)
auth-bypassfindingsAuthentication/authorization bypass patterns
secret-detectionfindingsHardcoded secrets and credentials
endpoint-discoveryhttp_recordsExtract API routes from source code
api-input-genhttp_recordsGenerate HTTP requests from endpoints
curl-command-genhttp_recordsGenerate curl commands for all routes
interactive-scanfindingsAutopilot: analyze + run scans
targeted-retestfindingsAutopilot: verify previous findings
attack-surface-mapperhttp_recordsDiscover and cross-reference APIs
nextjs-security-auditfindingsNext.js-specific security review
react-xss-auditfindingsReact XSS pattern analysis
auth-session-reviewfindingsAuth and session management
cors-csrf-reviewfindingsCORS/CSRF configuration review
build-config-auditfindingsBuild/deployment config security

Setup

Place custom templates in ~/.vigolium/prompts/ or set agent.templates_dir in config. User templates override built-in ones by ID.
# Use a custom template
vigolium agent --prompt-template my-custom-review --repo /path/to/source

# Dry-run to see the rendered prompt
vigolium agent --prompt-template my-custom-review --repo /path/to/source --dry-run

Pros

  • No code — Markdown files with template syntax.
  • Context-aware — automatic enrichment with database findings, endpoints, scan stats.
  • Multiple AI backends — works with Claude, Codex, OpenCode, Gemini, or any custom agent.
  • Iterative refinement — autopilot and pipeline modes pass prior findings back for verification.
  • Two output modes — emit findings for code review or HTTP records for endpoint discovery.

Cons

  • AI dependency — requires a configured agent backend and API access.
  • Non-deterministic — LLM output varies between runs; false positives require tuning.
  • Latency — agent invocations are slower than pattern matching (seconds to minutes per run).
  • Token costs — large codebases consume significant tokens per analysis.

When to use

  • Code-level security review that needs semantic understanding (not just pattern matching).
  • Generating HTTP test inputs from source code (route extraction, API fuzzing seeds).
  • Framework-specific audits (Next.js, React, Django, Spring) where templates can embed domain knowledge.
  • Iterative analysis where the agent refines findings across multiple passes.

5. Scanning Profiles

Profiles are YAML files that overlay on top of the main configuration. They bundle scanning strategy, pace, phase settings, and module selection into a reusable preset.

Format

A profile is a subset of vigolium-configs.yaml. Only non-nil values override the base config.
# ~/.vigolium/profiles/aggressive.yaml
# description: Fast aggressive scan for CI/CD pipelines

scanning_strategy:
  default_strategy: deep

scanning_pace:
  concurrency: 100
  rate_limit: 200
  max_per_host: 20
  audit:
    concurrency: 100
    max_duration: 60m

discovery:
  mode: files_and_dirs
  recursion:
    enabled: true
    max_depth: 8

spidering:
  max_depth: 0
  headless: true
  strategy: aggressive

audit:
  enabled_modules:
    active_modules:
      - all
    passive_modules:
      - all

Usage

# Use a named profile
vigolium scan --target https://example.com --scanning-profile aggressive

# Use a profile file path
vigolium scan --target https://example.com --scanning-profile /path/to/profile.yaml
Profiles are resolved from ~/.vigolium/profiles/ or public/presets/profiles/ by name.

Pros

  • Reusable presets — define once, use across targets and teams.
  • Composable — overlay on top of base config; only override what you need.
  • No code — pure YAML.
  • Team-friendly — share profiles in version control for consistent scan policies.

Cons

  • Config-only — can’t add new scanning logic, only tune existing settings.
  • No per-target logic — same profile applies to all targets in a scan.
  • Limited validation — typos in field names silently ignored.

When to use

  • You run different scan intensities for different contexts (CI/CD vs. full audit vs. quick check).
  • You want to enforce consistent scan settings across a team.
  • You need to toggle phases (e.g., skip discovery, only run passive modules).

6. Scope Rules

Scope rules control what gets scanned. They filter at the host, path, status code, content type, and body level. You can define them in the config, via CLI flags, or programmatically from JS extensions.

Configuration

# vigolium-configs.yaml
scope:
  applied_on_ingest: false     # enforce at ingest time or scan time

  host:
    include: ["*.example.com", "api.example.com"]
    exclude: ["staging.example.com"]

  path:
    include: ["/api/*"]
    exclude: ["/api/health", "/api/metrics", "/static/*"]

  status_code:
    include: ["2xx", "3xx"]    # exact, wildcard (2xx), range (400-499)
    exclude: ["404"]

  request_content_type:
    include: ["application/json*", "application/x-www-form-urlencoded*"]

  response_content_type:
    include: ["text/html*", "application/json*"]
    exclude: ["image/*", "font/*"]

  ignore_static_file: true     # auto-skip .jpg, .png, .css, etc.

Scope from extensions

// Check scope programmatically
if (vigolium.scan.isInScope("api.example.com", "/users")) {
  // proceed
}

// Read current scope
var scope = vigolium.scan.getScope();

// Modify scope at runtime
vigolium.scan.setScope({
  host: { include: ["*.example.com"], exclude: [] },
  path: { include: ["/api/*"], exclude: [] }
});

Pros

  • Precision targeting — scan only what matters, skip noise.
  • Multiple filter types — host globs, path patterns, status codes, content types, body strings.
  • Runtime adjustable — extensions can modify scope during a scan.
  • Safety net — prevents accidental scanning of out-of-scope systems.

Cons

  • Config-only complexity — complex scope rules can be hard to debug.
  • No request-level conditions — you can’t scope by request header values or authentication state (use pre-hooks for that).

When to use

  • Restricting scans to specific subdomains or API paths.
  • Excluding health checks, static assets, or third-party endpoints.
  • Bug bounty programs with defined scope boundaries.
  • Filtering by response characteristics (status codes, content types).

7. Pre-Hooks and Post-Hooks

Hooks wrap the scanning pipeline. Pre-hooks transform requests before modules process them. Post-hooks filter or modify findings after detection.

Pre-hook use cases

Use caseImplementation
Inject auth headersYAML add_headers or JS returning {headers: {...}}
Skip static assetsYAML skip_when.url_contains or JS returning null
Add correlation IDsJS generating unique IDs per request
Rewrite URLsJS modifying ctx.request before forwarding

Post-hook use cases

Use caseImplementation
Suppress low-severity on static pathsYAML drop_when
Escalate findings on admin endpointsYAML escalate.when_url_contains
Tag findings by business unitJS adding metadata based on URL patterns
AI-powered false positive filteringJS calling vigolium.agent.confirmFinding()

JS pre-hook example

module.exports = {
  id: "inject-session",
  name: "Session Injector",
  type: "pre_hook",

  execute: function(request) {
    return {
      headers: {
        "Cookie": "session=" + vigolium.config.session_token,
        "X-Correlation-ID": vigolium.utils.randomString(16)
      }
    };
  }
};

JS post-hook example (AI false positive filter)

module.exports = {
  id: "ai-fp-filter",
  name: "AI False Positive Filter",
  type: "post_hook",

  execute: function(result) {
    if (typeof vigolium.agent === "undefined") return result;

    var check = vigolium.agent.confirmFinding({
      name: result.info.name,
      request: result.request,
      response: result.response,
      matched: result.matched
    });

    if (!check.confirmed && check.confidence !== "low") {
      vigolium.log.info("Suppressed FP: " + result.info.name);
      return null; // drop the finding
    }
    return result;
  }
};

Pros

  • Pipeline integration — runs automatically on every request/finding.
  • Composable — multiple hooks chain sequentially.
  • Both JS and YAML — simple rules in YAML, complex logic in JS.
  • Non-invasive — doesn’t modify module code.

Cons

  • Sequential overhead — hooks run on the hot path; slow hooks slow everything.
  • Order-dependent — hook execution order matters but isn’t always obvious.
  • Pre-hooks can’t see responses — they only have access to the outbound request.

When to use

  • You need to inject authentication into every request (pre-hook).
  • You want to suppress known false positives across all modules (post-hook).
  • You need to tag or route findings based on URL patterns (post-hook).
  • AI-powered confirmation of findings before reporting (post-hook).
See the full guide: Writing Extensions

8. Agent Backends

Agent backends are external processes that Vigolium invokes for AI-driven analysis. You can plug in any CLI tool that accepts a prompt and returns structured output.

Built-in backends

BackendProtocolCommand
Claude Code (ACP)acpnpx -y @zed-industries/claude-agent-acp@latest
Codex (ACP)acpcodex app-server
OpenCode (ACP)acpnpx -y opencode-acp
Gemini (ACP)acpgemini --experimental-acp
Claude CLI (pipe)pipeclaude --dangerously-skip-permissions -p

Adding a custom backend

# vigolium-configs.yaml
agent:
  backends:
    my-agent:
      command: my-tool
      args: ["--json", "--security-mode"]
      description: "My custom security agent"
      protocol: pipe        # pipe: prompt on stdin, output on stdout
      env:
        MY_API_KEY: "${MY_API_KEY}"
Use it:
vigolium agent --agent my-agent --prompt-template security-code-review --repo /path/to/code

Protocols

ProtocolHow it worksAgent capabilities
pipePrompt piped to stdin, output read from stdoutSimple: no tool use, no file access
acpBidirectional JSON-RPC over stdioFull: file reading, tool invocation, streaming

Warm sessions

For iterative workflows (autopilot), ACP backends support session pooling to avoid subprocess startup overhead:
agent:
  warm_session:
    enable: true
    idle_timeout: 300    # seconds before killing idle session
    max_sessions: 2      # concurrent sessions per agent

LLM config (for JS extensions)

The agent.llm section configures the LLM provider used by vigolium.agent.* APIs in JavaScript extensions:
agent:
  llm:
    provider: anthropic    # or openai
    model: claude-sonnet-4-20250514
    api_key_env: ANTHROPIC_API_KEY
    max_tokens: 4096
    temperature: 0.0
    cache_size: 256        # LRU cache; 0 = disabled
    cache_ttl: 300         # seconds

Pros

  • Any AI model — plug in any CLI tool as a backend.
  • Two protocols — simple pipe for basic tools, ACP for full agent capabilities.
  • Session pooling — warm sessions reduce latency for iterative analysis.
  • Environment isolation — per-agent env vars, scoped file access.

Cons

  • External dependency — requires installing and configuring the agent CLI.
  • Cost — AI API calls have token costs.
  • Latency — subprocess startup + LLM inference is slower than local checks.

When to use

  • You have a preferred AI model or a fine-tuned security model you want to integrate.
  • You’re building a custom tool that produces structured security findings.
  • You need agent capabilities beyond what the built-in backends provide.

9. Configuration Overrides

The main vigolium-configs.yaml is the central control plane for all scan behavior. Every aspect of the scanner — phases, pace, modules, database, notifications, and more — is configurable.

Key configuration sections

SectionWhat it controls
scanning_strategyPhase presets: lite, balanced, deep, whitebox
scanning_paceConcurrency, rate limits, per-phase duration caps
auditActive/passive module selection, extension config
discoveryContent discovery mode, recursion, wordlists
spideringBrowser crawling depth, strategy, headless mode
scopeHost/path/status/content-type filtering
databaseSQLite or PostgreSQL, connection settings
notifyAlert routing: Telegram, Discord, severity filters
mutation_strategyPayload mutation modes, field-type defaults
oastOut-of-band testing server, blind XSS config
agentAI backends, LLM config, warm sessions

Environment variable expansion

database:
  postgres:
    password: ${VIGOLIUM_DB_PASSWORD}

agent:
  llm:
    api_key_env: ANTHROPIC_API_KEY

Pros

  • Comprehensive — controls every scanner behavior.
  • Environment-aware — variable expansion for secrets.
  • Layered — base config + profiles + CLI flags, in order of precedence.

Cons

  • No logic — pure configuration, can’t express conditional behavior.
  • Silent failures — unrecognized keys are ignored, not flagged.
  • Single file — large configs can become unwieldy.

When to use

  • Tuning scan speed and resource usage for your infrastructure.
  • Selecting which modules run by default.
  • Configuring database, notifications, and OAST.
  • Setting organization-wide defaults.

Decision Matrix

Use this table to quickly pick the right extension mechanism:
I want to…Use
Add a custom vulnerability check (simple patterns)YAML Extension
Add a custom vulnerability check (complex logic)JS Extension
Add a high-performance check compiled into the binaryGo Module
Run AI code review with custom focus areasPrompt Template
Create a reusable scan preset for my teamScanning Profile
Restrict scanning to specific hosts/pathsScope Rules
Inject auth headers into every requestPre-Hook
Suppress false positives across all modulesPost-Hook
Use AI to confirm findings before reportingPost-Hook + agent API
Plug in a new AI modelAgent Backend
Tune concurrency and rate limitsConfig Override or Profile
Generate HTTP test inputs from source codePrompt Template (with http_records schema)
Build an organization-specific scanner pipelineCombine: Profile + Scope + Hooks + Extensions