# Write Jsext

Reference for writing custom vigolium JavaScript extensions.

- Repository: https://github.com/vigolium/vigolium (1141 stars)
- Category: Writing
- License: MIT
- Last updated: 2026-10-25
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add vigolium/vigolium --skill write-jsext -g -a claude-code -y`
Codex: `npx skills add vigolium/vigolium --skill write-jsext -g -a codex -y`
Cursor: `npx skills add vigolium/vigolium --skill write-jsext -g -a cursor -y`
Gemini CLI: `npx skills add vigolium/vigolium --skill write-jsext -g -a gemini-cli -y`

## Description

Reference for writing custom vigolium JavaScript extensions. Use when you need to author a one-off scanner module, passive (reads existing HTTP records) or active (sends new requests), and run it via the run_extension tool. Covers the module shape, the vigolium.* API surface, and the common pitfalls.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# Writing a Custom Vigolium JS Extension

You're authoring a single-file JavaScript extension that the vigolium scanner
will load and run. Two output paths from here:

1. Hand the file path or inline source to **`run_extension`** to execute it
   immediately and get back findings.
2. Write the file to disk (e.g. into the session dir) for the operator to
   reuse later via `vigolium scan --ext path/to/script.js`.

You do **not** need a build step. Vigolium's embedded JS engine (Sobek) runs
the script directly. ES2017 features work; no `import` / `export`, use
`module.exports`.

## Module Shape

Every extension exports one object via `module.exports`. The shape decides
whether it runs as a passive or active scanner module.

### Passive (read-only, runs against stored HTTP records)

```javascript
module.exports = {
  id: "kebab-case-id",                // unique within the run
  name: "Human-readable name",
  description: "1, 2 sentence purpose",
  type: "passive",                     // required
  severity: "low",                     // critical|high|medium|low|info
  confidence: "tentative",             // certain|firm|tentative
  scope: "response",                   // request|response|both, what to read
  tags: ["exposure", "light"],         // free-form classification
  scanTypes: ["per_request"],          // only "per_request" for passive

  scanPerRequest: function(ctx) {
    // ctx.request:  { url, method, headers, body, ... }
    // ctx.response: { status, headers, body, ... }
    // ctx.record:   { uuid, addRemarks(tags) }  (DB-backed records only)
    //
    // Return null when there's nothing to report, OR an array of finding
    // objects (see "Finding shape" below). Throwing is fine, vigolium
    // catches per-record errors and continues.
  }
};
```

### Active (sends new requests; can mutate inputs and probe)

The rest: https://github.com/vigolium/vigolium/blob/HEAD/internal/resources/olium/skills/write-jsext/SKILL.md
