Skip to content

Template Structure

Recep Gunes edited this page May 17, 2026 · 6 revisions

Every template in vt-templates lives in its own directory and contains two files.


Directory Layout

vt-templates/
├── labs/
│   └── vt-dvwa/
│       ├── index.yaml           # Template metadata (required)
│       └── docker-compose.yaml  # Container definitions (required for docker-compose provider)
├── cves/
│   └── vt-2025-29927/
│       ├── index.yaml
│       └── docker-compose.yaml
├── benchmarks/
│   └── xbow/
│       └── vt-xbow-001/
│           ├── index.yaml
│           └── docker-compose.yaml
├── http/
│   └── vt-dagu/
│       ├── index.yaml
│       └── docker-compose.yaml
└── playbooks/
    └── vt-pb-0001.yaml

Categories:

Category Description
labs/ Pre-built intentionally vulnerable applications (DVWA, Juice Shop, etc.)
cves/ Isolated environments reproducing specific CVEs
benchmarks/ Security testing benchmark suites (XBow)
http/ HTTP/API-specific vulnerability targets
playbooks/ YAML files grouping multiple templates into a single deployment

index.yaml Format

id: vt-2025-29927                      # required — must be unique across all templates

info:
  name: "Next.js Middleware Bypass"    # required
  author: omarkurt                     # required
  description: |                       # optional
    Detailed multi-line description of the vulnerability,
    how it works, and what makes it interesting.
  targets:                             # required — at least one
    - "web-application"
    - "middleware"
  type: CVE                            # required — Lab | CVE | Benchmark
  affected_versions:                   # optional
    - "11.1.4"
  fixed_version: "15.2.3"             # optional
  cve: "CVE-2025-29927"               # optional
  cwe: "CWE-287"                      # optional
  cvss:                               # optional
    score: "9.1"
    metrics: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N"
  tags:                               # required — at least one
    - "nextjs"
    - "middleware"
    - "auth-bypass"
  references:                         # optional
    - "https://nvd.nist.gov/vuln/detail/CVE-2025-29927"
    - "https://github.com/advisories/GHSA-..."

poc:                                  # optional
  nuclei:                             # Nuclei template files (relative paths)
    - "nuclei_template.yaml"
  semgrep:                            # Semgrep rule files (relative paths)
    - "semgrep_rule.yaml"

remediation:                          # optional
  - "Upgrade Next.js to 15.2.3 or later."
  - "Block the x-middleware-subrequest header at the WAF or reverse proxy."

providers:                            # required — at least one
  docker-compose:
    path: "docker-compose.yaml"

post-install:                         # optional
  - "Access the application at http://localhost:3000"
  - "Default credentials: admin / password"
  - "Run the PoC: nuclei -t nuclei_template.yaml -u http://localhost:3000"

Field Reference

Field Required Description
id Yes Unique ID. Convention: vt-<year>-<cve-number> for CVEs, vt-<name> for labs, vt-xbow-<number> for benchmarks
info.name Yes Human-readable name
info.author Yes GitHub username or team name
info.description No Multi-line description of the target
info.targets Yes At least one target surface (e.g. web-application, api, login-system)
info.type Yes Lab, CVE, or Benchmark
info.affected_versions No Versions where the vulnerability exists
info.fixed_version No Version where the vulnerability was patched
info.cve No CVE identifier (e.g. CVE-2025-29927)
info.cwe No CWE identifier (e.g. CWE-287)
info.cvss.score No CVSS score (e.g. 9.1)
info.cvss.metrics No Full CVSS vector string
info.tags Yes At least one searchable tag
info.references No External links (NVD, GitHub, blog posts)
poc.nuclei No Relative paths to Nuclei template files
poc.semgrep No Relative paths to Semgrep rule files
remediation No Ordered list of remediation steps
providers Yes At least one deployment provider
providers.docker-compose.path Yes (if using docker-compose) Relative path to the compose file
post-install No Instructions shown to the user after vt start

docker-compose.yaml Format

Standard Docker Compose v2 format. The VT CLI injects a label (vt.template-id) automatically at runtime so vt ps can track state — you don't need to add it manually.

services:
  app:
    image: ghcr.io/happyhackingspace/vt-2025-29927:latest
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
    networks:
      - vt-network

networks:
  vt-network:
    driver: bridge

Guidelines:

  • Use images from ghcr.io/happyhackingspace/ when possible for consistency.
  • Bind only the ports actually needed for exploitation.
  • Prefer bridge networks scoped to the template.
  • Do not include secrets or real credentials in plain text.

Playbook Format

Playbook files live in playbooks/ at the repo root (not inside a subdirectory).

id: vt-pb-0001                         # required — must match pattern vt-pb-\d+

info:
  name: "Full Lab Suite"               # required
  description: "Runs all 5 training labs together."  # optional
  author: hhsteam                      # required

templates:                             # required — ordered list of template IDs
  - vt-bwapp
  - vt-dvwa
  - vt-juice-shop
  - vt-mutillidae-ii
  - vt-webgoat

ID Naming Conventions

Type Pattern Example
CVE template vt-<year>-<cve-number> vt-2025-29927
Lab template vt-<app-name> vt-dvwa, vt-juice-shop
Benchmark vt-xbow-<number> vt-xbow-042
HTTP/Other vt-<name> vt-dagu
Playbook vt-pb-<number> vt-pb-0001

Vulnerable Target

Usage

Reference

Contributing

Clone this wiki locally