Skip to content

DSL Reference ​

TestNet standardizes all security tools and automated pipelines using vNext DSL (Domain Specific Language). Built around YAML, vNext eliminates legacy boilerplate edge definitions and separates definitions into two concise types: kind: Tool (atomic tool specification) and kind: Workflow (multi-step DAG pipeline).


1. Core Architectural Principles ​

  1. Type Isolation & Unified Registry: Every DSL file must explicitly declare kind: Tool or kind: Workflow at the root;
  2. No Explicit Edges: DAG topology is determined naturally via dependsOn declarations and data-flow parameter mapping (inputs.*.from);
  3. Dynamic Expression Engine: Supports real-time Aviator expression evaluation in step parameters or conditional branches (when) (e.g., size(outputs) > 0).

2. Tool Specification (ToolSpec) ​

kind: Tool defines how a security utility or Docker container executes on remote Go nodes and how its raw output is parsed into structured data.

Complete ToolSpec Example ​

yaml
kind: Tool
metadata:
  id: subfinder
  name: Subfinder
  version: 1.0.0
  description: Passive subdomain discovery engine
  category: recon
  tags:
    - subdomain
    - dns
spec:
  inputs:
    target:
      required: true
      accepts: [DOMAIN]
      resolve:
        DOMAIN: '{{asset.domain}}'
      batch:
        enabled: true
        mode: FILE
        argName: -dL
        size: 50
  params:
    threads:
      type: INTEGER
      defaultValue: 10
      min: 1
      max: 100
    recursive:
      type: BOOLEAN
      defaultValue: false
  runtime:
    type: DOCKER
    timeoutSeconds: 300
    docker:
      image:
        default: projectdiscovery/subfinder:latest
      network: host
      args:
        - -silent
        - -t
        - '{{params.threads}}'
        - -d
        - '{{input.target}}'
        - -o
        - /tmp/output.json
        - -json
  outputs:
    subdomain:
      assetType: SUBDOMAIN
      parser:
        type: JSONL
      map:
        subdomain: $.host
        source: $.source
      identity:
        field: subdomain

Core Structure Reference ​

LevelFieldDescription
Topkind: ToolFixed type identifier
TopmetadataMetadata: id, name, version (semver)
TopspecTool specification (see below)
Spec FieldDescription
spec.inputsInput channels: defines accepted asset types and data resolution rules, supports batch mode
spec.paramsRuntime parameters: supports STRING/INTEGER/NUMBER/BOOLEAN/ARRAY/OBJECT types with defaults and validation
spec.runtimeExecution engine: defines type (DOCKER/HTTP/DNS/TCP) and engine-specific config
spec.outputsOutput channels: defines asset type mapping and parser (LINE/JSON/JSONL/REGEX/FILE/CSV/XML)

Engine Types (runtime.type) ​

TypeDescriptionConfig Fields
DOCKERDocker container executiondocker.image, docker.args, docker.network
HTTPHTTP probehttp.url, http.method, http.headers
DNSDNS query probedns.domain, dns.recordType
TCPTCP port probetcp.host, tcp.port, tcp.data

NOTE

The vNext DSL does not provide a SHELL runtime. The schema keeps HTTP_PROBE (httpProbe.url) only as a legacy alias of the HTTP probe type.

Placeholders & Variable Resolution ​

All placeholder expressions within Tool Spec use double curly braces {{...}} under strict namespaces:

NamespaceFormatAllowed InDescription
Input Channels{{input.<channel>}} (or alias {{inputs.<channel>}})runtime.docker.args, runtime.http.url, runtime.tcp.host, runtime.env, etc.References data from channels declared in spec.inputs (resolved from assets or upstream nodes)
Parameters{{params.<param>}}Any runtime configuration fieldsReferences parameter values declared in spec.params (defaults or caller overrides)
Asset Properties{{asset.<field>}}spec.inputs.<channel>.resolve and runtime.*Maps asset properties in input resolve templates; also provides direct fallback when executing on single assets (e.g. {{asset.domain}}, {{asset.ip}})
Secret References{{secret.<key>}}Any runtime configuration fieldsReferences platform-managed secrets (e.g. API keys) so credentials never appear in plain text inside the DSL

