Extensions¶
Extensions are third-party tools -- BOFs, .NET assemblies, DLLs, scripts, and aliases -- that plug into Stentor and register as native shell commands in the beacon console. The extension system provides an Armory-style catalog for browsing, installing, updating, and managing extensions, along with Ed25519 signature verification for supply chain integrity.
Overview¶
Extensions allow operators to expand Stentor's post-exploitation capabilities without modifying the core codebase. Each extension ships with a manifest that declares its metadata, supported platforms, entry point, and the shell commands it provides. Once installed and enabled, the extension's commands become available in the beacon console alongside built-in commands.
Key capabilities:
- Catalog browsing -- Discover extensions from a remote repository with one API call
- One-click install -- Install extensions by name; the server downloads, verifies, and stores them automatically
- Signature verification -- Ed25519 signatures on extension packages prevent tampering
- Enable/disable toggle -- Temporarily disable an extension without uninstalling it
- Automatic updates -- Check for and apply new versions from the catalog
- Manual upload -- Install extensions from local files for air-gapped environments
- Command resolution -- Enabled extensions are automatically resolved when operators type their commands in the beacon shell
flowchart LR
A[Extension Catalog] -->|download + verify| B[Stentor Server]
C[Manual Upload] -->|multipart POST| B
B -->|store| D[(PostgreSQL)]
D -->|resolve command| E[Beacon Shell]
E -->|execute| F[Beacon] Extension Types¶
Extensions are categorized by their runtime type:
| Type | Description | Entry Point |
|---|---|---|
bof | Beacon Object File (position-independent C code) | C function name (e.g., go) |
assembly | .NET assembly (execute-assembly) | Fully qualified class.method |
dll | Native DLL (reflective loading) | Exported function name |
script | CNA script extension | CNA function name |
alias | Command alias (maps to existing commands) | Alias target |
Extension Manifest¶
Every extension package includes a manifest.json that describes the extension. The manifest is validated on install with the following rules:
namemust be alphanumeric with dashes/underscores (regex:^[a-zA-Z0-9][a-zA-Z0-9_-]*$)versionmust be semver format (e.g.,1.2.0,1.0.0-beta.1)typemust be one of:bof,assembly,dll,script,alias- At least one command must be declared
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Unique extension identifier (e.g., "nanodump") |
version | string | Yes | Semantic version (e.g., "1.2.0") |
author | string | Yes | Author name or handle |
description | string | Yes | Human-readable description |
type | string | Yes | Extension type: bof, assembly, dll, script, alias |
platforms | string[] | Yes | Supported platforms (e.g., ["windows/x64", "windows/x86"]) |
entry_point | string | Yes | Runtime entry point (function name, class.method, etc.) |
commands | ExtensionCommand[] | Yes | Shell commands this extension provides |
dependencies | string[] | No | Other extension names required |
min_version | string | No | Minimum Stentor version required |
license | string | No | SPDX license identifier |
repository | string | No | Source code URL |
tags | string[] | No | Category tags for search |
Each command in the commands array:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Shell command name (e.g., "nanodump") |
description | string | Yes | Help text |
usage | string | Yes | Usage syntax (e.g., "nanodump [pid] [--fork]") |
help_text | string | No | Extended help |
Example manifest:
{
"name": "nanodump",
"version": "1.3.0",
"author": "helpsystems",
"description": "MiniDumpWriteDump via syscalls for LSASS credential extraction",
"type": "bof",
"platforms": ["windows/x64"],
"entry_point": "go",
"commands": [
{
"name": "nanodump",
"description": "Dump LSASS credentials using NtReadVirtualMemory syscalls",
"usage": "nanodump [--pid <pid>] [--fork] [--dup] [--write C:\\path]"
}
],
"min_version": "3.0.0",
"license": "MIT",
"tags": ["credentials", "lsass", "bof"]
}
API Reference¶
All extension endpoints require JWT authentication.
Base path: /api/v1/extensions
List Installed Extensions¶
GET /api/v1/extensions
Returns all installed extensions, ordered by name. The data and signature fields are excluded for efficiency; the response includes a computed size field instead.
Response (200 OK):
[
{
"id": "d4e5f6a7-b8c9-0123-4567-890abcdef012",
"name": "nanodump",
"version": "1.3.0",
"author": "helpsystems",
"description": "MiniDumpWriteDump via syscalls for LSASS credential extraction",
"type": "bof",
"platforms": ["windows/x64"],
"entry_point": "go",
"manifest": { ... },
"enabled": true,
"size": 45056,
"installed_at": "2026-02-20T14:30:00Z"
}
]
Get Extension¶
GET /api/v1/extensions/:id
Returns a single extension by ID (includes full manifest).
Browse Catalog¶
GET /api/v1/extensions/catalog
Fetches the list of available extensions from the configured remote repository. Results are cached server-side for 5 minutes.
Response (200 OK):
[
{
"name": "nanodump",
"version": "1.3.0",
"author": "helpsystems",
"description": "MiniDumpWriteDump via syscalls for LSASS credential extraction",
"type": "bof",
"platforms": ["windows/x64"],
"entry_point": "go",
"commands": [
{
"name": "nanodump",
"description": "Dump LSASS credentials using NtReadVirtualMemory syscalls",
"usage": "nanodump [--pid <pid>] [--fork] [--dup] [--write C:\\path]"
}
]
}
]
Catalog Configuration
The catalog URL is configured via the EXTENSION_REPO_URL server environment variable. If not set, the catalog endpoint returns an empty array.
Install Extension¶
POST /api/v1/extensions/install
Downloads and installs an extension from the remote repository. The server fetches the package (tar.gz), downloads and verifies the Ed25519 signature, extracts the embedded manifest, and stores everything in the database.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Extension name (must match a catalog entry) |
version | string | No | Specific version to install. Omit or "latest" for the newest version. |
curl -s -X POST https://stentor.app/api/v1/extensions/install \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "nanodump"}'
Response (201 Created):
{
"id": "d4e5f6a7-b8c9-0123-4567-890abcdef012",
"name": "nanodump",
"version": "1.3.0",
"author": "helpsystems",
"description": "MiniDumpWriteDump via syscalls for LSASS credential extraction",
"type": "bof",
"platforms": ["windows/x64"],
"entry_point": "go",
"manifest": { ... },
"enabled": true,
"size": 45056,
"installed_at": "2026-02-21T10:00:00Z"
}
Error Responses:
| Status | Body | Cause |
|---|---|---|
| 400 | {"error": "..."} | Invalid request or signature verification failure |
| 404 | {"error": "extension \"xyz\" not found in catalog"} | Name not in catalog |
| 409 | {"error": "extension \"nanodump\" already installed"} | Duplicate name |
Upload Extension (Manual)¶
POST /api/v1/extensions/upload
Install an extension from local files using multipart form upload. This is the offline installation path for air-gapped environments.
Multipart Form Fields:
| Field | Type | Required | Description |
|---|---|---|---|
manifest | file | Yes | The manifest.json file |
data | file | Yes | The extension binary (BOF .o, .NET assembly, DLL, or script) |
signature | file | No | Ed25519 signature file (.sig). If provided, it is verified against the data. |
curl -s -X POST https://stentor.app/api/v1/extensions/upload \
-H "Authorization: Bearer $TOKEN" \
-F "[email protected]" \
-F "[email protected]" \
-F "[email protected]"
Response (201 Created): Same as Install response.
Signature Verification on Upload
If a signature file is provided, the server verifies it against the data bytes using the configured Ed25519 public key. If no public key is configured (development mode), verification is skipped with a warning log.
Remove Extension¶
DELETE /api/v1/extensions/:id
Uninstalls an extension. Its shell commands will no longer be available in the beacon console.
curl -s -X DELETE https://stentor.app/api/v1/extensions/$EXTENSION_ID \
-H "Authorization: Bearer $TOKEN"
Response: 204 No Content
Toggle Extension¶
POST /api/v1/extensions/:id/toggle
Enable or disable an extension without removing it. Disabled extensions remain installed but their commands are not resolved in the beacon shell.
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
enabled | boolean | Yes | true to enable, false to disable |
curl -s -X POST https://stentor.app/api/v1/extensions/$EXTENSION_ID/toggle \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": false}'
Response (200 OK): Returns the updated extension object.
Update Extension¶
POST /api/v1/extensions/:id/update
Updates an installed extension to the latest version from the remote catalog. The server compares the installed version against the catalog, downloads the new package if a newer version exists, verifies the signature, and replaces the stored data.
curl -s -X POST https://stentor.app/api/v1/extensions/$EXTENSION_ID/update \
-H "Authorization: Bearer $TOKEN"
Response (200 OK):
If an update was applied, returns the updated extension object. If already up to date:
Signature Verification¶
Extension packages are signed with Ed25519 to ensure integrity and authenticity. The verification flow works as follows:
sequenceDiagram
participant Operator
participant Server
participant Repository
Operator->>Server: POST /extensions/install
Server->>Repository: GET /packages/{name}/{version}.tar.gz
Repository-->>Server: Package data
Server->>Repository: GET /packages/{name}/{version}.sig
Repository-->>Server: Ed25519 signature (64 bytes)
Server->>Server: Verify signature against data
alt Signature valid
Server->>Server: Extract manifest.json from tar.gz
Server->>Server: Store extension in database
Server-->>Operator: 201 Created
else Signature invalid
Server-->>Operator: 400 Bad Request
end Configuration:
The Ed25519 public key is configured via the EXTENSION_PUBLIC_KEY server environment variable (hex-encoded). If not set, the server runs in development mode and skips signature verification with a warning log.
Production Deployment
Always configure EXTENSION_PUBLIC_KEY in production to prevent installation of tampered extension packages. Without it, any package will be accepted regardless of its signature.
Signing extensions (for package authors):
The GenerateKeyPair() and SignExtension() functions in the extension service can be used to create key pairs and sign packages:
- Generate an Ed25519 key pair
- Sign the extension
tar.gzwith the private key - Distribute the
.sigfile alongside the package - Configure the public key on all Stentor servers
Extension Response Object¶
All API responses (except delete) return the ExtensionResponse format, which excludes the raw binary data and signature bytes for efficiency.
| Field | Type | Description |
|---|---|---|
id | string (UUID) | Extension ID |
name | string | Extension name |
version | string | Installed version |
author | string | Author |
description | string | Description |
type | string | Extension type (bof, assembly, dll, script, alias) |
platforms | string[] | Supported platforms |
entry_point | string | Runtime entry point |
manifest | object | Full manifest JSON |
enabled | boolean | Whether the extension is active |
size | integer | Extension data size in bytes |
installed_at | string (ISO 8601) | Installation timestamp |
Repository Package Format¶
Extension packages in the catalog repository follow this structure:
/catalog.json # Array of ExtensionManifest objects
/packages/{name}/{version}.tar.gz # Gzipped tar archive containing:
# manifest.json
# <extension binary>
/packages/{name}/{version}.sig # Ed25519 signature of the .tar.gz
The manifest.json can appear at any depth within the tar.gz archive -- the extractor searches for any file ending in manifest.json.
UI Integration¶
The Extensions page (/extensions) provides three sections:
- Installed Extensions -- Table view with columns for name, version, type, author, platforms, commands, size, and enabled toggle. Each row has update and remove buttons.
- Extension Catalog -- Collapsible panel that fetches the remote catalog on demand. Shows available extensions with install buttons. Already-installed extensions show an "Installed" badge.
- Manual Upload -- Collapsible form for uploading local manifest, data, and optional signature files.
Cross-References¶
- REST API Reference -- Extension endpoints are listed under the Extensions section
- Beacon Commands -- Extensions register as additional beacon shell commands
- Scripting -- CNA script extensions use the
scripttype