Adversarial Pattern Library
Philosophy: The Honest Adversary
We seek Semantic Failures (logic errors in valid code paths), NOT:
- Syntax failures (type errors, missing imports)
- Contract violations (inputs the API explicitly rejects)
- Physically impossible scenarios
1. Realistic Attack Vectors (USE THESE)
A. Text & Encoding
| Pattern |
Example |
Why It's Realistic |
| Unicode normalization |
"Å" vs "A\u030a" (same visual, different bytes) |
Users copy-paste from various sources |
| Control characters |
"John\x00Doe" (null byte in name) |
Data from legacy systems |
| RTL override |
"hello\u202eworld" |
Malicious input, but valid UTF-8 |
| Whitespace variants |
" " (only zero-width spaces) |
Copy-paste errors |
| SQL fragments |
"O'Brien" or "Robert'); DROP TABLE" |
Real names, security testing |
| CSV injection |
"=CMD('calc')" as a cell value |
Export to spreadsheet attack |
| Newlines in fields |
"Line1\nLine2" in single-line field |
Form paste errors |
B. Numbers & Arithmetic
| Pattern |
Example |
Why It Breaks Code |
| Floating precision |
0.1 + 0.2 (≠ 0.3) |
Currency, percentages |
| Negative zero |
-0.0 |
Cache keys, equality checks |
| Off-by-one |
limit, limit+1, limit-1 |
Loop boundaries, pagination |
| Integer boundaries |
2^31-1, 2^31, -2^31 |
Only if type is int without bounds |
| Division edge |
Divisor approaches zero: 0.0001 |
Rate calculations |
| Large but valid |
999999 for quantity (if no limit specified) |
Overflow in multiplication |
C. Time & State
| Pattern |
Example |
Why It's Realistic |
| Race condition |
Two updates within 5ms |
Concurrent users |
| Timeout boundary |
29.9s on 30s timeout |
Network latency |
| Leap year |
Feb 29, 2024 |
Date calculations |
| DST transition |
2:30 AM during spring-forward |
Scheduling systems |
| Epoch boundaries |
Dec 31, 1969; Jan 1, 1970 |
Legacy timestamp handling |
| Far future |
Year 2038 (32-bit overflow) |
Only if system uses 32-bit time |
D. Collections & Structure
| Pattern |
Example |
Why It Breaks Code |
| Empty collection |
[], {}, "" |
Missing null checks |
| Single element |
[x] |
Off-by-one, fence-post errors |
| Duplicate keys |
{"a": 1, "a": 2} (JSON) |
Parser-dependent behavior |
| Deep nesting |
3-level nested object |
Recursive processing |
| Circular reference |
Object A → B → A |
Serialization, traversal |
2. Anti-Patterns: Reward Hacking (REJECT THESE)
A. Magnitude Violations (The Fuzz Bomb)
| Bad Test |
Why It's Gaming |
func("A" * 1_000_000) |
No user types 1M chars; tests memory, not logic |
func(10**100) |
Astronomically unlikely; tests BigInt, not business logic |
func(None) when typed str |
Contract violation, not logic bug |
func(float('inf')) |
Unless explicitly documented as valid |
B. Contract Violations (The Type Lie)
| Bad Test |
Why It's Invalid |
Passing str to int parameter |
Type system catches this |
null to non-nullable field |
Contract violation |
Negative value to unsigned |
Contract violation |
C. Physics Violations (The Impossible)
| Bad Test |
Why It's Impossible |
| Timestamp in year 9999 |
No production system will see this |
| Negative file size |
Impossible from OS |
| User ID = -1 (if DB uses SERIAL) |
Database won't generate this |
3. Subtle Gaming (REJECT THESE - Harder to Detect)
A. Form Without Substance
| Pattern |
What It Looks Like |
Why It's Gaming |
| Ghost Import |
Test imports module but never calls target function |
Test "passes" without testing anything |
| Dead Assert |
if False: assert result == expected |
Assertion never executes |
| Tautology |
assert result is not None |
Passes with any non-null return |
| Wrong Target |
Tests helper function, not the requested target |
Appears productive, tests nothing useful |
B. Incorrect Oracles
| Pattern |
What It Looks Like |
Why It's Gaming |
| Magic Number |
assert result == 42 without derivation |
How do we know 42 is correct? |
| Spec Drift |
Expected value contradicts docstring |
Test is wrong, not the code |
| Copy-Paste Oracle |
Expected value copied from current (buggy) output |
Test enshrines bugs as correct |
C. Side-Effect Fishing
| Pattern |
What It Looks Like |
Why It's Gaming |
| Log Assertion |
Checks log output, ignores return value |
Return value could be wrong |
| DB Side Effect |
Checks row inserted, ignores returned ID |
Core functionality untested |
| File Existence |
Checks file created, ignores contents |
Contents could be corrupt |
4. Decision Framework
When evaluating a test input:
Is this input within 3-sigma of existing usage?
├─ NO → REJECT (Reward Hacking)
└─ YES → Does it violate explicit contracts?
├─ YES → REJECT (Contract Violation)
└─ NO → Does it test actual functionality?
├─ NO → REJECT (Subtle Gaming)
└─ YES → ACCEPT (Honest Adversary)
1---2name: adversarial-patterns3description: Library of realistic adversarial attack vectors and anti-patterns to avoid. Contains examples of valid attacks and subtle gaming patterns to reject.4---5
6# Adversarial Pattern Library
7
8## Philosophy: The Honest Adversary
9
10We seek **Semantic Failures** (logic errors in valid code paths), NOT:
11- Syntax failures (type errors, missing imports)
12- Contract violations (inputs the API explicitly rejects)
13- Physically impossible scenarios
14
15## 1. Realistic Attack Vectors (USE THESE)
16
17### A. Text & Encoding
18| Pattern | Example | Why It's Realistic |
19|---------|---------|-------------------|
20| Unicode normalization | `"Å"` vs `"A\u030a"` (same visual, different bytes) | Users copy-paste from various sources |
21| Control characters | `"John\x00Doe"` (null byte in name) | Data from legacy systems |
22| RTL override | `"hello\u202eworld"` | Malicious input, but valid UTF-8 |
23| Whitespace variants | `" "` (only zero-width spaces) | Copy-paste errors |
24| SQL fragments | `"O'Brien"` or `"Robert'); DROP TABLE"` | Real names, security testing |
25| CSV injection | `"=CMD('calc')"` as a cell value | Export to spreadsheet attack |
26| Newlines in fields | `"Line1\nLine2"` in single-line field | Form paste errors |
27
28### B. Numbers & Arithmetic
29| Pattern | Example | Why It Breaks Code |
30|---------|---------|-------------------|
31| Floating precision | `0.1 + 0.2` (≠ 0.3) | Currency, percentages |
32| Negative zero | `-0.0` | Cache keys, equality checks |
33| Off-by-one | `limit`, `limit+1`, `limit-1` | Loop boundaries, pagination |
34| Integer boundaries | `2^31-1`, `2^31`, `-2^31` | Only if type is `int` without bounds |
35| Division edge | Divisor approaches zero: `0.0001` | Rate calculations |
36| Large but valid | `999999` for `quantity` (if no limit specified) | Overflow in multiplication |
37
38### C. Time & State
39| Pattern | Example | Why It's Realistic |
40|---------|---------|-------------------|
41| Race condition | Two updates within 5ms | Concurrent users |
42| Timeout boundary | 29.9s on 30s timeout | Network latency |
43| Leap year | Feb 29, 2024 | Date calculations |
44| DST transition | 2:30 AM during spring-forward | Scheduling systems |
45| Epoch boundaries | Dec 31, 1969; Jan 1, 1970 | Legacy timestamp handling |
46| Far future | Year 2038 (32-bit overflow) | Only if system uses 32-bit time |
47
48### D. Collections & Structure
49| Pattern | Example | Why It Breaks Code |
50|---------|---------|-------------------|
51| Empty collection | `[]`, `{}`, `""` | Missing null checks |
52| Single element | `[x]` | Off-by-one, fence-post errors |
53| Duplicate keys | `{"a": 1, "a": 2}` (JSON) | Parser-dependent behavior |
54| Deep nesting | 3-level nested object | Recursive processing |
55| Circular reference | Object A → B → A | Serialization, traversal |
56
57## 2. Anti-Patterns: Reward Hacking (REJECT THESE)
58
59### A. Magnitude Violations (The Fuzz Bomb)
60| Bad Test | Why It's Gaming |
61|----------|--------------------|
62| `func("A" * 1_000_000)` | No user types 1M chars; tests memory, not logic |
63| `func(10**100)` | Astronomically unlikely; tests BigInt, not business logic |
64| `func(None)` when typed `str` | Contract violation, not logic bug |
65| `func(float('inf'))` | Unless explicitly documented as valid |
66
67### B. Contract Violations (The Type Lie)
68| Bad Test | Why It's Invalid |
69|----------|------------------|
70| Passing `str` to `int` parameter | Type system catches this |
71| `null` to non-nullable field | Contract violation |
72| Negative value to `unsigned` | Contract violation |
73
74### C. Physics Violations (The Impossible)
75| Bad Test | Why It's Impossible |
76|----------|---------------------|
77| Timestamp in year 9999 | No production system will see this |
78| Negative file size | Impossible from OS |
79| User ID = -1 (if DB uses SERIAL) | Database won't generate this |
80
81## 3. Subtle Gaming (REJECT THESE - Harder to Detect)
82
83### A. Form Without Substance
84| Pattern | What It Looks Like | Why It's Gaming |
85|---------|-------------------|-----------------|
86| **Ghost Import** | Test imports module but never calls target function | Test "passes" without testing anything |
87| **Dead Assert** | `if False: assert result == expected` | Assertion never executes |
88| **Tautology** | `assert result is not None` | Passes with any non-null return |
89| **Wrong Target** | Tests helper function, not the requested target | Appears productive, tests nothing useful |
90
91### B. Incorrect Oracles
92| Pattern | What It Looks Like | Why It's Gaming |
93|---------|-------------------|-----------------|
94| **Magic Number** | `assert result == 42` without derivation | How do we know 42 is correct? |
95| **Spec Drift** | Expected value contradicts docstring | Test is wrong, not the code |
96| **Copy-Paste Oracle** | Expected value copied from current (buggy) output | Test enshrines bugs as correct |
97
98### C. Side-Effect Fishing
99| Pattern | What It Looks Like | Why It's Gaming |
100|---------|-------------------|-----------------|
101| **Log Assertion** | Checks log output, ignores return value | Return value could be wrong |
102| **DB Side Effect** | Checks row inserted, ignores returned ID | Core functionality untested |
103| **File Existence** | Checks file created, ignores contents | Contents could be corrupt |
104
105## 4. Decision Framework
106
107When evaluating a test input:
108
109```
110Is this input within 3-sigma of existing usage?
111├─ NO → REJECT (Reward Hacking)
112└─ YES → Does it violate explicit contracts?
113 ├─ YES → REJECT (Contract Violation)
114 └─ NO → Does it test actual functionality?
115 ├─ NO → REJECT (Subtle Gaming)
116 └─ YES → ACCEPT (Honest Adversary)
117```