ATT&CK Workbench REST API Configuration Guide
May 7, 2026 · View on GitHub
This guide explains how to configure the ATT&CK Workbench REST API using environment variables, JSON configuration files, or a combination of both.
Table of Contents
- ATT&CK Workbench REST API Configuration Guide
Configuration System Overview
The REST API uses Convict, a configuration management library.
All configuration is defined in app/config/config.js with sensible defaults.
You only need to override values specific to your environment.
Configuration Methods
Environment Variables
Environment variables are the recommended method for configuring the REST API in containerized deployments and for simple configurations.
A template.env file is included in the repository for you to make use of this option.
JSON Configuration File
JSON configuration files are recommended for complex configurations, especially when defining service accounts or OIDC clients.
Setting up JSON configuration:
-
Create a configuration file (e.g.,
config.json):{ "server": { "port": 3000, "corsAllowedOrigins": ["https://workbench.example.com", "https://staging.example.com"] }, "database": { "url": "mongodb://localhost:27017/attack-workspace" }, "userAuthn": { "mechanism": "oidc", "oidc": { "issuerUrl": "https://auth.example.com/realms/workbench", "clientId": "attack-workbench-rest-api", "clientSecret": "your-client-secret", "redirectOrigin": "https://workbench.example.com" } }, "serviceAuthn": { "basicApikey": { "enable": true, "serviceAccounts": [ { "name": "navigator", "apikey": "your-navigator-apikey", "serviceRole": "read-only" }, { "name": "collection-manager", "apikey": "your-collection-manager-apikey", "serviceRole": "collection-manager" } ] } } } -
Reference the file via environment variable:
export JSON_CONFIG_PATH=/path/to/config.json npm startOr in
.env:JSON_CONFIG_PATH=/path/to/config.json
Configuration Precedence
When both environment variables and JSON configuration are used:
- Environment variables are loaded first with their defaults
- JSON configuration file (if specified) is loaded second and overrides environment variables
- Validation occurs after all configuration is loaded
Example:
# .env file
PORT=3000
DATABASE_URL=mongodb://localhost:27017/attack-workspace
JSON_CONFIG_PATH=./config.json
// config.json
{
"server": {
"port": 8080
}
}
Result: Port will be 8080 (JSON overrides environment variable)
Configuration Options
Server
Configuration for the HTTP server.
| Option | Environment Variable | JSON Path | Type | Default | Description |
|---|---|---|---|---|---|
| Port | PORT | server.port | integer | 3000 | HTTP server port |
| CORS Allowed Origins | CORS_ALLOWED_ORIGINS | server.corsAllowedOrigins | domains | * | Allowed origins for CORS. Use * for all, disable to disable CORS, or comma-separated list of origins |
CORS Allowed Origins accepts:
*- Allow any origin (not recommended for production)disable- Disable CORS entirely- Comma-separated list of origins (with protocol):
https://workbench.example.comhttp://localhost:4200,https://workbench.example.com
- Supports localhost, private IPs (10.x, 172.16-31.x, 192.168.x), and FQDNs
Examples:
# Environment variable
CORS_ALLOWED_ORIGINS=https://workbench.example.com,https://staging.example.com
// JSON
{
"server": {
"corsAllowedOrigins": ["https://workbench.example.com", "https://staging.example.com"]
}
}
Database
MongoDB database configuration.
| Option | Environment Variable | JSON Path | Type | Default | Description |
|---|---|---|---|---|---|
| URL | DATABASE_URL | database.url | string | (empty) | MongoDB connection string (REQUIRED) |
| Auto-migrate | WB_REST_DATABASE_MIGRATION_ENABLE | database.migration.enable | boolean | true | Run migrations automatically on startup |
Examples:
# Local MongoDB
DATABASE_URL=mongodb://localhost:27017/attack-workspace
# Docker Compose
DATABASE_URL=mongodb://attack-workbench-database/attack-workspace
Migration Notes:
- When
database.migration.enableistrue, migrations run automatically at startup - Set to
falseif you manage migrations separately (e.g., in a Kubernetes init container) - Migrations are idempotent and safe to run multiple times
- Automation-enabled migrations may also write durable audit records to
automationRunsandautomationRunItems; see Automation Run Audit Trail
Application
General application settings.
| Option | Environment Variable | JSON Path | Type | Default | Description |
|---|---|---|---|---|---|
| Name | (none) | app.name | string | attack-workbench-rest-api | Application name |
| Environment | NODE_ENV | app.env | string | development | Environment name (development, production, test) |
| Version | (none) | app.version | string | (from package.json) | Application version |
| ATT&CK Spec Version | (none) | app.attackSpecVersion | string | (from package.json) | ATT&CK specification version |
Example:
NODE_ENV=production
Logging
Logging configuration using Winston.
| Option | Environment Variable | JSON Path | Type | Default | Description |
|---|---|---|---|---|---|
| Log Level | LOG_LEVEL | logging.logLevel | string | info | Console log level |
Log Levels (from least to most verbose):
error- Only errorswarn- Warnings and errorshttp- HTTP requests, warnings, and errorsinfo- General information (recommended for production)verbose- Detailed informationdebug- Debug messages (recommended for development)
Example:
LOG_LEVEL=debug
Session
Session management for user authentication.
| Option | Environment Variable | JSON Path | Type | Default | Description |
|---|---|---|---|---|---|
| Secret | SESSION_SECRET | session.secret | string | (generated at startup) | Secret used to sign session cookies |
| Mongo Session Secret | MONGOSTORE_CRYPTO_SECRET | session.mongoStoreCryptoSecret | string | (generated at startup) | Secret to encrypt session data in MongoDB |
Important Notes:
- If not set, a secret is generated randomly at startup
- Random secrets are regenerated on restart, forcing users to re-login
- Random secrets cannot be shared across multiple server instances
- Production: Always set
SESSION_SECRETto a fixed, secure value
Generating a secure secret:
node -e "console.log(require('crypto').randomBytes(48).toString('base64'))"
Example:
SESSION_SECRET=your-secure-secret-here
MONGOSTORE_CRYPTO_SECRET=your-secure-secret-here
User Authentication
Configuration for user authentication (how end-users log in).
| Option | Environment Variable | JSON Path | Type | Default | Description |
|---|---|---|---|---|---|
| Mechanism | AUTHN_MECHANISM | userAuthn.mechanism | enum | anonymous | Authentication mechanism to use |
Mechanism Options:
anonymous- No authentication required (development only)oidc- OpenID Connect (recommended for production)
OIDC Configuration
Required when mechanism is set to oidc.
| Option | Environment Variable | JSON Path | Type | Default | Description |
|---|---|---|---|---|---|
| Issuer URL | AUTHN_OIDC_ISSUER_URL | userAuthn.oidc.issuerUrl | string | (empty) | OIDC provider's issuer URL |
| Client ID | AUTHN_OIDC_CLIENT_ID | userAuthn.oidc.clientId | string | (empty) | OIDC client identifier |
| Client Secret | AUTHN_OIDC_CLIENT_SECRET | userAuthn.oidc.clientSecret | string | (empty) | OIDC client secret |
| Redirect Origin | AUTHN_OIDC_REDIRECT_ORIGIN | userAuthn.oidc.redirectOrigin | string | http://localhost:3000 | Base URL for redirect URI |
Example:
AUTHN_MECHANISM=oidc
AUTHN_OIDC_ISSUER_URL=https://auth.example.com/realms/workbench
AUTHN_OIDC_CLIENT_ID=attack-workbench-rest-api
AUTHN_OIDC_CLIENT_SECRET=your-client-secret
AUTHN_OIDC_REDIRECT_ORIGIN=https://workbench.example.com
For detailed OIDC setup, see Authentication Documentation.
Service Authentication
Configuration for service-to-service authentication (APIs, automation tools).
The REST API supports three service authentication methods:
- OIDC Client Credentials - OAuth2 client credentials flow
- Challenge API Key - Token exchange with challenge/response
- Basic API Key - Simple API key authentication
All methods support role-based access control with three service roles:
read-only- Read-only access to endpointscollection-manager- Read/write access for collection managementstix-export- Access to STIX export endpoints
OIDC Client Credentials
Uses OAuth2 Client Credentials flow with JWT validation.
| Option | Environment Variable | JSON Path | Type | Default | Description |
|---|---|---|---|---|---|
| Enable | SERVICE_ACCOUNT_OIDC_ENABLE | serviceAuthn.oidcClientCredentials.enable | boolean | false | Enable OIDC client credentials authentication |
| JWKS URI | JWKS_URI | serviceAuthn.oidcClientCredentials.jwksUri | string | (empty) | JWKS endpoint for IdP public keys |
| Clients | (JSON only) | serviceAuthn.oidcClientCredentials.clients | array | [] | Array of authorized OIDC clients |
Clients Array Schema:
{
"clientId": "string", // OIDC client ID
"serviceRole": "enum" // Service role (read-only, collection-manager, stix-export)
}
Example:
# .env
SERVICE_ACCOUNT_OIDC_ENABLE=true
JWKS_URI=https://auth.example.com/realms/workbench/protocol/openid-connect/certs
JSON_CONFIG_PATH=./config.json
// config.json
{
"serviceAuthn": {
"oidcClientCredentials": {
"enable": true,
"clients": [
{
"clientId": "collection-manager-service",
"serviceRole": "collection-manager"
}
]
}
}
}
See sample configurations:
Challenge API Key
Token exchange authentication with challenge/response mechanism.
| Option | Environment Variable | JSON Path | Type | Default | Description |
|---|---|---|---|---|---|
| Enable | WB_REST_SERVICE_ACCOUNT_CHALLENGE_APIKEY_ENABLE | serviceAuthn.challengeApikey.enable | boolean | false | Enable challenge API key authentication |
| Token Signing Secret | WB_REST_TOKEN_SIGNING_SECRET | serviceAuthn.challengeApikey.secret | string | (generated at startup) | Secret used to sign access tokens |
| Token Timeout | WB_REST_TOKEN_TIMEOUT | serviceAuthn.challengeApikey.tokenTimeout | integer | 300 | Access token lifetime in seconds |
| Service Accounts | (JSON only) | serviceAuthn.challengeApikey.serviceAccounts | array | [] | Array of service accounts |
Service Accounts Array Schema:
{
"name": "string", // Service account name
"apikey": "string", // Shared secret (API key)
"serviceRole": "enum" // Service role
}
Example:
# .env
WB_REST_SERVICE_ACCOUNT_CHALLENGE_APIKEY_ENABLE=true
WB_REST_TOKEN_SIGNING_SECRET=your-secure-secret
WB_REST_TOKEN_TIMEOUT=600
JSON_CONFIG_PATH=./config.json
// config.json
{
"serviceAuthn": {
"challengeApikey": {
"enable": true,
"serviceAccounts": [
{
"name": "collection-manager",
"apikey": "your-secure-apikey",
"serviceRole": "collection-manager"
}
]
}
}
}
See sample: test-service-challenge-apikey.json
Basic API Key
Simple API key authentication (no challenge).
| Option | Environment Variable | JSON Path | Type | Default | Description |
|---|---|---|---|---|---|
| Enable | WB_REST_SERVICE_ACCOUNT_BASIC_APIKEY_ENABLE | serviceAuthn.basicApikey.enable | boolean | false | Enable basic API key authentication |
| Service Accounts | (JSON only) | serviceAuthn.basicApikey.serviceAccounts | array | [] | Array of service accounts |
Service Accounts Array Schema:
{
"name": "string", // Service account name
"apikey": "string", // API key
"serviceRole": "enum" // Service role
}
Example:
# .env
WB_REST_SERVICE_ACCOUNT_BASIC_APIKEY_ENABLE=true
JSON_CONFIG_PATH=./config.json
// config.json
{
"serviceAuthn": {
"basicApikey": {
"enable": true,
"serviceAccounts": [
{
"name": "navigator",
"apikey": "your-navigator-apikey",
"serviceRole": "read-only"
}
]
}
}
}
See sample: navigator-basic-apikey.json
Multiple Service Authentication Methods
You can enable multiple service authentication methods simultaneously:
{
"serviceAuthn": {
"oidcClientCredentials": {
"enable": true,
"clients": [
{
"clientId": "automated-collection-manager",
"serviceRole": "collection-manager"
}
]
},
"challengeApikey": {
"enable": true,
"serviceAccounts": [
{
"name": "legacy-service",
"apikey": "legacy-apikey",
"serviceRole": "read-only"
}
]
},
"basicApikey": {
"enable": true,
"serviceAccounts": [
{
"name": "navigator",
"apikey": "navigator-apikey",
"serviceRole": "read-only"
}
]
}
}
}
See sample: multiple-apikey-services.json
Scheduler
Background job scheduler configuration.
| Option | Environment Variable | JSON Path | Type | Default | Description |
|---|---|---|---|---|---|
| Enable | ENABLE_SCHEDULER | scheduler.enableScheduler | boolean | true | Enable background job scheduler |
| Check Interval | CHECK_WORKBENCH_INTERVAL | scheduler.checkWorkbenchInterval | integer | 10 | Scheduler check interval in seconds |
Scheduler Functions:
- Checks for collection index updates
- Downloads collection bundles from remote URLs
- Processes subscription update policies
Example:
ENABLE_SCHEDULER=true
CHECK_WORKBENCH_INTERVAL=30
Validation
Configuration for ATT&CK Data Model (ADM) request validation and the scheduled re-validation task.
| Option | Environment Variable | JSON Path | Type | Default | Description |
|---|---|---|---|---|---|
| Validate Requests | VALIDATE_WITH_ADM_SCHEMAS | validateRequests.withAttackDataModel | boolean | false | Run incoming POST/PUT bodies through the ADM schemas before persisting |
| Re-validate Cron | VALIDATE_OBJECTS_CRON | scheduler.validateObjectsCron | string | 0 3 * * * | Cron pattern for the background task that refreshes workspace.validation on every document |
| ADM Log Level | ADM_LOG_LEVEL | (env only) | enum | warn | Verbosity of the ADM library's internal logger |
VALIDATE_WITH_ADM_SCHEMAS
When enabled, every POST and PUT validates the composed STIX payload against the ADM schemas before saving. Failed validations cause the request to throw with an HTTP error and the document is not persisted. When disabled, the write pipeline does not gate on ADM compliance and downstream tools are responsible for detecting non-compliant content.
This setting does not affect the legacy OpenAPI request validation (VALIDATE_WITH_LEGACY_SCHEMAS), which can be enabled or disabled independently.
VALIDATE_OBJECTS_CRON
The Workbench scheduler periodically re-validates every SDO and SRO in the database against the current ADM and refreshes each document's workspace.validation field. This combats concept drift: documents that passed validation under an older ADM version may become non-compliant after a Workbench upgrade.
The cron pattern follows standard 5-field syntax (minute hour day-of-month month day-of-week). The default 0 3 * * * runs the task daily at 3:00 AM. The task is skipped entirely if the global scheduler is disabled (ENABLE_SCHEDULER=false).
For the lifecycle of workspace.validation itself, see Stateful Validation Tracking.
ADM_LOG_LEVEL
Read by the @mitre-attack/attack-data-model library directly — not a Convict-managed setting and not configurable via JSON_CONFIG_PATH. It controls the verbosity of the ADM library's own logger, which is independent of the Workbench LOG_LEVEL.
This was introduced primarily to suppress the deprecation warning that the ADM emits for every relationship in the database during a re-validation run. Setting ADM_LOG_LEVEL=error (or silent) keeps the scheduled task quiet without affecting Workbench's own logs.
| Level | Description |
|---|---|
debug | Verbose diagnostic output |
info | Informational status messages (data retrieval, parse counts, etc.) |
warn | Validation issues in relaxed mode and deprecation warnings |
error | Errors only |
silent | Disables all output |
Levels are inclusive: setting info enables info, warn, and error. The default is warn.
Examples:
# Enable ADM-based request validation
VALIDATE_WITH_ADM_SCHEMAS=true
# Run re-validation hourly instead of daily at 3 AM
VALIDATE_OBJECTS_CRON=0 * * * *
# Suppress noisy ADM deprecation warnings during scheduler runs
ADM_LOG_LEVEL=error
Collection Indexes
Configuration for ATT&CK collection index subscriptions.
| Option | Environment Variable | JSON Path | Type | Default | Description |
|---|---|---|---|---|---|
| Default Interval | DEFAULT_INTERVAL | collectionIndex.defaultInterval | integer | 300 | Default update check interval in seconds |
Notes:
- Only applies to new collection indexes added after configuration change
- Does not affect existing collection indexes (they retain their configured interval)
Configuration Files
Paths to additional configuration and data files.
| Option | Environment Variable | JSON Path | Type | Default | Description |
|---|---|---|---|---|---|
| JSON Config Path | JSON_CONFIG_PATH | configurationFiles.jsonConfigFile | string | (empty) | Path to JSON configuration file |
| Allowed Values Path | ALLOWED_VALUES_PATH | configurationFiles.allowedValues | string | ./app/config/allowed-values.json | Path to allowed values configuration |
| Static Marking Definitions Path | WB_REST_STATIC_MARKING_DEFS_PATH | configurationFiles.staticMarkingDefinitionsPath | string | ./app/lib/default-static-marking-definitions/ | Directory containing static marking definitions |
Allowed Values:
The allowed values file defines valid enum values for STIX object properties (platforms, permissions, etc.).
See app/config/allowed-values.json for the schema.
Static Marking Definitions:
Directory containing JSON files with STIX marking definitions that are automatically loaded into the system on startup.
ATT&CK Specific
ATT&CK-specific configuration values.
| Option | Environment Variable | JSON Path | Type | Default | Description |
|---|---|---|---|---|---|
| Attack Source Names | (JSON only) | attackSourceNames | array | See below | Valid source_name values in ATT&CK external_references |
| Domain to Kill Chain Map | (JSON only) | domainToKillChainMap | object | See below | Maps domain names to kill chain phase names |
Default Attack Source Names:
["mitre-attack", "mitre-mobile-attack", "mobile-attack", "mitre-ics-attack"]
Default Domain to Kill Chain Map:
{
"enterprise-attack": "mitre-attack",
"mobile-attack": "mitre-mobile-attack",
"ics-attack": "mitre-ics-attack"
}