Skip to content

Variable replacement

Step commands are templates. Before a task runs, Sonar substitutes named variables into the command and file paths — turning subfinder -d {PARAM.domain} into a concrete command for one target. This page is the canonical reference for every variable the engine understands.

The essentials

  • {OUTPUT} / {OUTPUT_FILE} — where this step writes its result (stdout / a file).
  • {INPUT_UPSTREAM} / {INPUT_FILE_UPSTREAM} — the upstream step's output, fed into a Single-dependency child.
  • {INPUT_FILE_SQL} — a CSV/JSON file materialized from the step's inputSql query.
  • {PARAM.x} — a declared parameter (visible targeting value). {SECRETS.x} — a masked secret, only ever substituted into the command.
  • {scanId} / {taskId} / {random} — run/task identifiers, handy for unique paths.
  • {PHASE_STARTED_AT} — the current recency-phase cutoff, bound into a step's inputSql so a query only pulls recently-updated rows.

Expansion

Two special inputs turn one step into many tasks:

  • {INPUT_PATH_EXPAND} — one child task per file in a MinIO directory.
  • {INPUT_FILE_EXPAND} — one child task per line in a file.

This is how a single crawl result fans out into thousands of parallel probes.

Full reference (from the repo)

The section below is the raw engineering reference, included verbatim from the repo so it never drifts. It's written for implementers, so expect a lower-level tone and some legacy shorthand — e.g. it may write {INPUT} / {INPUT_FILE} where the current engine uses the fuller {INPUT_UPSTREAM} / {INPUT_FILE_UPSTREAM} names above. When in doubt, the names in the sections above this line are canonical.

Current Behavior

The system already supports multiple instances of the same variable in a command. All occurrences are replaced with the same value.

Example 1: Multiple {OUTPUT_FILE} instances

json
{
  "command": "subfinder -d example.com -o {OUTPUT_FILE} && httpx -l {OUTPUT_FILE} -o {OUTPUT_FILE}.json",
  "variables": {
    "OUTPUT_FILE": "/scan-results/123/subdomains.txt"
  }
}

Result:

bash
subfinder -d example.com -o /scan-results/123/subdomains.txt && httpx -l /scan-results/123/subdomains.txt -o /scan-results/123/subdomains.txt.json

All three {OUTPUT_FILE} instances are replaced with the same value.

Example 2: Multiple {INPUT_FILE} instances

json
{
  "command": "cat {INPUT_FILE} | grep test > {OUTPUT_FILE} && cp {INPUT_FILE} {OUTPUT_FILE}.bak",
  "variables": {
    "INPUT_FILE": "/scan-results/123/input.txt",
    "OUTPUT_FILE": "/scan-results/123/output.txt"
  }
}

Result:

bash
cat /scan-results/123/input.txt | grep test > /scan-results/123/output.txt && cp /scan-results/123/input.txt /scan-results/123/output.txt.bak

Using Different Values for Multiple Instances

If you need different values for multiple instances, use numbered variables:

Example: Multiple Input Files

json
{
  "command": "cat {INPUT_FILE_1} {INPUT_FILE_2} > {OUTPUT_FILE}",
  "variables": {
    "INPUT_FILE_1": "/scan-results/123/subdomains.txt",
    "INPUT_FILE_2": "/scan-results/123/ips.txt",
    "OUTPUT_FILE": "/scan-results/123/combined.txt"
  }
}

Result:

bash
cat /scan-results/123/subdomains.txt /scan-results/123/ips.txt > /scan-results/123/combined.txt

Example: Multiple Output Files

json
{
  "command": "subfinder -d {INPUT} -o {OUTPUT_FILE_1} && httpx -l {OUTPUT_FILE_1} -o {OUTPUT_FILE_2}",
  "variables": {
    "INPUT": "example.com",
    "OUTPUT_FILE_1": "/scan-results/123/subdomains.txt",
    "OUTPUT_FILE_2": "/scan-results/123/httpx_results.json"
  }
}

Result:

bash
subfinder -d example.com -o /scan-results/123/subdomains.txt && httpx -l /scan-results/123/subdomains.txt -o /scan-results/123/httpx_results.json

Special Variables

{INPUT_FILE} and {OUTPUT_FILE}

These have special handling:

  • {OUTPUT_FILE}: Automatically creates the directory structure and uploads the file to MinIO after execution
  • {INPUT_FILE}: Automatically downloads the file from MinIO before execution

Note: If you use numbered variants like {INPUT_FILE_1}, {INPUT_FILE_2}, they are treated as regular variables (no automatic MinIO download/upload).

Example: Using Special Variables with Regular Variables

json
{
  "command": "subfinder -d {INPUT} -o {OUTPUT_FILE} && cat {OUTPUT_FILE} | httpx -o {OUTPUT_FILE_2}",
  "variables": {
    "INPUT": "example.com",
    "OUTPUT_FILE": "/scan-results/123/subdomains.txt",
    "OUTPUT_FILE_2": "/scan-results/123/httpx_results.json"
  }
}

In this case:

  • {OUTPUT_FILE} will be automatically uploaded to MinIO after execution
  • {OUTPUT_FILE_2} is a regular variable (no automatic upload)

Best Practices

  1. Use the same variable name if you want the same value in multiple places
  2. Use numbered variables ({INPUT_FILE_1}, {INPUT_FILE_2}) if you need different values
  3. Use {OUTPUT_FILE} for the primary output file that should be uploaded to MinIO
  4. Use numbered variants for secondary outputs that don't need MinIO upload

Implementation Details

The replacement uses a global regex pattern:

typescript
command.replace(new RegExp(`\\{${key}\\}`, 'g'), value)

The 'g' flag ensures all occurrences are replaced.