claw-code/.guardrails/docs/standards/ADVERSARIAL_TESTING.md

14 KiB

Adversarial Testing Protocol (Breaker Agent)

Break it before users do. Systematic protocols for stress-testing AI-generated code.

Related: TESTING_VALIDATION.md | AGENT_REVIEW_PROTOCOL.md


Overview

This document defines the "Breaker Agent" protocol - a systematic approach to adversarial testing that attempts to crash, exploit, or break AI-generated code before deployment. The goal is not to confirm code works; it is to prove it can't be broken.

Philosophy: "If you don't actively try to break your code, your users will do it for you."


THE BREAKER AGENT PERSONA

Agent Configuration

When running adversarial tests, configure the agent with this persona:

PERSONA: Senior QA Security Engineer

MISSION: Find every way to crash, exploit, or misbehave this code.

MINDSET:
- Assume the code is broken until proven otherwise
- Think like a malicious user, not a happy-path user
- Every input is a potential attack vector
- Every edge case is a potential crash

GOAL: Produce a comprehensive failure report, not a success confirmation.

Breaker vs Builder Separation

BUILDER AGENT:
- Creates features
- Writes "happy path" tests
- Assumes good faith input
- Optimizes for functionality

BREAKER AGENT:
- Destroys features (in testing)
- Writes "sad path" tests
- Assumes malicious input
- Optimizes for finding failures

RULE: The same agent should NOT build and break.
      Use separate sessions or separate agents.

ATTACK VECTOR CATEGORIES

1. Input Validation Attacks

String Attacks

Attack Type Test Input Expected Behavior
Empty string "" Graceful error, not crash
Whitespace only " " Rejected or trimmed
Very long string 10,000+ characters Rejected with limit error
Unicode edge cases "café", "日本語", "🔥🎉" Handled correctly
Null bytes "hello\x00world" Sanitized or rejected
Newlines "line1\nline2" Handled per requirements
Control characters "\t\r\n\b" Sanitized

XSS (Cross-Site Scripting) Attacks

// Test these inputs against any user-facing text field:

const xssPayloads = [
  '<script>alert("XSS")</script>',
  '<img src="x" onerror="alert(1)">',
  '<svg onload="alert(1)">',
  'javascript:alert(1)',
  '<iframe src="javascript:alert(1)">',
  '"><script>alert(1)</script>',
  "'-alert(1)-'",
  '<body onload="alert(1)">',
];

// EXPECTED: All should be escaped or rejected
// FAILURE: Any script execution = CRITICAL vulnerability

SQL Injection Attacks

// Test these against any database-connected input:

const sqlPayloads = [
  "'; DROP TABLE users; --",
  "' OR '1'='1",
  "1; SELECT * FROM users",
  "admin'--",
  "' UNION SELECT * FROM passwords --",
  "1 AND 1=1",
  "1' AND '1'='1",
];

// EXPECTED: All should be parameterized/escaped
// FAILURE: Any SQL execution = CRITICAL vulnerability

Number Attacks

Attack Type Test Input Expected Behavior
Zero 0 Handled (no division errors)
Negative -1, -999999 Rejected or handled
Float precision 0.1 + 0.2 Handled correctly
Very large Number.MAX_SAFE_INTEGER + 1 Rejected or BigInt
NaN NaN Rejected or handled
Infinity Infinity, -Infinity Rejected
String as number "123abc" Rejected

2. Boundary Condition Attacks

Array/Collection Attacks

const boundaryTests = [
  [],                          // Empty array
  [null],                      // Array with null
  [undefined],                 // Array with undefined
  Array(10000).fill(1),        // Very large array
  [1, [2, [3, [4]]]],         // Deeply nested
  new Array(1000000),          // Sparse array
];

Object Attacks

const objectTests = [
  {},                          // Empty object
  { __proto__: { admin: true } }, // Prototype pollution
  { constructor: { } },        // Constructor pollution
  null,                        // Null object
  Object.create(null),         // No prototype
  { [Symbol()]: 'hidden' },    // Symbol keys
];

3. State-Based Attacks

Race Conditions

// Test concurrent operations:

async function raceConditionTest() {
  // Submit same form 100 times simultaneously
  const promises = Array(100).fill().map(() => 
    submitPayment({ amount: 100 })
  );
  
  const results = await Promise.all(promises);
  
  // EXPECTED: Only 1 payment processed
  // FAILURE: Multiple payments = race condition bug
}

Session Attacks

