Skip to main content

Configuration

BlackRainbow engagements are defined in YAML config files. The config is parsed by load_config() and validated by 7 Pydantic models. Every field is type-checked at load time.

Config File

Default filename: blackrainbow.yaml. Override with br run --config <path>.

Generate from a template:

br init --template htb         # Creates blackrainbow.yaml
br init --template webapp # Web application template

Complete Example

target:
type: network-service
host: 10.10.10.5
label: htb-example
port: 80
protocol: tcp
url: http://10.10.10.5
scope:
networks:
- 10.10.10.0/24
exclude:
- 10.10.10.1

engagement:
purpose: |
Full compromise of target host. Obtain root-level access.
Capture user.txt and root.txt flags as proof.
rules:
- No denial of service
- No data destruction
- No attacking out-of-scope hosts
operator: pitl0rd

plugins:
- recon
- id: credential-access
numTests: 10
severity: high
config:
wordlist: /usr/share/wordlists/rockyou.txt

strategies:
- sequential

model:
provider: ollama
model: blackrainbow-v0
host: http://localhost:11434
temperature: 0.3

output:
report: ./reports/
capture: ./captures/
format: markdown
training_export: true

Top-Level Keys

KeyTypeRequiredDescription
targetObjectYesTarget definition
engagementObjectYesEngagement metadata
pluginsListNoPlugin references
strategiesListNoStrategy IDs
frameworksListNoFramework references (e.g., MITRE ATT&CK)
modelObjectNoAI model configuration
outputObjectNoOutput and capture settings

Pydantic Models

Seven models validate the config. All use strict type checking.

BlackRainbowConfig

The root model. Contains all other models.

class BlackRainbowConfig(BaseModel):
target: TargetConfig
engagement: EngagementConfig
plugins: List[PluginRefConfig] = []
strategies: List[str] = []
frameworks: List[str] = []
model: Optional[ModelConfig] = None
output: OutputConfig = Field(default_factory=OutputConfig)

TargetConfig

FieldTypeDefaultDescription
typestr"network-service"Target type (validated against allowed set)
hoststr(required)Target hostname or IP
labelstrNoneHuman-readable label for reports
portintNoneSpecific port
protocolstrNoneProtocol (e.g., tcp, udp)
urlstrNoneFull URL (for web targets)
scopeScopeConfig{}Network scope constraints

Allowed type values:

  • network-service
  • web-application
  • active-directory
  • cloud-service
  • ai-system
  • ninjato
  • custom

ScopeConfig

FieldTypeDefaultDescription
networksList[str][]In-scope CIDRs
excludeList[str][]Excluded hosts/CIDRs

EngagementConfig

FieldTypeDefaultDescription
purposestr(required)Engagement objective
rulesList[str][]Rules of engagement
operatorstr"unknown"Operator name

PluginRefConfig

Supports two forms in YAML. Both are normalized to the same model at parse time.

Short form (string):

plugins:
- recon

Normalizes to {"id": "recon"}.

Long form (dict):

plugins:
- id: recon
numTests: 10
severity: high
config:
scan_type: full
FieldTypeDefaultDescription
idstr(required)Plugin ID from registry
numTestsint5Number of test sequences to generate
severitystr"medium"Minimum severity level
configDict[str, Any]{}Plugin-specific configuration

File references are also accepted as IDs:

plugins:
- file://./my-plugin.py

ModelConfig

FieldTypeDefaultDescription
providerstr"ollama"Model provider
modelstr"blackrainbow-v0"Model name
hoststr"http://localhost:11434"Provider API endpoint
temperaturefloat0.3Inference temperature

OutputConfig

FieldTypeDefaultDescription
reportstr"./reports/"Report output directory
capturestr"./captures/"Capture output directory
formatstr"markdown"Output format (validated)
training_exportbooltrueExport results as training data

Allowed format values:

  • markdown
  • json
  • html
  • pdf

Template System

Templates live in templates/ at the repo root. The br init command copies a template to the working directory.

htb.yaml

HackTheBox / CTF template. Target type network-service. Includes scope for 10.10.10.0/24, recon plugin, and Ollama model config. All target-specific fields use CHANGEME placeholders.

webapp.yaml

Web application assessment template. Target type web-application. Includes a url field, recon plugin, and a web-exploit plugin reference (long form with severity override). Rules include restrictions on automated credential stuffing.

Adding Templates

Create a new YAML file in templates/:

# templates/ad.yaml
target:
type: active-directory
host: CHANGEME
label: ad-TARGET
scope:
networks:
- CHANGEME/24
exclude: []

engagement:
purpose: |
Active Directory domain compromise assessment.
Demonstrate full kill chain from initial access to domain admin.
rules:
- No denial of service
- No data destruction
operator: CHANGEME

plugins:
- recon
- id: credential-access
severity: high

strategies: []

output:
report: ./reports/
capture: ./captures/
format: markdown
training_export: true

Then add the template name to the --template Click choice in cli.py:

@click.option(
"--template",
type=click.Choice(["htb", "webapp", "ad"]),
default="htb",
)

Config Loading

load_config(path) handles the full parse chain:

  1. Read the YAML file.
  2. Validate it is a non-empty mapping.
  3. Normalize plugin references (string to dict).
  4. Construct and return BlackRainbowConfig (Pydantic validates all fields).

Errors:

  • FileNotFoundError: config file does not exist.
  • ValueError: YAML is empty, not a mapping, or fails Pydantic validation.

Config to Context

config_to_context(config) converts a validated config into an EngagementContext for plugin consumption:

EngagementContext(
target=config.target.model_dump(),
purpose=config.engagement.purpose,
scope=config.target.scope.model_dump(),
strategies=[s for s in config.strategies],
)

This is the bridge between static config and runtime state. The engine adds previous_results, discovered_services, credentials, and model as the engagement progresses.