Skip to content

Architecture

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

Hadrian Architecture

This document describes how Hadrian works internally — its components, data flow, testing methodology, and security safeguards.

High-Level Architecture

Hadrian processes security tests in five phases:

INPUT FILES → INITIALIZATION → TEMPLATE MATCHING → TEST EXECUTION → FINDINGS & OUTPUT

Phase 1: Initialization

Hadrian loads and parses four input types:

Input Parser Output
api.yaml (OpenAPI/Swagger/Postman) REST/GraphQL/gRPC plugin Operations (endpoints, methods)
roles.yaml Role parser Roles with permission strings
auth.yaml Auth loader Per-role authentication tokens
templates/*.yaml Template parser Compiled test templates

Phase 2: Template Matching

For each discovered operation, Hadrian matches it against template endpoint selectors:

endpoint_selector:
  has_path_parameter: true      # Only {id} endpoints
  requires_auth: true           # Authenticated endpoints only
  methods: ["GET", "PUT"]       # Matching HTTP methods

An operation matches a template if ALL selector criteria are satisfied.

Phase 3: Test Execution

Matched operations are executed using either simple or mutation test patterns.

Simple Tests (Single Request)

  1. Build request with variable substitution
  2. Inject attacker's authentication token
  3. Execute request against victim's resource
  4. Check detection matchers against response
  5. If matched → vulnerability found

Three-Phase Mutation Testing

For vulnerabilities that modify state (writes, deletes), Hadrian uses a three-phase approach to prove the vulnerability actually occurred:

┌─────────────────────────────────────────────────┐
│ Phase 1: SETUP (as victim)                       │
│   Create resource → store resource_id            │
├─────────────────────────────────────────────────┤
│ Phase 2: ATTACK (as attacker)                    │
│   Attempt unauthorized action on resource_id     │
├─────────────────────────────────────────────────┤
│ Phase 3: VERIFY (as victim)                      │
│   Check if resource was actually modified/deleted │
└─────────────────────────────────────────────────┘

Why verify? A 200 OK from a delete endpoint doesn't prove the resource was deleted — the server may have accepted but ignored the request. The verify phase confirms the state change by reading the resource back.

Phase 4: Findings & Triage

Each confirmed vulnerability produces a Finding with:

  • OWASP category and severity
  • Endpoint and HTTP method
  • Attacker/victim role pair
  • Request/response evidence

If LLM triage is enabled, findings are sent to Ollama for contextual analysis:

  • Sensitive data is redacted before LLM processing
  • LLM adds confidence scores and recommendations
  • Helps reduce false positives

Phase 5: Output

Findings are formatted as terminal output (default), JSON, or Markdown reports.

Package Structure

hadrian/
├── cmd/hadrian/main.go          # CLI entry point
├── pkg/
│   ├── runner/                  # Orchestration, rate limiting, execution
│   │   ├── run.go               # CLI commands and main loop
│   │   ├── graphql.go           # GraphQL test runner
│   │   ├── grpc.go              # gRPC test runner
│   │   ├── ratelimit.go         # Rate limiter configuration
│   │   ├── ratelimit_client.go  # HTTP client with reactive backoff
│   │   └── execution.go         # Template execution logic
│   ├── model/                   # Data structures (Operation, Finding)
│   ├── templates/               # Template parsing and compilation
│   ├── auth/                    # Authentication handling
│   ├── roles/                   # Role-based authorization logic
│   ├── orchestrator/            # Test orchestration and mutation tests
│   ├── plugins/                 # API spec parsers
│   │   ├── rest/                # OpenAPI/Swagger parser
│   │   ├── graphql/             # GraphQL SDL and introspection
│   │   └── grpc/                # Protocol Buffers parser
│   ├── graphql/                 # GraphQL scanning engine
│   ├── reporter/                # Output formatting
│   ├── llm/                     # LLM integration (Ollama)
│   └── matchers/                # Detection matchers
├── internal/http/               # HTTP client with proxy support
└── templates/
    ├── rest/                    # 8 built-in REST templates
    ├── graphql/                 # 13 built-in GraphQL templates
    └── grpc/                    # 9 built-in gRPC templates

Security Safeguards

Safeguard Description
Adaptive Rate Limiting Proactive (configurable req/s) + reactive (backoff on 429/503)
YAML Bomb Protection 1MB size limit, 20-depth limit
TLS 1.3 Enforcement No legacy TLS allowed
Credential Validation Warns on insecure auth.yaml permissions
LLM Data Redaction Tokens and credentials stripped before LLM processing
Audit Logging All requests logged to .hadrian/audit.log

Data Flow Summary

  1. API spec → parsed into operations (endpoint + method + parameters)
  2. Roles + auth → mapped to role pairs (attacker/victim combinations)
  3. Templates → matched to operations via endpoint selectors
  4. Execution → requests sent with attacker credentials against victim resources
  5. Detection → response matched against success/failure indicators
  6. Triage → optional LLM analysis of confirmed findings
  7. Output → findings formatted and reported

Clone this wiki locally