const sessionTests = [
  { token: '' },               // Empty token
  { token: 'expired_token' },  // Expired token
  { token: 'malformed' },      // Invalid format
  { token: null },             // Null token
  { /* no token */ },          // Missing token
  { token: 'other_user_token' }, // Token from different user
];

4. Resource Exhaustion Attacks

Memory Exhaustion

// Test inputs that could exhaust memory:

const memoryTests = [
  'a'.repeat(1000000000),      // 1GB string
  JSON.parse('{"a":'.repeat(100000) + '1' + '}'.repeat(100000)), // Deep JSON
  new Array(100000000),        // Huge array allocation
];

// EXPECTED: Rejection before allocation
// FAILURE: Out of memory crash

CPU Exhaustion (ReDoS)

// Regular expressions vulnerable to catastrophic backtracking:

const redosPayloads = [
  'a'.repeat(30) + '!',        // For regex like /^(a+)+$/
  'aaaaaaaaaaaaaaaaaaaaaaaaaaaa!', // Exponential backtracking
];

// EXPECTED: Timeout or rejection
// FAILURE: CPU hang

FUZZ TESTING PROTOCOL

Automated Fuzzing Setup

// fuzzer.js - Generic input fuzzer

const FUZZ_ITERATIONS = 1000;

function generateFuzzInput() {
  const generators = [
    () => '',                                    // Empty
    () => null,                                  // Null
    () => undefined,                             // Undefined
    () => Math.random().toString(36),            // Random string
    () => Math.floor(Math.random() * 1000000),   // Random number
    () => Array(Math.floor(Math.random() * 100)).fill(Math.random()), // Random array
    () => ({ [Math.random()]: Math.random() }), // Random object
    () => '<script>alert(1)</script>',          // XSS
    () => "'; DROP TABLE users; --",            // SQL injection
    () => 'a'.repeat(10000),                    // Long string
    () => -Math.floor(Math.random() * 1000000), // Negative number
    () => NaN,                                   // NaN
    () => Infinity,                              // Infinity
  ];
  
  return generators[Math.floor(Math.random() * generators.length)]();
}

async function fuzzEndpoint(endpoint, method = 'POST') {
  const results = { passed: 0, failed: 0, errors: [] };
  
  for (let i = 0; i < FUZZ_ITERATIONS; i++) {
    const input = generateFuzzInput();
    try {
      const response = await fetch(endpoint, {
        method,
        body: JSON.stringify({ data: input }),
        headers: { 'Content-Type': 'application/json' },
      });
      
      // Success = 2xx or 4xx (handled error)
      // Failure = 5xx (unhandled error)
      if (response.status >= 500) {
        results.failed++;
        results.errors.push({ input, status: response.status });
      } else {
        results.passed++;
      }
    } catch (error) {
      results.failed++;
      results.errors.push({ input, error: error.message });
    }
  }
  
  return results;
}

Fuzz Test Directive

FUZZ TESTING PROTOCOL:

Target: [endpoint or function]
Iterations: 1000 minimum
Input Types: All categories above

PASS CRITERIA:
- Zero 5xx errors
- Zero unhandled exceptions
- Zero crashes
- All 4xx errors have meaningful messages

FAILURE CRITERIA:
- Any 5xx error → CRITICAL
- Any unhandled exception → CRITICAL
- Any crash → CRITICAL
- Timeout without rejection → HIGH

COMPONENT-SPECIFIC ATTACK CHECKLISTS

Form Component Attacks

ATTACK CHECKLIST: Form Component

[ ] Submit empty form
[ ] Submit with all fields empty strings
[ ] Submit with XSS in each text field
[ ] Submit with SQL injection in each text field
[ ] Submit with 10,000 character strings
[ ] Submit with emoji-only strings
[ ] Submit with unicode edge cases
[ ] Submit same form 100 times rapidly
[ ] Submit with JavaScript disabled
[ ] Submit with modified hidden fields
[ ] Submit bypassing client validation

API Endpoint Attacks

ATTACK CHECKLIST: API Endpoint

[ ] Call without authentication
[ ] Call with expired token
[ ] Call with malformed token
[ ] Call with other user's token
[ ] Send malformed JSON
[ ] Send wrong Content-Type
[ ] Send empty body
[ ] Send body > 10MB
[ ] Send deeply nested JSON (100 levels)
[ ] Call 1000 times in 1 second (rate limit)
[ ] Call with HTTP method not allowed

File Upload Attacks

ATTACK CHECKLIST: File Upload

