Skip to content

Template System

Peter Mueller edited this page Mar 26, 2026 · 1 revision

Hadrian Template System

Hadrian security tests are defined using YAML templates — declarative files that specify which endpoints to test, which role combinations to use, and how to detect vulnerabilities. You can use the 30 built-in templates or write custom ones for application-specific authorization rules.

Template Types

Type Pattern Use Case Phases
Simple test_pattern: "simple" Read operations, BFLA checks, data exposure Single request
Mutation test_pattern: "mutation" Write/delete operations that modify state Setup → Attack → Verify

Template Structure

Every template has four sections:

1. Info Section

id: api1-bola-cross-user
info:
  name: "BOLA - Cross-User Resource Access"
  category: "API1:2023"
  severity: "HIGH"
  description: |
    Tests for Broken Object Level Authorization by attempting
    to access resources belonging to other users.
  tags: ["bola", "owasp-api-top10", "api1"]
  requires_llm_triage: true
  test_pattern: "simple"
Field Required Description
id Yes Unique template identifier
name Yes Human-readable test name
category Yes OWASP category (e.g., "API1:2023")
severity Yes CRITICAL, HIGH, MEDIUM, LOW
description No Detailed explanation
tags No Categorization tags
requires_llm_triage No Enable AI analysis of findings
test_pattern Yes "simple" or "mutation"

2. Endpoint Selector

Filters which endpoints this template applies to:

endpoint_selector:
  has_path_parameter: true      # Only test endpoints with {id} parameters
  requires_auth: true           # Only authenticated endpoints
  methods: ["GET", "PUT"]       # HTTP methods to match

For gRPC:

endpoint_selector:
  requires_auth: true
  methods: ["Get*", "Read*", "Fetch*"]   # gRPC method name patterns

3. Role Selector

Defines attacker/victim role combinations:

role_selector:
  attacker_permission_level: "lower"    # Less privileged attacker
  victim_permission_level: "higher"     # More privileged victim
Value Meaning
"lower" Roles with lower level than the counterpart
"higher" Roles with higher level than the counterpart
"all" All roles
"none" Unauthenticated access (no auth header sent)

4. Detection Logic

How to identify vulnerabilities:

detection:
  success_indicators:
    - type: status_code
      status_code: 200
    - type: body_contains
      pattern: "\"id\":"
  failure_indicators:
    - type: status_code
      status_code: 403
    - type: status_code
      status_code: 401

Vulnerability found if: Response matches ALL success_indicators and NONE of the failure_indicators.

Detection Types

Type Fields Description
status_code status_code HTTP status code match
body_contains pattern Response body contains string
body_field body_field, exists JSON field exists in response
grpc_status code gRPC status code (single or array)

Simple Template Example (REST)

id: api1-bola-read
info:
  name: "BOLA - Cross-User Resource Read"
  category: "API1:2023"
  severity: "HIGH"
  test_pattern: "simple"

endpoint_selector:
  has_path_parameter: true
  requires_auth: true
  methods: ["GET"]

role_selector:
  attacker_permission_level: "lower"
  victim_permission_level: "higher"

http:
  - method: "{{method}}"
    path: "{{path}}"
    headers:
      Authorization: "{{attacker_auth}}"

detection:
  success_indicators:
    - type: status_code
      status_code: 200
    - type: body_contains
      pattern: "\"id\":"
  failure_indicators:
    - type: status_code
      status_code: 403

Mutation Template Example (Three-Phase)

id: api1-bola-delete
info:
  name: "BOLA - Unauthorized Resource Deletion"
  category: "API1:2023"
  severity: "CRITICAL"
  test_pattern: "mutation"

endpoint_selector:
  has_path_parameter: true
  requires_auth: true
  methods: ["DELETE"]

role_selector:
  attacker_permission_level: "lower"
  victim_permission_level: "higher"

test_phases:
  setup:
    - path: "/api/user/dashboard"
      auth: "victim"
      store_response_fields:
        victim_id: "id"
        victim_video_id: "video_id"

  attack:
    path: "/api/resource/{victim_video_id}"
    auth: "attacker"
    operation: "delete"
    expected_status: 200

  verify:
    path: "/api/resource/{victim_video_id}"
    auth: "victim"
    check_field: "status"
    expected_value: "deleted"

detection:
  success_indicators:
    - type: status_code
      status_code: 200
  failure_indicators:
    - type: status_code
      status_code: 403
  conditions:
    - attack_phase_status: [200]
      verify_phase_status: [404]

Phase Fields

Field Phase Description
path All Endpoint to call
auth All Role credentials to use ("victim" or "attacker")
operation Attack "create", "update", "delete", "read"
data Setup Request body fields
store_response_field Setup JSON path to extract from response
store_response_fields Setup Map of field names to JSON paths
use_stored_field Attack/Verify Use previously stored field
expected_status All Expected status code
check_field Verify Field to check for changes
expected_value Verify Expected field value after attack

Template Variable Limitations

store_response_fields uses JSON path expressions supporting dot-separated object key traversal only (e.g., data.user.id). Array indexing, keys containing dots, and nested arrays are not supported.

GraphQL Template Example

id: graphql-bola
info:
  name: "GraphQL BOLA"
  category: "API1:2023"
  severity: "HIGH"
  test_pattern: "simple"

endpoint_selector:
  requires_auth: true

role_selector:
  attacker_permission_level: "lower"
  victim_permission_level: "higher"

graphql:
  - query: |
      query { user(id: "{{victim_id}}") { email ssn } }
    auth: "attacker"

detection:
  success_indicators:
    - type: status_code
      status_code: 200
    - type: body_field
      body_field: "data.user"
      exists: true

gRPC Template Example

id: grpc-bola-read
info:
  name: "gRPC BOLA Read"
  category: "API1:2023"
  severity: "HIGH"
  test_pattern: "simple"

endpoint_selector:
  requires_auth: true
  methods: ["Get*", "Read*"]

role_selector:
  attacker_permission_level: "lower"
  victim_permission_level: "higher"

grpc:
  - method: "{{operation.method}}"
    service: "{{operation.service}}"
    message: '{"{{operation.owner_field}}": "{{victim_id}}"}'
    metadata:
      authorization: "Bearer {{attacker_token}}"

detection:
  success_indicators:
    - type: "grpc_status"
      code: 0
  failure_indicators:
    - type: "grpc_status"
      code: [7, 16]

Template Execution Order

Templates are loaded and executed in alphabetical order by filename. Prefix filenames with numbers to control order:

  • 01-* to 05-*: Non-destructive read tests
  • 06-* to 07-*: Write/modification tests
  • 08-* to 09-*: Destructive delete tests

This ensures read tests run before tests that modify or delete data.

Template Variables

Variable Description
{{method}} HTTP method (GET, POST, etc.)
{{path}} Endpoint path
{{attacker_auth}} Attacker's auth header value
{{victim_id}} Victim's user/resource ID
{{attacker_id}} Attacker's user/resource ID
{{attacker_token}} Attacker's raw token
{{random_id}} Random string for unique resources
{{operation.method}} gRPC method name
{{operation.service}} gRPC service name
{{operation.owner_field}} Field that identifies resource owner
{{operation.resource_type}} Resource type name

Clone this wiki locally