vNext DSL 核心语法规范
TestNet 统一采用 vNext DSL (Domain Specific Language) 作为安全工具箱与自动化工作流的标准化表达格式。vNext 精简为两大核心类型:kind: Tool (单体工具规范) 与 kind: Workflow (多工具 DAG 编排规范)。
一、 DSL 总体设计理念
- 类型隔离与统一注册:所有 DSL 文件必须在顶层声明
kind: Tool或kind: Workflow; - 零显式节点连线:通过
dependsOn控制执行顺序,通过inputs.*.from自动建立任务间参数传递的数据流; - 动态表达式引擎:内置 Aviator 表达式引擎,在步骤参数或条件判断(
when)中支持如size(outputs) > 0等灵活的高级表达式。
二、 工具规范语法
kind: Tool 描述了一个安全扫描或数据处理工具在分布式节点上的运行方式与输入输出映射。
完整 Tool Spec 示例
yaml
kind: Tool
metadata:
id: subfinder
name: Subfinder
version: 1.0.0
description: 被动子域名发现工具
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核心结构说明
| 层级 | 字段 | 说明 |
|---|---|---|
| 顶层 | kind: Tool | 固定标识为工具类型 |
| 顶层 | metadata | 元数据:id(唯一标识)、name、version(语义化版本) |
| 顶层 | spec | 工具规格定义(见下表) |
| Spec 字段 | 说明 |
|---|---|
spec.inputs | 输入通道:定义工具接收的资产类型及数据解析规则,支持 batch 批量处理模式 |
spec.params | 运行时参数:支持 STRING/INTEGER/NUMBER/BOOLEAN/ARRAY/OBJECT 类型,可设置默认值和校验范围 |
spec.runtime | 执行引擎:定义 type(DOCKER/HTTP/DNS/TCP)及各引擎特有配置 |
spec.outputs | 输出通道:定义资产类型映射与解析器,支持 LINE/JSON/JSONL/REGEX/FILE/CSV/XML 7 种解析器 |
执行引擎类型 (runtime.type)
| 类型 | 说明 | 配置字段 |
|---|---|---|
DOCKER | Docker 容器执行 | docker.image、docker.args、docker.network 等 |
HTTP | HTTP 探针 | http.url、http.method、http.headers |
DNS | DNS 查询探针 | dns.domain、dns.recordType |
TCP | TCP 端口探测 | tcp.host、tcp.port、tcp.data |
NOTE
vNext DSL 不提供 SHELL 运行时;本地命令行类工具(PROCESS 类型)属于旧版 ExecutionSpec 概念,vNext 中请改用 DOCKER 或原生 HTTP/DNS/TCP 执行器。Schema 中另保留 HTTP_PROBE(httpProbe.url)作为早期 HTTP 探针类型的兼容别名。
占位符与变量引用规范
在 Tool Spec 的各个配置段中,占位符语法采用双花括号 {{...}},遵循严格的命名空间规范:
| 命名空间 | 格式 | 适用位置 | 说明 |
|---|---|---|---|
| 输入通道 | {{input.<channel>}}(或别名 {{inputs.<channel>}}) | runtime.docker.args、runtime.http.url、runtime.tcp.host、runtime.env 等 | 引用 spec.inputs 中声明的输入通道数据(经资产解析或上游传递的值) |
| 工具参数 | {{params.<param>}} | runtime.* 配置中的任意参数字段 | 引用 spec.params 中声明的参数值(支持默认值与用户传参) |
| 资产属性 | {{asset.<field>}} | spec.inputs.<channel>.resolve 及 runtime.* | 在输入解析中映射资产字段;在单资产直接运行模式下亦可兜底引用资产属性(如 {{asset.domain}}、{{asset.ip}}) |
| 密钥引用 | {{secret.<key>}} | runtime.* 配置中的任意参数字段 | 引用平台密钥/敏感配置项(如 API Key),避免在 DSL 中明文书写凭据 |
占位符严格校验机制
- 编译期静态拦截:保存/校验 Tool DSL 时,平台将静态提取
runtime配置中所有的占位符。若引用的通道未在spec.inputs声明、参数未在spec.params声明,或命名空间无法识别,平台将直接报错拦截,拒绝非法 DSL。 - 运行时契约校验:构建任务执行 Spec 时,若运行时占位符无法解析(如输入通道为空或参数未传入),平台将立即抛出异常阻断执行,严禁静默替换为空字符串导致命令行参数错位或报错。
三、 工作流编排规范
kind: Workflow 将多个独立工具通过依赖关系组合为一个高可靠的 DAG 工作流。
Workflow Spec 精简示例
yaml
kind: Workflow
metadata:
id: domain-recon-pipeline
name: Domain Recon Pipeline
version: 1.0.0
spec:
trigger:
type: MANUAL
enabled: true
input:
assetTypes: [DOMAIN]
nodes:
subfinder:
tool: subfinder
inputs:
target:
from: [trigger.asset]
params:
threads: 20
timeoutSeconds: 600
httpx_probe:
tool: httpx
inputs:
target:
from: [subfinder.outputs.subdomain]
dependsOn:
nodes: [subfinder]
policy: ALL_SUCCESS
timeoutSeconds: 900
outputs:
web:
from: [httpx_probe.outputs.web]
policy:
errorStrategy: CONTINUE
maxConcurrency: 5
timeoutSeconds: 1800核心结构说明
| 字段 | 说明 |
|---|---|
metadata | 元数据:id、name、version、description |
spec.trigger | 触发配置:type 支持 MANUAL/CRON/AUTO,cron 表达式(CRON 类型时);AUTO 表示资产事件联动自动触发(新资产发现时自动执行) |
spec.nodes | DAG 节点集合:每个节点声明调用的 tool、输入绑定 inputs.*.from、依赖关系 dependsOn |
spec.outputs | 工作流输出声明:汇总各节点的输出通道 |
spec.policy | 执行策略:errorStrategy(STOP(默认)/CONTINUE/SKIP_NODE/RETRY_NODE)、maxConcurrency、timeoutSeconds、maxRetries |
节点依赖 (dependsOn)
| 字段 | 说明 |
|---|---|
dependsOn.nodes | 依赖的前置节点 ID 列表 |
dependsOn.policy | 依赖策略:ALL_SUCCESS(默认,全部成功才执行)、ALL_DONE(全部结束即执行)、ANY_SUCCESS(任一成功即执行)、ANY_DONE(任一结束即执行)、EXPRESSION(配合 dependsOn.expression 自定义 Aviator 表达式判定) |
输入绑定 (inputs.*.from)
| 来源 | 语法 | 说明 |
|---|---|---|
| 触发输入 | trigger.asset | 引用工作流触发时传入的资产 |
| 节点输出 | {nodeId}.outputs.{channel} | 引用上游节点的输出通道 |
条件执行 (when)
节点支持通过 Aviator 表达式进行条件执行:
yaml
nodes:
nuclei_scan:
tool: nuclei
dependsOn:
nodes: [httpx_probe]
policy: ALL_SUCCESS
when: 'size(httpx_probe.outputs.web) > 0'节点还可声明 skipOnNoInput: true:当输入解析不到任何资产时优雅跳过该节点(而非判定失败)。
TIP
欲学习如何在本地 testnet-registry 仓库中进行多版本化 DSL 存储与自定义 Registry 商店发布,请参考:testnet-registry 仓库 README。