[ ] Upload empty file
[ ] Upload file > max size
[ ] Upload file with wrong extension
[ ] Upload .exe renamed to .jpg
[ ] Upload file with null bytes in name
[ ] Upload file with path traversal (../../../etc/passwd)
[ ] Upload SVG with embedded JavaScript
[ ] Upload zip bomb (compressed 1MB → 1GB)
[ ] Upload same file 100 times rapidly
[ ] Upload with modified Content-Type header

Authentication Attacks

ATTACK CHECKLIST: Authentication

[ ] Login with empty credentials
[ ] Login with SQL injection
[ ] Login 100 times with wrong password (lockout)
[ ] Login with valid user, no password
[ ] Login with case-modified username
[ ] Password reset with non-existent email
[ ] Password reset token replay
[ ] Session fixation attempt
[ ] CSRF token bypass attempt
[ ] Remember-me token theft simulation

BREAKER AGENT PROMPT TEMPLATE

Use this prompt to configure a "Breaker Agent" session:

BREAKER AGENT SESSION

PERSONA: You are a Senior Security QA Engineer specializing in 
breaking software. Your job is to find bugs, not confirm success.

TARGET: [Component/Endpoint Name]

OBJECTIVE: Systematically attempt to crash, exploit, or cause 
unexpected behavior in the target.

ATTACK CATEGORIES TO USE:
1. Input validation attacks (XSS, SQLi, boundary values)
2. State-based attacks (race conditions, session manipulation)
3. Resource exhaustion attacks (memory, CPU, network)
4. Authentication/authorization bypass attempts

REPORT FORMAT:

For each attack attempted, report:
- Attack type
- Input used
- Expected behavior
- Actual behavior
- Severity (CRITICAL / HIGH / MEDIUM / LOW)
- Reproduction steps

CONSTRAINTS:
- Do NOT attack production systems
- Do NOT use attacks that could cause data loss
- Do NOT attempt actual credential theft
- Stay within test environment boundaries

BEGIN ATTACK SEQUENCE:

INTEGRATION WITH CI/CD

Automated Adversarial Tests

# .github/workflows/adversarial-tests.yml
name: Adversarial Testing

on:
  pull_request:
    branches: [main]

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Run OWASP ZAP scan
        uses: zaproxy/action-full-scan@v0.8.0
        with:
          target: 'http://localhost:3000'
      
      - name: Run SQLMap
        run: |
          sqlmap -u "http://localhost:3000/api/search?q=test" --batch --level=5          
      
      - name: Run Fuzz Tests
        run: npm run test:fuzz
      
      - name: Check results
        run: |
          if [ -f "fuzz-failures.json" ]; then
            echo "Fuzz tests found failures!"
            cat fuzz-failures.json
            exit 1
          fi          

Blocking Gate

ADVERSARIAL TEST GATE:

BLOCKING (Must Pass):
[ ] Zero XSS vulnerabilities detected
[ ] Zero SQL injection vulnerabilities detected
[ ] Zero authentication bypasses
[ ] Fuzz tests: < 1% failure rate
[ ] Rate limiting verified functional

NON-BLOCKING (Should Pass):
[ ] All edge cases handled gracefully
[ ] Error messages are user-friendly
[ ] Timeouts configured appropriately

QUICK REFERENCE

+------------------------------------------------------------------+
|              ADVERSARIAL TESTING QUICK REFERENCE                  |
+------------------------------------------------------------------+
| ATTACK CATEGORIES:                                                |
|   1. Input Validation (XSS, SQLi, boundaries)                     |
|   2. State-Based (race conditions, sessions)                      |
|   3. Resource Exhaustion (memory, CPU)                            |
|   4. Auth/AuthZ Bypass                                            |
+------------------------------------------------------------------+
| KEY PAYLOADS:                                                     |
|   XSS: <script>alert(1)</script>                                  |
|   SQLi: ' OR '1'='1                                               |
|   Long: 'a'.repeat(10000)                                         |
|   Empty: '', null, undefined                                      |
+------------------------------------------------------------------+
| FUZZ TESTING:                                                     |
|   Iterations: 1000 minimum                                        |
|   Pass: Zero 5xx errors                                           |
|   Fail: Any unhandled exception                                   |
+------------------------------------------------------------------+
| RULE: Builder agent ≠ Breaker agent                               |
|       Separate sessions for building and breaking                 |
+------------------------------------------------------------------+

Authored by: TheArchitectit Document Owner: Project Maintainers Last Updated: 2026-01-21 Line Count: ~400