Strict Placeholder Enforcement

  1. Compile-time Static Validation: When saving or validating a Tool DSL, the system statically scans all runtime placeholders. Any reference to undeclared inputs/params or unknown namespaces is rejected immediately with a compilation error.
  2. Runtime Contract Enforcement: When constructing task execution specifications, any unresolvable placeholder (e.g. missing target value or unset required parameter) immediately raises an exception, preventing silent drops that cause corrupted CLI flags.

3. Workflow Specification (WorkflowSpec) ​

kind: Workflow chains multiple independent tools into an enterprise-grade Directed Acyclic Graph (DAG).

Complete WorkflowSpec Example ​

yaml
kind: Workflow
metadata:
  id: domain-recon-pipeline
  name: Domain Recon Pipeline
  version: 1.0.0
  description: "Domain reconnaissance pipeline: discover subdomains and probe web services"
  tags:
    - recon
    - subdomain
    - web
spec:
  trigger:
    type: MANUAL
    enabled: true
    input:
      assetTypes: [DOMAIN]
  nodes:
    subfinder:
      tool: subfinder
      inputs:
        target:
          from:
            - trigger.asset
      params:
        threads: 20
        recursive: true
      timeoutSeconds: 600
      skipOnNoInput: true
    httpx_probe:
      tool: httpx
      inputs:
        target:
          from:
            - subfinder.outputs.subdomain
      dependsOn:
        nodes: [subfinder]
        policy: ALL_SUCCESS
      params:
        followRedirects: true
        threads: 50
      timeoutSeconds: 900
      skipOnNoInput: true
  outputs:
    subdomain:
      from: [subfinder.outputs.subdomain]
    web:
      from: [httpx_probe.outputs.web]
  policy:
    errorStrategy: CONTINUE
    maxConcurrency: 5
    timeoutSeconds: 1800
    maxRetries: 2

Core Structure ​

FieldDescription
metadataMetadata: id, name, version, description, tags
spec.triggerTrigger config: type supports MANUAL/CRON/AUTO; AUTO means asset-event-linked auto-trigger (executes when new assets are discovered)
spec.nodesDAG nodes: each node declares its tool, inputs.*.from bindings, and dependsOn dependencies
spec.outputsWorkflow output declarations: aggregates node output channels
spec.policyExecution policy: errorStrategy, maxConcurrency, timeoutSeconds, maxRetries

Node Dependency (dependsOn) ​

FieldDescription
dependsOn.nodesList of upstream node IDs
dependsOn.policyStrategy: ALL_SUCCESS (default, all must succeed), ALL_DONE (run when all finish), ANY_SUCCESS (run when any succeeds), ANY_DONE (run when any finishes), EXPRESSION (custom Aviator expression via dependsOn.expression)

Input Binding (inputs.*.from) ​

SourceSyntaxDescription
Trigger inputtrigger.assetReferences the asset passed to the workflow trigger
Node output{nodeId}.outputs.{channel}References an output channel of an upstream node

Conditional Execution (when) ​

Nodes support Aviator expressions for conditional execution:

yaml
nodes:
  nuclei_scan:
    tool: nuclei
    dependsOn:
      nodes: [httpx_probe]
      policy: ALL_SUCCESS
    when: 'size(httpx_probe.outputs.web) > 0'

A node may also declare skipOnNoInput: true to be skipped gracefully (instead of failing) when its input resolves to zero assets.

TIP

To learn how to maintain versioned DSL files inside your local testnet-registry store and publish custom tools, refer to the testnet-registry README.


最近更新

Released under the MIT License