vanara 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/README.md +14 -0
  2. package/bin/vanara.js +66 -2
  3. package/catalog/agents/api-designer/AGENT.md +140 -0
  4. package/catalog/agents/api-designer/examples/openapi-snippet.yaml +130 -0
  5. package/catalog/agents/api-designer/examples/review-notes.md +61 -0
  6. package/catalog/agents/api-designer/references/contract-and-openapi.md +82 -0
  7. package/catalog/agents/api-designer/references/design-checklist.md +68 -0
  8. package/catalog/agents/api-designer/references/versioning-and-evolution.md +63 -0
  9. package/catalog/agents/api-designer/scripts/lint-openapi.mjs +180 -0
  10. package/catalog/agents/code-reviewer/AGENT.md +168 -0
  11. package/catalog/agents/code-reviewer/examples/pr-comment-template.md +48 -0
  12. package/catalog/agents/code-reviewer/examples/sample-review-output.md +38 -0
  13. package/catalog/agents/code-reviewer/references/review-checklist.md +46 -0
  14. package/catalog/agents/code-reviewer/references/security-review.md +62 -0
  15. package/catalog/agents/code-reviewer/references/severity-rubric.md +63 -0
  16. package/catalog/agents/code-reviewer/scripts/review-guard.mjs +102 -0
  17. package/catalog/agents/debugger/AGENT.md +112 -0
  18. package/catalog/agents/debugger/examples/postmortem-template.md +59 -0
  19. package/catalog/agents/debugger/examples/repro-template.md +50 -0
  20. package/catalog/agents/debugger/references/bisection.md +63 -0
  21. package/catalog/agents/debugger/references/debugging-method.md +57 -0
  22. package/catalog/agents/debugger/references/observability.md +61 -0
  23. package/catalog/agents/debugger/scripts/parse-stacktrace.mjs +109 -0
  24. package/catalog/agents/pr-summarizer/AGENT.md +156 -0
  25. package/catalog/agents/pr-summarizer/examples/sample-pr-summary.md +46 -0
  26. package/catalog/agents/pr-summarizer/examples/weak-vs-strong-summary.md +68 -0
  27. package/catalog/agents/pr-summarizer/references/identifying-risk.md +68 -0
  28. package/catalog/agents/pr-summarizer/references/reading-the-diff.md +68 -0
  29. package/catalog/agents/pr-summarizer/references/test-plan-and-missing-tests.md +64 -0
  30. package/catalog/agents/pr-summarizer/references/writing-the-summary.md +63 -0
  31. package/catalog/agents/pr-summarizer/scripts/diff-risk.mjs +111 -0
  32. package/catalog/agents/refactoring-specialist/AGENT.md +185 -0
  33. package/catalog/agents/refactoring-specialist/examples/before-after.md +91 -0
  34. package/catalog/agents/refactoring-specialist/examples/refactor-plan.md +97 -0
  35. package/catalog/agents/refactoring-specialist/references/large-scale-refactor.md +50 -0
  36. package/catalog/agents/refactoring-specialist/references/safe-workflow.md +75 -0
  37. package/catalog/agents/refactoring-specialist/references/smell-catalog.md +76 -0
  38. package/catalog/agents/refactoring-specialist/scripts/detect-smells.mjs +150 -0
  39. package/catalog/agents/security-auditor/AGENT.md +168 -0
  40. package/catalog/agents/security-auditor/examples/audit-report.md +68 -0
  41. package/catalog/agents/security-auditor/examples/finding-template.md +31 -0
  42. package/catalog/agents/security-auditor/references/audit-workflow.md +116 -0
  43. package/catalog/agents/security-auditor/references/severity-and-reporting.md +56 -0
  44. package/catalog/agents/security-auditor/references/vuln-classes.md +129 -0
  45. package/catalog/agents/security-auditor/scripts/scan-secrets.mjs +86 -0
  46. package/catalog/agents/technical-writer/AGENT.md +163 -0
  47. package/catalog/agents/technical-writer/examples/how-to-example.md +76 -0
  48. package/catalog/agents/technical-writer/examples/reference-example.md +75 -0
  49. package/catalog/agents/technical-writer/references/clarity-and-style.md +52 -0
  50. package/catalog/agents/technical-writer/references/diataxis-and-doc-types.md +61 -0
  51. package/catalog/agents/technical-writer/references/structure-and-maintenance.md +59 -0
  52. package/catalog/agents/technical-writer/scripts/readability.mjs +103 -0
  53. package/catalog/agents/test-author/AGENT.md +177 -0
  54. package/catalog/agents/test-author/examples/test-plan.md +54 -0
  55. package/catalog/agents/test-author/examples/unit-test-example.ts +55 -0
  56. package/catalog/agents/test-author/references/aaa-and-naming.md +75 -0
  57. package/catalog/agents/test-author/references/mocking-and-fixtures.md +94 -0
  58. package/catalog/agents/test-author/references/test-types-and-pyramid.md +60 -0
  59. package/catalog/agents/test-author/scripts/check-coverage.mjs +145 -0
  60. package/catalog/agents/threat-modeler/AGENT.md +163 -0
  61. package/catalog/agents/threat-modeler/examples/dfd-example.md +55 -0
  62. package/catalog/agents/threat-modeler/examples/threat-model.md +81 -0
  63. package/catalog/agents/threat-modeler/references/dfd-and-trust-boundaries.md +76 -0
  64. package/catalog/agents/threat-modeler/references/mitigation-catalog.md +77 -0
  65. package/catalog/agents/threat-modeler/references/stride-method.md +68 -0
  66. package/catalog/agents/threat-modeler/scripts/stride-checklist.mjs +183 -0
  67. package/catalog/agents/vuln-scanner/AGENT.md +146 -0
  68. package/catalog/agents/vuln-scanner/examples/finding-template.md +57 -0
  69. package/catalog/agents/vuln-scanner/examples/scan-report.md +49 -0
  70. package/catalog/agents/vuln-scanner/references/remediation-and-severity.md +68 -0
  71. package/catalog/agents/vuln-scanner/references/scan-types-and-tools.md +83 -0
  72. package/catalog/agents/vuln-scanner/references/triage-and-false-positives.md +73 -0
  73. package/catalog/agents/vuln-scanner/scripts/parse-scan-results.mjs +133 -0
  74. package/catalog/packs/code-review-pack/PACK.md +100 -0
  75. package/catalog/packs/code-review-pack/examples/pr-flow-example.md +50 -0
  76. package/catalog/packs/code-review-pack/references/rollout-guide.md +40 -0
  77. package/catalog/packs/security-pack/PACK.md +128 -0
  78. package/catalog/packs/security-pack/examples/owasp-vuln-triage-and-fix.md +66 -0
  79. package/catalog/packs/security-pack/examples/threat-model-then-audit.md +77 -0
  80. package/catalog/packs/security-pack/references/choosing-the-right-tool.md +37 -0
  81. package/catalog/packs/security-pack/references/threat-model-to-remediation.md +69 -0
  82. package/catalog/packs/security-pack/references/workflow.md +56 -0
  83. package/catalog/skills/api-pagination/SKILL.md +83 -0
  84. package/catalog/skills/api-pagination/examples/keyset-queries.sql +38 -0
  85. package/catalog/skills/api-pagination/examples/response-shapes.md +51 -0
  86. package/catalog/skills/api-pagination/references/consuming-pages.md +39 -0
  87. package/catalog/skills/api-pagination/references/counting-and-totals.md +41 -0
  88. package/catalog/skills/api-pagination/references/cursor-encoding.md +34 -0
  89. package/catalog/skills/api-pagination/scripts/check-cursor.mjs +51 -0
  90. package/catalog/skills/caching-strategies/SKILL.md +180 -0
  91. package/catalog/skills/caching-strategies/examples/http-cache-headers.md +82 -0
  92. package/catalog/skills/caching-strategies/examples/redis-cache-aside.js +110 -0
  93. package/catalog/skills/caching-strategies/references/cache-patterns.md +93 -0
  94. package/catalog/skills/caching-strategies/references/eviction-and-ttl.md +67 -0
  95. package/catalog/skills/caching-strategies/references/invalidation-and-stampede.md +99 -0
  96. package/catalog/skills/caching-strategies/scripts/ttl-jitter.mjs +99 -0
  97. package/catalog/skills/conventional-commits/SKILL.md +135 -0
  98. package/catalog/skills/conventional-commits/examples/commit-examples.md +60 -0
  99. package/catalog/skills/conventional-commits/examples/commitlint.config.js +31 -0
  100. package/catalog/skills/conventional-commits/references/breaking-changes-semver.md +50 -0
  101. package/catalog/skills/conventional-commits/references/scoping-commits.md +42 -0
  102. package/catalog/skills/conventional-commits/references/spec.md +78 -0
  103. package/catalog/skills/conventional-commits/scripts/lint-commit.mjs +97 -0
  104. package/catalog/skills/database-migrations/SKILL.md +137 -0
  105. package/catalog/skills/database-migrations/examples/add-column-safe.sql +34 -0
  106. package/catalog/skills/database-migrations/examples/migration-config.example.json +27 -0
  107. package/catalog/skills/database-migrations/references/expand-contract.md +74 -0
  108. package/catalog/skills/database-migrations/references/rollback-and-safety.md +71 -0
  109. package/catalog/skills/database-migrations/references/zero-downtime-changes.md +84 -0
  110. package/catalog/skills/database-migrations/scripts/check-migration-reversible.mjs +139 -0
  111. package/catalog/skills/error-handling-patterns/SKILL.md +136 -0
  112. package/catalog/skills/error-handling-patterns/examples/express-error-middleware.js +93 -0
  113. package/catalog/skills/error-handling-patterns/examples/result-pattern.ts +81 -0
  114. package/catalog/skills/error-handling-patterns/references/error-taxonomy.md +91 -0
  115. package/catalog/skills/error-handling-patterns/references/language-patterns.md +102 -0
  116. package/catalog/skills/error-handling-patterns/references/retry-and-backoff.md +76 -0
  117. package/catalog/skills/error-handling-patterns/scripts/lint-empty-catch.mjs +113 -0
  118. package/catalog/skills/git-collaboration-workflows/SKILL.md +104 -0
  119. package/catalog/skills/git-collaboration-workflows/examples/branch-protection.md +48 -0
  120. package/catalog/skills/git-collaboration-workflows/examples/pr-review-playbook.md +48 -0
  121. package/catalog/skills/git-collaboration-workflows/references/branching-models.md +52 -0
  122. package/catalog/skills/git-collaboration-workflows/references/history-hygiene.md +44 -0
  123. package/catalog/skills/git-collaboration-workflows/scripts/check-branch-hygiene.mjs +62 -0
  124. package/catalog/skills/owasp-top10/SKILL.md +112 -0
  125. package/catalog/skills/owasp-top10/examples/sql-injection-fix.md +33 -0
  126. package/catalog/skills/owasp-top10/examples/xss-fix.md +27 -0
  127. package/catalog/skills/owasp-top10/references/access-control.md +36 -0
  128. package/catalog/skills/owasp-top10/references/crypto-failures.md +29 -0
  129. package/catalog/skills/owasp-top10/references/injection.md +39 -0
  130. package/catalog/skills/owasp-top10/references/ssrf-and-design.md +35 -0
  131. package/catalog/skills/owasp-top10/scripts/scan-injection.mjs +73 -0
  132. package/catalog/skills/prompt-engineering/SKILL.md +100 -0
  133. package/catalog/skills/prompt-engineering/examples/classification-prompt.md +29 -0
  134. package/catalog/skills/prompt-engineering/examples/extraction-prompt.md +25 -0
  135. package/catalog/skills/prompt-engineering/references/prompt-injection.md +34 -0
  136. package/catalog/skills/prompt-engineering/references/structured-output.md +34 -0
  137. package/catalog/skills/prompt-engineering/references/techniques.md +33 -0
  138. package/catalog/skills/prompt-engineering/scripts/validate-output.mjs +71 -0
  139. package/catalog/skills/readme-writing/SKILL.md +176 -0
  140. package/catalog/skills/readme-writing/examples/README.template.md +73 -0
  141. package/catalog/skills/readme-writing/examples/good-readme-example.md +95 -0
  142. package/catalog/skills/readme-writing/references/anatomy.md +107 -0
  143. package/catalog/skills/readme-writing/references/maintenance.md +68 -0
  144. package/catalog/skills/readme-writing/references/writing-style.md +79 -0
  145. package/catalog/skills/readme-writing/scripts/lint-readme.mjs +117 -0
  146. package/catalog/skills/refactoring-patterns/SKILL.md +178 -0
  147. package/catalog/skills/refactoring-patterns/examples/extract-function.before-after.js +57 -0
  148. package/catalog/skills/refactoring-patterns/examples/replace-conditional-with-polymorphism.before-after.ts +63 -0
  149. package/catalog/skills/refactoring-patterns/references/code-smells.md +92 -0
  150. package/catalog/skills/refactoring-patterns/references/refactoring-catalog.md +78 -0
  151. package/catalog/skills/refactoring-patterns/references/safe-workflow.md +74 -0
  152. package/catalog/skills/refactoring-patterns/scripts/detect-smells.mjs +137 -0
  153. package/catalog/skills/rest-api-design/SKILL.md +147 -0
  154. package/catalog/skills/rest-api-design/examples/error-envelope.json +26 -0
  155. package/catalog/skills/rest-api-design/examples/orders-api.openapi.yaml +106 -0
  156. package/catalog/skills/rest-api-design/references/error-handling.md +43 -0
  157. package/catalog/skills/rest-api-design/references/pagination.md +41 -0
  158. package/catalog/skills/rest-api-design/references/status-codes.md +32 -0
  159. package/catalog/skills/rest-api-design/references/versioning.md +31 -0
  160. package/catalog/skills/rest-api-design/scripts/check-envelope.mjs +62 -0
  161. package/catalog/skills/secrets-management/SKILL.md +134 -0
  162. package/catalog/skills/secrets-management/examples/env-example.md +41 -0
  163. package/catalog/skills/secrets-management/examples/rotation-runbook.md +50 -0
  164. package/catalog/skills/secrets-management/references/leak-response.md +47 -0
  165. package/catalog/skills/secrets-management/references/rotation.md +46 -0
  166. package/catalog/skills/secrets-management/references/secret-managers.md +52 -0
  167. package/catalog/skills/secrets-management/scripts/detect-hardcoded.mjs +96 -0
  168. package/catalog/skills/secure-auth/SKILL.md +135 -0
  169. package/catalog/skills/secure-auth/examples/auth-flow.md +60 -0
  170. package/catalog/skills/secure-auth/examples/jwt-verify.ts +89 -0
  171. package/catalog/skills/secure-auth/references/auth-attacks.md +76 -0
  172. package/catalog/skills/secure-auth/references/oauth2-oidc.md +65 -0
  173. package/catalog/skills/secure-auth/references/password-hashing.md +70 -0
  174. package/catalog/skills/secure-auth/references/sessions-vs-jwt.md +69 -0
  175. package/catalog/skills/secure-auth/scripts/check-password-policy.mjs +114 -0
  176. package/catalog/skills/sql-index-tuning/SKILL.md +171 -0
  177. package/catalog/skills/sql-index-tuning/examples/explain-walkthrough.sql +91 -0
  178. package/catalog/skills/sql-index-tuning/examples/index-ddl.sql +67 -0
  179. package/catalog/skills/sql-index-tuning/references/btree-internals.md +58 -0
  180. package/catalog/skills/sql-index-tuning/references/composite-and-covering.md +60 -0
  181. package/catalog/skills/sql-index-tuning/references/reading-explain.md +54 -0
  182. package/catalog/skills/sql-index-tuning/references/selectivity-and-cardinality.md +62 -0
  183. package/catalog/skills/sql-index-tuning/scripts/suggest-index.mjs +213 -0
  184. package/catalog/skills/test-plan-design/SKILL.md +154 -0
  185. package/catalog/skills/test-plan-design/examples/test-case-template.md +45 -0
  186. package/catalog/skills/test-plan-design/examples/test-plan.md +57 -0
  187. package/catalog/skills/test-plan-design/references/case-design.md +79 -0
  188. package/catalog/skills/test-plan-design/references/risk-prioritization.md +58 -0
  189. package/catalog/skills/test-plan-design/references/test-pyramid.md +58 -0
  190. package/catalog/skills/test-plan-design/scripts/coverage-gaps.mjs +109 -0
  191. package/free-tier.json +15 -0
  192. package/package.json +15 -4
  193. package/premium-index.json +1 -0
  194. package/src/config.js +31 -1
  195. package/src/license.js +143 -0
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env node
2
+ // Coverage gate: reads an Istanbul/c8/Jest-style coverage-summary.json and fails (exit 1)
3
+ // if total coverage falls below a threshold. Zero dependencies — Node built-ins only.
4
+ //
5
+ // A coverage-summary.json looks like:
6
+ // { "total": { "lines": { "pct": 92.3 }, "statements": { "pct": 90.1 },
7
+ // "functions": { "pct": 85.0 }, "branches": { "pct": 88.2 } }, ... }
8
+ //
9
+ // Usage:
10
+ // node check-coverage.mjs coverage/coverage-summary.json # gate at 80% (default)
11
+ // node check-coverage.mjs coverage/coverage-summary.json --min=90 # custom threshold
12
+ // node check-coverage.mjs --min=75 < coverage-summary.json # read JSON from stdin
13
+ // node check-coverage.mjs --selftest # built-in test cases
14
+
15
+ import { readFileSync } from 'node:fs';
16
+
17
+ const DEFAULT_MIN = 80;
18
+ // Metrics we gate on; the lowest of these must meet the threshold.
19
+ const METRICS = ['lines', 'statements', 'functions', 'branches'];
20
+
21
+ // Pull the per-metric pct numbers out of a coverage summary's `total` block.
22
+ export function extractTotals(summary) {
23
+ if (!summary || typeof summary !== 'object' || !summary.total) {
24
+ throw new Error('missing "total" block in coverage summary');
25
+ }
26
+ const totals = {};
27
+ for (const m of METRICS) {
28
+ const pct = summary.total?.[m]?.pct;
29
+ if (typeof pct === 'number' && Number.isFinite(pct)) totals[m] = pct;
30
+ }
31
+ if (Object.keys(totals).length === 0) {
32
+ throw new Error('no numeric coverage metrics found in "total"');
33
+ }
34
+ return totals;
35
+ }
36
+
37
+ // Returns { ok, min, worst, totals, failures } — pure, so it is unit-testable.
38
+ export function evaluateCoverage(summary, min = DEFAULT_MIN) {
39
+ const totals = extractTotals(summary);
40
+ const failures = Object.entries(totals)
41
+ .filter(([, pct]) => pct < min)
42
+ .map(([metric, pct]) => ({ metric, pct }));
43
+ const worst = Math.min(...Object.values(totals));
44
+ return { ok: failures.length === 0, min, worst, totals, failures };
45
+ }
46
+
47
+ function parseMin(argv) {
48
+ const flag = argv.find((a) => a.startsWith('--min='));
49
+ if (!flag) return DEFAULT_MIN;
50
+ const n = Number(flag.slice('--min='.length));
51
+ if (!Number.isFinite(n) || n < 0 || n > 100) {
52
+ console.error(`✗ invalid --min value: "${flag}" (expected 0–100)`);
53
+ process.exit(1);
54
+ }
55
+ return n;
56
+ }
57
+
58
+ function report(label, result) {
59
+ const pad = (m) => m.padEnd(11);
60
+ for (const [metric, pct] of Object.entries(result.totals)) {
61
+ const mark = pct < result.min ? '✗' : '✓';
62
+ console.log(` ${mark} ${pad(metric)} ${pct.toFixed(2)}%`);
63
+ }
64
+ if (result.ok) {
65
+ console.log(`✓ ${label}: coverage ${result.worst.toFixed(2)}% meets ${result.min}% threshold`);
66
+ } else {
67
+ const names = result.failures.map((f) => `${f.metric} ${f.pct.toFixed(2)}%`).join(', ');
68
+ console.error(`✗ ${label}: below ${result.min}% threshold — ${names}`);
69
+ }
70
+ return result.ok;
71
+ }
72
+
73
+ function runFile(path, min) {
74
+ let summary;
75
+ try {
76
+ summary = JSON.parse(readFileSync(path, 'utf8'));
77
+ } catch (err) {
78
+ console.error(`✗ could not read/parse "${path}": ${err.message}`);
79
+ process.exit(1);
80
+ }
81
+ try {
82
+ process.exit(report(path, evaluateCoverage(summary, min)) ? 0 : 1);
83
+ } catch (err) {
84
+ console.error(`✗ ${path}: ${err.message}`);
85
+ process.exit(1);
86
+ }
87
+ }
88
+
89
+ function runStdin(min) {
90
+ let buf = '';
91
+ process.stdin.on('data', (c) => (buf += c));
92
+ process.stdin.on('end', () => {
93
+ try {
94
+ process.exit(report('stdin', evaluateCoverage(JSON.parse(buf), min)) ? 0 : 1);
95
+ } catch (err) {
96
+ console.error(`✗ stdin: ${err.message}`);
97
+ process.exit(1);
98
+ }
99
+ });
100
+ }
101
+
102
+ function selftest() {
103
+ const passing = { total: {
104
+ lines: { pct: 92.3 }, statements: { pct: 90.1 },
105
+ functions: { pct: 85.0 }, branches: { pct: 88.2 },
106
+ } };
107
+ const failing = { total: {
108
+ lines: { pct: 72.0 }, statements: { pct: 70.5 },
109
+ functions: { pct: 60.0 }, branches: { pct: 55.0 },
110
+ } };
111
+ const edge = { total: { lines: { pct: 80.0 }, statements: { pct: 80.0 },
112
+ functions: { pct: 80.0 }, branches: { pct: 80.0 } } }; // exactly at threshold -> pass
113
+
114
+ const cases = [
115
+ ['passing above 80', evaluateCoverage(passing, 80).ok, true],
116
+ ['failing below 80', evaluateCoverage(failing, 80).ok, false],
117
+ ['exactly at 80 passes', evaluateCoverage(edge, 80).ok, true],
118
+ ['passing fails a 95 gate', evaluateCoverage(passing, 95).ok, false],
119
+ ['worst metric is the branch pct', evaluateCoverage(passing, 80).worst === 85.0, true],
120
+ ];
121
+
122
+ let allOk = true;
123
+ for (const [name, actual, expected] of cases) {
124
+ const correct = actual === expected;
125
+ allOk &&= correct;
126
+ console.log(`${correct ? '✓' : '✗'} selftest ${name}: got ${actual} (expected ${expected})`);
127
+ }
128
+ // Error handling: malformed input must throw.
129
+ let threw = false;
130
+ try { extractTotals({ nope: true }); } catch { threw = true; }
131
+ console.log(`${threw ? '✓' : '✗'} selftest rejects malformed summary: threw ${threw} (expected true)`);
132
+ allOk &&= threw;
133
+
134
+ process.exit(allOk ? 0 : 1);
135
+ }
136
+
137
+ const argv = process.argv.slice(2);
138
+ if (argv.includes('--selftest')) {
139
+ selftest();
140
+ } else {
141
+ const min = parseMin(argv);
142
+ const file = argv.find((a) => !a.startsWith('--'));
143
+ if (file) runFile(file, min);
144
+ else runStdin(min);
145
+ }
@@ -0,0 +1,163 @@
1
+ ---
2
+ name: threat-modeler
3
+ description: Use when designing a new system or feature, or assessing the attack surface of an existing one. Produces a STRIDE threat model over a data-flow diagram — assets, trust boundaries, threats, risk ratings, and prioritized mitigations.
4
+ tools: Read, Grep, Glob
5
+ model: claude-opus-4-8
6
+ type: agent
7
+ version: 2.0.0
8
+ updated: 2026-06-29
9
+ ---
10
+ # Threat Modeler
11
+
12
+ You are a threat-modeling specialist. You think like an attacker *during design*, when mitigations are
13
+ cheapest to apply, and you answer two questions for every system you look at: **what can go wrong**, and
14
+ **what are we doing about it?** You produce a structured, defensible threat model — not a vague list of
15
+ "security concerns" — that an engineering team can act on directly.
16
+
17
+ You operate read-only: you analyze designs, code, and architecture documents to build the model. You do
18
+ not implement fixes; you specify them and hand them to the people who do.
19
+
20
+ ## Role and operating principles
21
+
22
+ - **Boundaries first.** The most valuable threats live where data crosses from a less-trusted zone to a
23
+ more-trusted one. Find those crossings before enumerating anything.
24
+ - **Asset-driven, not technology-driven.** Start from what is worth protecting (data, funds, credentials,
25
+ availability, reputation) and who wants it. A clever attack on something worthless is noise.
26
+ - **Every threat gets a decision.** Each threat is rated and assigned an outcome: *mitigate*, *accept*,
27
+ *transfer*, or *avoid*. An unrated threat is an unfinished one.
28
+ - **Defense in depth.** Prefer layered controls over a single point of failure. Assume any one control
29
+ can be bypassed and ask what catches the attacker next.
30
+ - **Concrete over generic.** "Validate input" is not a mitigation; "reject `order_id` values that fail a
31
+ ULID format check before the DB query, server-side" is. Tie every mitigation to a specific threat.
32
+ - **Honest uncertainty.** Flag assumptions you could not verify and name the single riskiest one to
33
+ validate first. Do not invent endpoints, auth flows, or data stores that aren't in the material.
34
+
35
+ ## Workflow: STRIDE over a data-flow diagram
36
+
37
+ Work through these steps in order. Do not skip to threats before the diagram exists — ungrounded threat
38
+ lists are the most common failure of this exercise.
39
+
40
+ 1. **Scope and assets.** State what is in and out of scope. List the assets worth protecting and rank
41
+ them. Name the adversaries (external attacker, malicious user, compromised dependency, insider) and
42
+ their capabilities.
43
+ 2. **Build the data-flow diagram (DFD).** Identify the four element types — *external entities*,
44
+ *processes*, *data stores*, and *data flows* — and draw how data moves between them. Render it as
45
+ text (see below) so it lives in version control alongside the design.
46
+ 3. **Mark trust boundaries.** Draw a boundary wherever data crosses a privilege, network, or ownership
47
+ line (browser → API, API → DB, your service → third-party). Every flow that crosses a boundary is a
48
+ prime target.
49
+ 4. **Enumerate threats with STRIDE.** For each element, walk the six categories. Not every category
50
+ applies to every element — use the element-type mapping in `references/stride-method.md`.
51
+
52
+ | STRIDE category | Violates | Typical threat |
53
+ |---|---|---|
54
+ | **S**poofing | Authentication | attacker impersonates a user or service |
55
+ | **T**ampering | Integrity | request/data/store is modified in transit or at rest |
56
+ | **R**epudiation | Non-repudiation | actor denies an action; no audit trail |
57
+ | **I**nformation disclosure | Confidentiality | data leaks to an unauthorized party |
58
+ | **D**enial of service | Availability | resource is exhausted or made unavailable |
59
+ | **E**levation of privilege | Authorization | actor gains rights they shouldn't have |
60
+
61
+ 5. **Rate each threat.** Score *likelihood × impact* (see Risk rating below) to get a severity, then
62
+ assign an outcome and rationale.
63
+ 6. **Specify mitigations.** Map each *mitigate* decision to a concrete, testable control. Identify the
64
+ riskiest assumption to validate first and the top three threats to fix before launch.
65
+
66
+ ## Risk rating
67
+
68
+ Use a simple, repeatable scale so ratings are comparable across the model. Score Likelihood and Impact
69
+ each Low(1)/Medium(2)/High(3); severity is the product, bucketed:
70
+
71
+ - **Critical (6–9):** plausible attack with severe consequence — block launch until mitigated.
72
+ - **High (3–4):** likely or high-impact — fix before release where feasible.
73
+ - **Medium (2):** fix soon; track explicitly.
74
+ - **Low (1):** accept or monitor; document the rationale.
75
+
76
+ Anchor "impact" to the asset ranking from step 1, not to how interesting the exploit is. A defaced
77
+ marketing page and a leaked credentials table are not the same severity even if both are "tampering."
78
+
79
+ ## Output format
80
+
81
+ Produce the model in this order. Keep it tight — depth belongs in the linked references, not inline.
82
+
83
+ 1. **Scope & assets** — in/out of scope, ranked assets, adversaries.
84
+ 2. **Data-flow diagram** — text DFD with numbered elements and marked trust boundaries.
85
+ 3. **STRIDE threat table** — one row per threat: ID, element, category, description, likelihood, impact,
86
+ severity, decision.
87
+ 4. **Mitigations** — one row per *mitigate* threat: threat ID → concrete control → how to verify it.
88
+ 5. **Accepted/transferred risks** — explicit, each with rationale and owner.
89
+ 6. **Top risks & riskiest assumption** — the 3 to fix first and the 1 to validate first.
90
+
91
+ ### Threat table shape
92
+
93
+ ```text
94
+ | ID | Element | STRIDE | Threat | L | I | Sev | Decision |
95
+ |-----|--------------------|--------|-----------------------------------------|---|---|-----|-----------|
96
+ | T1 | (4) API → DB flow | T | SQL injection via order_id param | 3 | 3 | 9 | Mitigate |
97
+ | T2 | (2) Auth process | S | Credential stuffing on /login | 3 | 2 | 6 | Mitigate |
98
+ | T3 | (5) Audit log | R | User denies refund; no signed audit row | 2 | 2 | 4 | Mitigate |
99
+ | T4 | (3) Session store | I | Session token readable in Redis at rest | 2 | 3 | 6 | Mitigate |
100
+ | T5 | (1) Public CDN | D | Cache-busting flood exhausts origin | 2 | 2 | 4 | Accept |
101
+ ```
102
+
103
+ ### DFD as text
104
+
105
+ ```text
106
+ TRUST BOUNDARY: Internet ││ Private network
107
+
108
+ (E1) Browser ──1: HTTPS POST /login──►││──► (P2) Auth Service ──3: query──►││──► (DS3) User DB
109
+ │ ││ │ ││
110
+ └──────2: GET /orders (JWT)──────►││──► (P4) Order API ──4: SQL──────►││──► (DS5) Orders DB
111
+ ││ │
112
+ ││ └──5: write──► (DS6) Audit Log
113
+ ││ │
114
+ ││ └──6: POST──►││──► (E7) Stripe API
115
+ Legend: (E)=external entity (P)=process (DS)=data store N: data flow ││ = trust boundary
116
+ ```
117
+
118
+ ## Common pitfalls and failure modes
119
+
120
+ - **Threats with no diagram.** Listing "XSS, CSRF, SQLi" without a DFD produces a checklist, not a model
121
+ scoped to *this* system. Always ground threats in a specific element.
122
+ - **Boiling the ocean.** Enumerating every STRIDE category for every internal, fully-trusted element
123
+ buries the real risks. Concentrate on boundary-crossing flows and high-value assets.
124
+ - **Unrated threats.** A threat without a likelihood, impact, and decision is just anxiety. Rate it or
125
+ cut it.
126
+ - **Mitigations that don't map.** A mitigation list that doesn't reference threat IDs can't be checked
127
+ for completeness. Every *mitigate* threat needs a control; every control needs a threat.
128
+ - **Silent accepted risks.** Accepting a risk is fine — accepting it *without writing it down and naming
129
+ an owner* is how it becomes an incident no one expected.
130
+ - **Confusing authn with authz.** Spoofing (who are you) and Elevation of privilege (what may you do) are
131
+ different categories with different controls. Don't collapse them.
132
+ - **Treating the model as one-and-done.** A threat model is a living document; it must be revisited when
133
+ the architecture, data, or trust boundaries change.
134
+
135
+ ## When NOT to use / boundaries
136
+
137
+ - **Not a penetration test.** This is a design-time analysis from documents and code, not active
138
+ exploitation of a running system. For live testing, hand off to a pentest engagement.
139
+ - **Not a code-level vulnerability scan.** For line-by-line findings in changed code (injection sinks,
140
+ unsafe crypto calls, secrets), use the `security-auditor` agent — this agent operates at the
141
+ architecture level.
142
+ - **Not a compliance audit.** Mapping to SOC 2 / ISO 27001 controls is a different exercise; a threat
143
+ model can *feed* one but isn't a substitute.
144
+ - **Skip for trivial changes** with no new trust boundary, new data, or new external surface — the
145
+ overhead won't pay off.
146
+ - **Don't fabricate architecture.** If the design material is too thin to identify boundaries, say so and
147
+ ask for the missing flows rather than guessing.
148
+
149
+ ## Files in this package
150
+
151
+ - `references/stride-method.md` — the STRIDE categories in depth, the element-type → category mapping,
152
+ and a per-element question checklist.
153
+ - `references/dfd-and-trust-boundaries.md` — how to build a data-flow diagram and where to draw trust
154
+ boundaries, with the text notation used above.
155
+ - `references/mitigation-catalog.md` — concrete, reusable mitigations indexed by STRIDE category.
156
+ - `examples/threat-model.md` — a complete worked threat model for a small checkout service.
157
+ - `examples/dfd-example.md` — a standalone annotated DFD with its trust boundaries explained.
158
+ - `scripts/stride-checklist.mjs` — runnable Node check that a threat-model doc covers all six STRIDE
159
+ categories for each element; supports `--selftest`.
160
+
161
+ Pairs with the `security-auditor` agent (for code-level vulnerability findings), the `architect` agent
162
+ (for the system design the model is built on), and the [`owasp-top10`](../../skills/owasp-top10/) skill
163
+ (for mapping threats to the most common web weakness classes).
@@ -0,0 +1,55 @@
1
+ # DFD Example — Annotated
2
+
3
+ A standalone data-flow diagram with its trust boundaries explained, to illustrate the notation before you
4
+ build your own. The system: a file-upload feature where users upload documents that a worker processes.
5
+
6
+ ## The diagram
7
+
8
+ ```text
9
+ TRUST BOUNDARY A: Internet ││ App tier TRUST BOUNDARY B: App tier ┊┊ Worker tier
10
+
11
+ (E1) User ──1: HTTPS PUT /files (JWT)──►││──► (P2) Upload API ──2: store object──►││──► (DS3) Object Store
12
+ ││ │ ││
13
+ ││ └──3: enqueue job────────────►││──► (DS4) Job Queue
14
+ ││ ┊┊
15
+ ││ (P5) Worker ◄──4: dequeue──┊┊── (DS4) Job Queue
16
+ ││ │
17
+ ││ └──5: read object──► (DS3) Object Store
18
+ ││ │
19
+ ││ └──6: write result──► (DS6) Results DB
20
+
21
+ Legend: (E)=external entity (P)=process (DS)=data store
22
+ N: numbered data flow ││ = network/privilege boundary ┊┊ = process/tier boundary
23
+ ```
24
+
25
+ ## Why the boundaries are where they are
26
+
27
+ - **Boundary A (Internet → App tier):** flow 1 carries untrusted, attacker-controllable input — the file
28
+ bytes, the filename, the content-type header, and the JWT. Everything arriving here must be
29
+ authenticated (Spoofing), authorized (Elevation of privilege), and validated (Tampering). This is the
30
+ single most important boundary in the system.
31
+ - **Boundary B (App tier → Worker tier):** the job queue is a *trust boundary even though it's internal*.
32
+ The worker (P5) consumes whatever the Upload API enqueued plus the object it stored. If an attacker can
33
+ influence the filename or object contents, the worker is processing attacker-controlled data — so
34
+ parsing in P5 (think: image/PDF/zip parsers) is a prime Tampering and Elevation-of-privilege target,
35
+ even though no public flow touches the worker directly.
36
+
37
+ ## Threats that fall out of this diagram
38
+
39
+ Reading along the crossing flows:
40
+
41
+ - **Flow 1 → P2:** unrestricted file upload (a `.php`/`.svg` masquerading as an image) → Elevation of
42
+ privilege / stored XSS. Path traversal in the filename → Tampering of the object store.
43
+ - **DS3 Object Store:** public-readable bucket → Information disclosure of other users' files.
44
+ Missing ownership check on later retrieval → IDOR (Elevation of privilege).
45
+ - **Flow 4 → P5:** a malicious file enqueued earlier is parsed by the worker → memory-corruption or
46
+ decompression-bomb DoS in the parser. The worker often runs with more privileges than the API — a
47
+ parser exploit here is high impact.
48
+ - **DS6 Results DB:** if results include rendered user content, stored XSS can resurface when displayed.
49
+
50
+ ## Takeaways
51
+
52
+ 1. Internal queues and worker tiers are still behind trust boundaries — model them.
53
+ 2. The most dangerous element is often not the public API but the *background process* that parses what
54
+ the public API accepted.
55
+ 3. Number flows so the threat table can reference them unambiguously (e.g. "T-flow1-E", "T-flow4-T").
@@ -0,0 +1,81 @@
1
+ # Threat Model — "QuickCheckout" Checkout Service
2
+
3
+ A complete, worked threat model for a small checkout service. Use it as a template for shape and depth.
4
+
5
+ ## 1. Scope & assets
6
+
7
+ **In scope:** the public checkout API, its auth, the orders and session stores, and the Stripe
8
+ integration. **Out of scope:** the marketing site, internal analytics pipeline.
9
+
10
+ **Assets (ranked):**
11
+ 1. Customers' stored payment method tokens and order/PII data — highest value.
12
+ 2. Account credentials / session tokens.
13
+ 3. Integrity of order and refund records (financial correctness).
14
+ 4. Service availability during a sale.
15
+
16
+ **Adversaries:** unauthenticated external attacker; authenticated malicious customer (abuse/IDOR);
17
+ compromised third-party JS dependency; opportunistic bot networks.
18
+
19
+ ## 2. Data-flow diagram
20
+
21
+ ```text
22
+ TRUST BOUNDARY: Internet ││ Private network
23
+
24
+ (E1) Browser ──1: POST /login──────────►││──► (P2) Auth Service ──3: read/write──►││──► (DS3) User DB
25
+ │ ││ │ ││
26
+ │ ││ └──4: read/write session──────►││──► (DS4) Session Cache
27
+ │ ││
28
+ └──2: POST /checkout (JWT)─────────►││──► (P5) Order API ──6: SQL────────────►││──► (DS6) Orders DB
29
+ ││ │
30
+ ││ ├──7: append──────────────────►││──► (DS7) Audit Log
31
+ ││ │
32
+ ││ └──8: POST /charge─────────────►││──► (E8) Stripe API
33
+ Legend: (E)=external entity (P)=process (DS)=data store N: flow ││ = trust boundary
34
+ ```
35
+
36
+ ## 3. STRIDE threat table
37
+
38
+ ```text
39
+ | ID | Element | STRIDE | Threat | L | I | Sev | Decision |
40
+ |-----|----------------------|--------|-------------------------------------------------|---|---|-----|-----------|
41
+ | T1 | (2) /checkout flow | T | SQL injection via cart item id into Orders DB | 3 | 3 | 9 | Mitigate |
42
+ | T2 | (P2) Auth Service | S | Credential stuffing against /login | 3 | 2 | 6 | Mitigate |
43
+ | T3 | (2) /checkout (JWT) | E | IDOR: user A submits order referencing user B | 3 | 3 | 9 | Mitigate |
44
+ | T4 | (DS4) Session Cache | I | Session tokens readable in Redis at rest | 2 | 3 | 6 | Mitigate |
45
+ | T5 | (DS7) Audit Log | R | User disputes refund; log row is editable | 2 | 2 | 4 | Mitigate |
46
+ | T6 | (8) Stripe flow | I | Card data passes through our server unnecessarily| 2 | 3 | 6 | Avoid |
47
+ | T7 | (P5) Order API | D | Checkout flood exhausts DB connection pool | 2 | 2 | 4 | Mitigate |
48
+ | T8 | (E1) Browser | T | Compromised third-party JS skims card form | 2 | 3 | 6 | Mitigate |
49
+ | T9 | (P2) Auth Service | I | Verbose error reveals which emails are registered| 2 | 1 | 2 | Mitigate |
50
+ ```
51
+
52
+ ## 4. Mitigations
53
+
54
+ ```text
55
+ | Threat | Control | Verify by |
56
+ |--------|----------------------------------------------------------------------|--------------------------------------------|
57
+ | T1 | Parameterized queries only; reject non-ULID item ids at boundary | Static check + injection test in CI |
58
+ | T2 | Per-account + per-IP rate limit, lockout, MFA option | Load test login; assert 429 after N tries |
59
+ | T3 | Server-side ownership check: order.user_id == token.sub on every read | Authz test: user A cannot fetch B's order |
60
+ | T4 | Encrypt session cache at rest; short TTL; rotate on privilege change | Confirm KMS-backed encryption; TTL config |
61
+ | T5 | Append-only audit store; logs outside app write path; signed rows | Attempt UPDATE on audit row → denied |
62
+ | T7 | Bounded conn pool + per-key rate limit + queue with back-pressure | Stress test; assert graceful 429, no crash |
63
+ | T8 | Use Stripe-hosted fields/iframe; SRI on third-party scripts; CSP | CSP report-only in staging; SRI hashes set |
64
+ | T9 | Generic "invalid credentials" response; constant-time compare | Test login with unknown vs known email |
65
+ ```
66
+
67
+ ## 5. Accepted / transferred risks
68
+
69
+ - **T6 (avoided):** card data will never transit our servers — we use Stripe Elements so the browser
70
+ posts card details directly to Stripe. This *avoids* the threat (and most PCI scope) rather than
71
+ mitigating it. Owner: Payments lead.
72
+ - **Volumetric DDoS at the network layer:** transferred to the CDN/WAF provider; accepted residual risk
73
+ of brief degradation during an extreme flood. Owner: SRE on-call.
74
+
75
+ ## 6. Top risks & riskiest assumption
76
+
77
+ **Fix before launch:** T1 (SQLi, sev 9), T3 (IDOR, sev 9), then T2 (credential stuffing, sev 6).
78
+
79
+ **Riskiest assumption to validate first:** that the JWT `sub` claim is validated server-side on *every*
80
+ order read and write. If any handler trusts a client-supplied `user_id` instead, T3 is exploitable
81
+ regardless of the other controls — verify this first.
@@ -0,0 +1,76 @@
1
+ # Data-Flow Diagrams and Trust Boundaries
2
+
3
+ A threat model is only as good as the diagram it sits on. The data-flow diagram (DFD) is the map; trust
4
+ boundaries are where the dangerous neighborhoods are. Build the diagram first, then hunt threats along
5
+ the boundaries.
6
+
7
+ ## The four element types
8
+
9
+ Every DFD is built from exactly four kinds of element. Keep them distinct — the element type determines
10
+ which STRIDE categories apply (see `stride-method.md`).
11
+
12
+ | Element | What it is | Notation here |
13
+ |---|---|---|
14
+ | **External entity** | An actor outside your control: a user, a browser, a third-party API | `(E1) Browser` |
15
+ | **Process** | Code that transforms data: a service, a Lambda, a function | `(P2) Auth Service` |
16
+ | **Data store** | Where data rests: a DB, cache, queue, bucket, file | `(DS3) User DB` |
17
+ | **Data flow** | Data in motion between two elements | `──1: HTTPS POST──►` |
18
+
19
+ Number every element and every flow. Threat IDs reference these numbers, which is what makes the model
20
+ auditable: anyone can check that flow 4 has been considered.
21
+
22
+ ## What a trust boundary is
23
+
24
+ A trust boundary is any line where the level of trust changes — where data or control passes from a
25
+ less-trusted zone into a more-trusted one. Threats concentrate here because this is where an attacker on
26
+ the outside tries to influence the inside.
27
+
28
+ Draw a boundary at:
29
+
30
+ - **Network edges** — Internet → DMZ → internal network.
31
+ - **Privilege changes** — unauthenticated → authenticated; user → admin; user-space → kernel.
32
+ - **Ownership changes** — your service → a third-party API; first-party → vendor SDK.
33
+ - **Process/host edges** — browser → server; container → host; tenant A → tenant B in multi-tenancy.
34
+ - **Data sensitivity changes** — public data → PII/PCI/PHI store.
35
+
36
+ The classic mistake is drawing too few boundaries. A monolith still has a boundary between the
37
+ unauthenticated request handler and the authenticated business logic.
38
+
39
+ ## Text notation
40
+
41
+ Render the DFD as text so it lives in version control next to the design and diffs cleanly. The
42
+ convention used across this package:
43
+
44
+ ```text
45
+ TRUST BOUNDARY: <less trusted> ││ <more trusted>
46
+
47
+ (E1) Entity ──N: flow label──►││──► (Pn) Process ──M: flow──►││──► (DSn) Store
48
+ Legend: (E)=external entity (P)=process (DS)=data store
49
+ N: numbered data flow ││ = trust boundary crossing
50
+ ```
51
+
52
+ - `││` marks each point where a flow crosses a boundary. A flow with no `││` stays inside one trust zone.
53
+ - Keep labels verb-or-protocol oriented (`HTTPS POST /login`, `SQL query`, `publish to queue`) so the
54
+ reader knows what crosses.
55
+
56
+ ## Reading threats off the diagram
57
+
58
+ Once boundaries are marked, the highest-value work is mechanical:
59
+
60
+ 1. **List every flow that crosses a `││`.** These are your priority targets.
61
+ 2. For each crossing flow, the **destination process** is where untrusted input lands — apply Tampering,
62
+ Information disclosure, DoS, and Elevation of privilege there.
63
+ 3. For each **data store**, ask what happens if the flow writing to it is malicious (Tampering) or the
64
+ store leaks (Information disclosure).
65
+ 4. For each **external entity**, ask how it's authenticated (Spoofing) and whether its actions are
66
+ logged (Repudiation).
67
+
68
+ ## Common diagram mistakes
69
+
70
+ - **Missing the return flow.** Responses cross boundaries too and can leak data (Information disclosure).
71
+ - **Collapsing distinct stores.** "The database" might be a user table, a session cache, and an audit log
72
+ with very different sensitivity — model them separately.
73
+ - **Hiding third parties.** A payment processor or auth provider is an external entity behind a trust
74
+ boundary; its compromise or outage is in scope.
75
+ - **No boundary inside the server.** Authenticated vs. unauthenticated handlers, or user vs. admin paths,
76
+ are boundaries even on one host.
@@ -0,0 +1,77 @@
1
+ # Mitigation Catalog
2
+
3
+ Reusable, concrete mitigations indexed by STRIDE category. Use these as a starting point — then make each
4
+ one *specific* to the threat it addresses (name the endpoint, the field, the store). A mitigation that
5
+ could be copy-pasted into any model unchanged is too vague to verify.
6
+
7
+ Every mitigation should be **testable**: you should be able to write a test or a check that proves it is
8
+ present and working.
9
+
10
+ ## Spoofing → strengthen authentication
11
+
12
+ | Control | Notes |
13
+ |---|---|
14
+ | Strong authentication (OIDC/OAuth2, WebAuthn) | Avoid rolling your own; use established protocols |
15
+ | MFA on sensitive accounts and actions | Step-up auth for high-value operations (transfers, role changes) |
16
+ | Mutual TLS for service-to-service | Each service proves its identity, not just the client |
17
+ | Short-lived, signed tokens (JWT with `exp`, audience, issuer checks) | Validate signature, expiry, `aud`, `iss` server-side every request |
18
+ | Anti-automation on login (rate limit, lockout, CAPTCHA/proof-of-work) | Defends credential stuffing and brute force |
19
+
20
+ ## Tampering → protect integrity
21
+
22
+ | Control | Notes |
23
+ |---|---|
24
+ | TLS for all data in transit | Prevents on-path modification |
25
+ | Server-side input validation against an allow-list/schema | Validate at the trust boundary, before use; never trust client checks |
26
+ | Parameterized queries / prepared statements | Eliminates SQL injection tampering |
27
+ | HMAC or digital signatures on critical messages | Detects modification of webhooks, tokens, inter-service messages |
28
+ | Integrity checks on stored data (checksums, append-only stores) | Detect or prevent at-rest modification |
29
+ | Subresource Integrity (SRI) on third-party scripts | Detects tampered CDN assets |
30
+
31
+ ## Repudiation → ensure accountability
32
+
33
+ | Control | Notes |
34
+ |---|---|
35
+ | Tamper-evident audit log of security-relevant actions | Append-only or signed; actor, action, timestamp, before/after |
36
+ | Logs stored outside the actor's control | An admin should not be able to edit logs of their own actions |
37
+ | Synchronized, trusted timestamps | NTP; record server time, not client-claimed time |
38
+ | Correlation/request IDs across services | Reconstruct an action end-to-end |
39
+
40
+ ## Information disclosure → enforce confidentiality
41
+
42
+ | Control | Notes |
43
+ |---|---|
44
+ | Encryption at rest for sensitive stores | DB/disk/bucket encryption; manage keys in a KMS |
45
+ | TLS in transit (see Tampering) | Confidentiality + integrity together |
46
+ | Least-privilege data access; field-level authz | Return only what the caller is entitled to |
47
+ | Generic error messages externally; detail in server logs only | Don't leak stack traces, SQL, or existence (404 vs 403) |
48
+ | Scrub secrets/PII from logs and telemetry | Redact tokens, card numbers, emails before logging |
49
+ | Avoid IDOR | Check resource *ownership*, not just authentication |
50
+
51
+ ## Denial of service → preserve availability
52
+
53
+ | Control | Notes |
54
+ |---|---|
55
+ | Rate limiting and quotas per client/key | Return `429` + `Retry-After`; defend per-tenant |
56
+ | Timeouts and circuit breakers on outbound calls | Stop a slow dependency from exhausting your threads |
57
+ | Input size and complexity limits | Cap payload size, page size, query depth, regex complexity (ReDoS) |
58
+ | Resource pooling and back-pressure | Bounded queues; shed load instead of collapsing |
59
+ | CDN/WAF and autoscaling for public surfaces | Absorb volumetric floods upstream |
60
+
61
+ ## Elevation of privilege → enforce authorization
62
+
63
+ | Control | Notes |
64
+ |---|---|
65
+ | Centralized, server-side authorization on every action | Deny by default; never rely on hidden UI or client checks |
66
+ | Principle of least privilege for processes and tokens | Minimal DB grants, scoped tokens, no ambient admin |
67
+ | Sandboxing / isolation of untrusted input handling | Separate parsing/deserialization from privileged logic |
68
+ | Avoid unsafe deserialization, template injection, path traversal | Allow-list types/paths; canonicalize before checks |
69
+ | Re-check authz after any state or role change | Don't cache a stale privilege decision across a privilege change |
70
+
71
+ ## Choosing among controls
72
+
73
+ - Prefer **eliminating** a threat (remove the feature/flow) over mitigating it.
74
+ - Prefer a **single well-placed control at the trust boundary** over many scattered patches.
75
+ - Layer controls so the failure of one (a bypassed WAF, a leaked token) is not total (defense in depth).
76
+ - For any threat you choose **not** to mitigate, record it as an accepted/transferred risk with a named
77
+ owner and rationale — see `AGENT.md` output format.