YAML template schema
Applies to .yaml and .yml templates only.
cxg deserializes the document with serde. It does not read comments, so an
@id: annotation header in a YAML file does nothing — see
Annotation header schema.
Root keys
Section titled “Root keys”Metadata keys sit at the root of the document, beside the request sections.
| Key | Type | Required | Absent → |
|---|---|---|---|
id |
string | yes | — |
name |
string | yes | — |
author |
author object |
yes | — |
severity |
severity | yes | — |
description |
string | yes | — |
cve_ids |
list of string | no | empty list |
cwe_ids |
list of string | no | empty list |
cvss_score |
number | no | unset |
tags |
list of string | no | empty list |
language |
language | yes | — |
file_path |
string (path) | no | empty string |
created |
string (RFC 3339 timestamp) | no | Utc::now at load time |
updated |
string (RFC 3339 timestamp) | no | Utc::now at load time |
version |
string | no | 1.0 |
confidence |
integer | no | unset |
context_vars |
list of string | no | empty list |
vuln_class |
string | no | unset |
hypothesis_tags |
list of string | no | empty list |
batch_group |
string | no | unset |
auto_probe |
boolean | no | false |
http |
list of http entry |
no | unset |
network |
list of network entry |
no | unset |
matchers |
list of matcher | no | unset |
matchers-condition |
and / or |
no | unset |
flows |
list of flow | no | unset |
Loaded by the pinned binary, from a template carrying keys this schema does not define:
$ cxg --disable-update-check --no-color template info schema-fixture-unknown-keys[INF] Auto-update checks disabled
╔════════════════════════════════════════════════════════════════╗║ Template Information ║╚════════════════════════════════════════════════════════════════╝
ID: schema-fixture-unknown-keys Name: Schema fixture Language: Yaml Severity: Info Author: docs.bugb.io generator Description: Carries keys this schema does not define, and an annotation header.What a missing required key does
Section titled “What a missing required key does”The template does not load, and at default verbosity nothing says so —
it is absent from the library and from every scan. -v reports the reason.
Loaded by the pinned binary, from one fixture per required key — each omitting exactly that key — plus the malformed fixtures the sections below refer to:
$ cxg --disable-update-check --no-color -v template listINFO cert_x_gen::template::manager: Discovered 11 templatesWARN cert_x_gen::template::engine: Failed to load template ./templates/author-as-string.yaml: YAML parse error: invalid type: string "docs.bugb.io generator", expected struct AuthorInfoWARN cert_x_gen::template::engine: Failed to load template ./templates/missing-author.yaml: YAML parse error: missing field `author`WARN cert_x_gen::template::engine: Failed to load template ./templates/missing-description.yaml: YAML parse error: missing field `description`WARN cert_x_gen::template::engine: Failed to load template ./templates/missing-id.yaml: YAML parse error: missing field `id`WARN cert_x_gen::template::engine: Failed to load template ./templates/missing-language.yaml: YAML parse error: missing field `language`WARN cert_x_gen::template::engine: Failed to load template ./templates/missing-name.yaml: YAML parse error: missing field `name`WARN cert_x_gen::template::engine: Failed to load template ./templates/missing-severity.yaml: YAML parse error: missing field `severity`WARN cert_x_gen::template::engine: Failed to load template ./templates/time-as-scalar.yaml: YAML parse error: http[0].matchers: invalid type: integer `5`, expected struct Duration at line 11 column 7WARN cert_x_gen::template::engine: Failed to load template ./templates/unknown-matcher-type.yaml: YAML parse error: http[0].matchers[0].type: unknown variant `dsl`, expected one of `status`, `word`, `regex`, `binary`, `time`, `size`, `hash`, `tls`, `dns`, `diff`, `custom` at line 11 column 15WARN cert_x_gen::template::engine: Failed to load template ./templates/unknown-severity.yaml: YAML parse error: unknown variant `catastrophic`, expected one of `info`, `low`, `medium`, `high`, `critical`INFO cert_x_gen::core: Loaded 1 templates from ./templatesThose are the loader’s own lines out of a longer output — template list
also prints every template that did load. Each Failed to load line is
serde’s error for one fixture. Three things are done to those lines and
nothing else: the timestamp and thread id that prefix each one are removed,
the failures are sorted by filename, and the lines about the unrelated
template directory under $HOME are left out.
Asking for a template that failed to load says only that it does not exist:
$ cxg --disable-update-check --no-color template info schema-fixture-missing-author[INF] Auto-update checks disabled❌ No template found matching: schema-fixture-missing-author
Try: cxg search --query "schema-fixture-missing-author"author
Section titled “author”author is an object, not a string:
author: name: CERT-X-GEN Security Team email: security@example.com| Key | Type | Required |
|---|---|---|
name |
string | yes |
email |
string | no |
github |
string | no |
author: Some Name is the most common way a template written for another
scanner stops loading here, and the loader says so only under -v:
Failed to load template ./templates/author-as-string.yaml: YAML parse error: invalid type: string "docs.bugb.io generator", expected struct AuthorInfoseverity
Section titled “severity”One of info, low, medium, high, critical.
Unlike the annotation header — where an unrecognised severity silently
becomes Medium — an unrecognised value here fails the load:
Failed to load template ./templates/unknown-severity.yaml: YAML parse error: unknown variant `catastrophic`, expected one of `info`, `low`, `medium`, `high`, `critical`language
Section titled “language”One of yaml, python, rust, shell, javascript, c, cpp, java, go, ruby, perl, php. Required, and it is metadata: it does not change which
engine loads the file, which is decided by the file extension.
HTTP request specification
| Key | Type | Required | Absent → |
|---|---|---|---|
method |
string | no | GET |
path |
list of string | no | unset |
headers |
map of string to string | no | empty map |
body |
string | no | unset |
matchers |
list of matcher | no | unset |
matchers-condition |
and / or |
no | unset |
Only GET and POST are sent; any other method is skipped with a warning.
A request with no path is sent to /.
network
Section titled “network”Network/TCP request specification
| Key | Type | Required | Absent → |
|---|---|---|---|
protocol |
string | no | tcp |
port |
integer | yes | — |
payloads |
list of string | no | empty list |
matchers |
list of matcher | no | unset |
matchers-condition |
and / or |
no | unset |
Escape sequences \r\n, \n, \r and \t in a payload are
interpreted before it is written to the socket.
matchers
Section titled “matchers”A list of matchers, each identified by its type key. Matchers may sit at
the root of the template or inside an http or network entry; an entry’s
own matchers win over the template’s.
The set is closed — these 11 types and nothing else:
$ cxg --disable-update-check --no-color -v template listWARN cert_x_gen::template::engine: Failed to load template ./templates/unknown-matcher-type.yaml: YAML parse error: http[0].matchers[0].type: unknown variant `dsl`, expected one of `status`, `word`, `regex`, `binary`, `time`, `size`, `hash`, `tls`, `dns`, `diff`, `custom` at line 11 column 15That is the engine listing them itself, from a fixture using a type it does not have.
type: status
Section titled “type: status”Status code matcher
| Key | Type | Required | Absent → |
|---|---|---|---|
status |
list of integer | yes | — |
type: word
Section titled “type: word”Word matcher
| Key | Type | Required | Absent → |
|---|---|---|---|
words |
list of string | yes | — |
condition |
and / or |
no | or |
part |
response part | no | body |
type: regex
Section titled “type: regex”Regex matcher
| Key | Type | Required | Absent → |
|---|---|---|---|
regex |
list of string | yes | — |
group |
integer | no | unset |
type: binary
Section titled “type: binary”Binary matcher
| Key | Type | Required | Absent → |
|---|---|---|---|
binary |
list of string | yes | — |
type: time
Section titled “type: time”Time-based matcher
| Key | Type | Required | Absent → |
|---|---|---|---|
condition |
time condition | yes | — |
time |
{secs: <integer>, nanos: <integer>} |
yes | — |
A duration is a map, not a number of seconds:
- type: time condition: greater time: {secs: 5, nanos: 0}time: 5 does not load:
Failed to load template ./templates/time-as-scalar.yaml: YAML parse error: http[0].matchers: invalid type: integer `5`, expected struct Duration at line 11 column 7type: size
Section titled “type: size”Size matcher
| Key | Type | Required | Absent → |
|---|---|---|---|
condition |
size condition | yes | — |
size |
integer | yes | — |
type: hash
Section titled “type: hash”Hash matcher
| Key | Type | Required | Absent → |
|---|---|---|---|
algorithm |
hash algorithm | yes | — |
hash |
string | yes | — |
type: tls
Section titled “type: tls”TLS/SSL matcher
| Key | Type | Required | Absent → |
|---|---|---|---|
versions |
list of string | no | unset |
ciphers |
list of string | no | unset |
vulnerabilities |
list of string | no | unset |
type: dns
Section titled “type: dns”DNS matcher
| Key | Type | Required | Absent → |
|---|---|---|---|
record_type |
string | yes | — |
pattern |
string | no | unset |
value |
string | no | unset |
type: diff
Section titled “type: diff”Diff matcher (compare with baseline)
| Key | Type | Required | Absent → |
|---|---|---|---|
baseline |
string | yes | — |
threshold |
integer | yes | — |
type: custom
Section titled “type: custom”Custom matcher (code-based)
| Key | Type | Required | Absent → |
|---|---|---|---|
language |
string | yes | — |
code |
string | yes | — |
MatchCondition
Section titled “MatchCondition”Match condition
| Value | Meaning |
|---|---|
and |
All matchers must match |
or |
At least one matcher must match |
ResponsePart
Section titled “ResponsePart”Response part to match against
| Value | Meaning |
|---|---|
body |
Match against response body |
header |
Match against response headers |
all |
Match against entire response |
data |
Match against raw data (for network protocols) |
TimeCondition
Section titled “TimeCondition”Time-based condition
| Value | Meaning |
|---|---|
greater |
Greater than threshold |
less |
Less than threshold |
SizeCondition
Section titled “SizeCondition”Size-based condition
| Value | Meaning |
|---|---|
greater |
Greater than threshold |
less |
Less than threshold |
equal |
Equal to threshold |
HashAlgorithm
Section titled “HashAlgorithm”Hash algorithms
| Value | Meaning |
|---|---|
md5 |
MD5 hash |
sha1 |
SHA1 hash |
sha256 |
SHA256 hash |
sha512 |
SHA512 hash |
blake3 |
Blake3 hash |
Flow definition
| Key | Type | Required | Absent → |
|---|---|---|---|
name |
string | yes | — |
steps |
list of flow step | yes | — |
depends_on |
list of string | no | empty list |
condition |
string | no | unset |
optional |
boolean | no | false |
description |
string | no | unset |
Flow steps
Section titled “Flow steps”Each step is identified by its action key.
action: http_request
Section titled “action: http_request”HTTP request
| Key | Type | Required | Absent → |
|---|---|---|---|
method |
string | yes | — |
path |
string | yes | — |
headers |
map of string to string | no | empty map |
body |
string | no | unset |
store |
string | no | unset |
action: set_variable
Section titled “action: set_variable”Set variable
| Key | Type | Required | Absent → |
|---|---|---|---|
name |
string | yes | — |
value |
string | yes | — |
action: extract
Section titled “action: extract”Extract from response
| Key | Type | Required | Absent → |
|---|---|---|---|
from |
string | yes | — |
pattern |
string | yes | — |
store |
string | yes | — |
action: check
Section titled “action: check”Check condition
| Key | Type | Required | Absent → |
|---|---|---|---|
condition |
string | yes | — |
message |
string | no | unset |
action: wait
Section titled “action: wait”Wait/sleep
| Key | Type | Required | Absent → |
|---|---|---|---|
duration_ms |
integer | yes | — |
What the engine requires of a loaded template
Section titled “What the engine requires of a loaded template”Checked after the document deserializes, when the template is validated:
Template must have either 'http', 'network', or 'flows' definedSource
Section titled “Source”Deserialized by src/engine/yaml/mod.rs, over the types in
src/types.rs,
src/matcher.rs and
src/flows.rs, at v1.3.0.

