@jaimevalasek/aioson 1.17.3 → 1.19.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.
- package/CHANGELOG.md +13 -0
- package/README.md +85 -51
- package/docs/en/3-recipes/full-feature-with-sheldon.md +1 -1
- package/docs/en/5-reference/cli-reference.md +4 -4
- package/docs/en/5-reference/qa-browser.md +2 -2
- package/docs/en/README.md +1 -1
- package/docs/en/deyvin-subtask-scout/how-to-use.md +2 -2
- package/docs/en/deyvin-subtask-scout/sub-task-scout.md +3 -3
- package/docs/en/deyvin-subtask-scout/troubleshooting.md +1 -1
- package/docs/pt/3-receitas/publicar-no-aioson-com.md +17 -0
- package/docs/pt/5-referencia/comandos-cli.md +2 -2
- package/docs/pt/5-referencia/inteligencia-adaptativa.md +3 -3
- package/docs/pt/5-referencia/skills.md +1 -1
- package/docs/pt/5-referencia/web3.md +3 -3
- package/docs/pt/README.md +1 -1
- package/docs/pt/_arquivo/README.md +1 -1
- package/docs/pt/_arquivo/cenarios.md +31 -31
- package/docs/pt/_arquivo/design-hybrid-forge.md +5 -5
- package/docs/pt/_arquivo/guia-engineer.md +1 -1
- package/docs/pt/_arquivo/profiler-system.md +1 -1
- package/docs/pt/_arquivo/site-forge.md +16 -16
- package/docs/pt/_arquivo/squad-genome.md +2 -2
- package/docs/pt/agentes.md +37 -37
- package/docs/pt/deyvin-subtask-scout/como-usar.md +2 -2
- package/docs/pt/deyvin-subtask-scout/sub-task-scout.md +1 -1
- package/docs/pt/deyvin-subtask-scout/troubleshooting.md +1 -1
- package/docs/pt/living-memory/README.md +1 -1
- package/docs/pt/living-memory/memoria-viva.md +2 -2
- package/docs/pt/living-memory/reflexao-in-harness.md +1 -1
- package/docs/pt/living-memory/troubleshooting.md +6 -6
- package/package.json +1 -1
- package/src/cli.js +111 -7
- package/src/commands/gate-approve.js +56 -1
- package/src/commands/live.js +81 -54
- package/src/commands/op-capture.js +27 -2
- package/src/commands/op-list.js +33 -1
- package/src/commands/store-system.js +4 -0
- package/src/commands/tool-capabilities.js +14 -10
- package/src/commands/workflow-heal.js +47 -1
- package/src/constants.js +73 -0
- package/src/i18n/messages/en.js +20 -2
- package/src/i18n/messages/es.js +18 -1
- package/src/i18n/messages/fr.js +18 -1
- package/src/i18n/messages/pt-BR.js +20 -2
- package/src/lib/dev-resume.js +6 -1
- package/src/lib/tool-capabilities.js +64 -37
- package/src/operator-memory/decision.js +11 -4
- package/src/operator-memory/proposal.js +11 -7
- package/src/session-handoff.js +52 -1
- package/template/.aioson/agents/analyst.md +33 -1
- package/template/.aioson/agents/architect.md +33 -1
- package/template/.aioson/agents/briefing.md +23 -0
- package/template/.aioson/agents/orchestrator.md +26 -0
- package/template/.aioson/agents/pentester.md +66 -14
- package/template/.aioson/agents/pm.md +18 -1
- package/template/.aioson/agents/product.md +11 -0
- package/template/.aioson/agents/sheldon.md +21 -1
- package/template/.aioson/agents/tester.md +114 -1
- package/template/.aioson/docs/pentester/browser-dast-playbook.md +398 -0
- package/template/.aioson/rules/agent-structural-contract.md +139 -0
- package/template/.aioson/skills/process/decision-presentation/SKILL.md +2 -2
- package/template/.claude/commands/aioson/agent/analyst.md +16 -5
- package/template/.claude/commands/aioson/agent/architect.md +17 -5
- package/template/.claude/commands/aioson/agent/briefing.md +16 -5
- package/template/.claude/commands/aioson/agent/committer.md +16 -5
- package/template/.claude/commands/aioson/agent/copywriter.md +16 -5
- package/template/.claude/commands/aioson/agent/design-hybrid-forge.md +16 -5
- package/template/.claude/commands/aioson/agent/dev.md +18 -5
- package/template/.claude/commands/aioson/agent/deyvin.md +16 -5
- package/template/.claude/commands/aioson/agent/discover.md +16 -5
- package/template/.claude/commands/aioson/agent/discovery-design-doc.md +16 -5
- package/template/.claude/commands/aioson/agent/genome.md +16 -5
- package/template/.claude/commands/aioson/agent/neo.md +16 -5
- package/template/.claude/commands/aioson/agent/orache.md +16 -5
- package/template/.claude/commands/aioson/agent/orchestrator.md +21 -5
- package/template/.claude/commands/aioson/agent/pair.md +16 -5
- package/template/.claude/commands/aioson/agent/pentester.md +22 -5
- package/template/.claude/commands/aioson/agent/pm.md +20 -5
- package/template/.claude/commands/aioson/agent/product.md +16 -5
- package/template/.claude/commands/aioson/agent/profiler-enricher.md +16 -5
- package/template/.claude/commands/aioson/agent/profiler-forge.md +16 -5
- package/template/.claude/commands/aioson/agent/profiler-researcher.md +16 -5
- package/template/.claude/commands/aioson/agent/qa.md +16 -5
- package/template/.claude/commands/aioson/agent/setup.md +16 -5
- package/template/.claude/commands/aioson/agent/sheldon.md +16 -5
- package/template/.claude/commands/aioson/agent/site-forge.md +16 -5
- package/template/.claude/commands/aioson/agent/squad.md +16 -5
- package/template/.claude/commands/aioson/agent/tester.md +16 -5
- package/template/.claude/commands/aioson/agent/ux-ui.md +19 -5
- package/template/.claude/commands/aioson/agent/validator.md +17 -5
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Pentester browser DAST playbook — Playwright-based dynamic security probes for app_target surface TS-A08 (browser_exposure). Load when review_contract.target_mode = app_target AND the application has a browser-accessible UI."
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Pentester — Browser DAST Playbook
|
|
6
|
+
|
|
7
|
+
Load this when `review_contract.target_mode = app_target` AND the target application serves a browser-accessible UI (web app, SPA, SSR page).
|
|
8
|
+
|
|
9
|
+
## Prerequisites
|
|
10
|
+
|
|
11
|
+
1. Application must be running and accessible at a known URL.
|
|
12
|
+
2. Playwright installed: `npm install -g playwright && npx playwright install chromium`
|
|
13
|
+
3. Verify readiness: `aioson qa:doctor`
|
|
14
|
+
|
|
15
|
+
## Phase 0 — Baseline DAST (mandatory pre-step)
|
|
16
|
+
|
|
17
|
+
Before running any manual Playwright probe, execute the AIOSON automated DAST baseline:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Full run with hacker persona (secrets, XSS, IDOR, open redirect, SQL injection, debug routes)
|
|
21
|
+
aioson qa:run --persona=hacker --url=<target-url>
|
|
22
|
+
|
|
23
|
+
# Autonomous crawl scan (discovers routes, probes each one)
|
|
24
|
+
aioson qa:scan --url=<target-url> --depth=3 --max-pages=50
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Read `aios-qa-report.json` and import any `critical` or `high` findings into the pentester findings artifact as `status: needs_validation`. The pentester validates or reclassifies each — `qa:run` automates detection, pentester applies adversarial judgment.
|
|
28
|
+
|
|
29
|
+
**Do NOT skip Phase 0.** The automated baseline catches low-hanging fruit (exposed secrets, accessible .env files, basic XSS) without burning manual probe time. Phase 1+ targets what automation misses.
|
|
30
|
+
|
|
31
|
+
## Phase 1 — Security Headers Audit
|
|
32
|
+
|
|
33
|
+
Navigate to the target URL with Playwright and capture response headers on the main document request.
|
|
34
|
+
|
|
35
|
+
### Mandatory headers to check
|
|
36
|
+
|
|
37
|
+
| Header | Expected | Severity if missing/weak |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| `Content-Security-Policy` | Present, no `unsafe-inline` for scripts, no `unsafe-eval` | `high` if missing entirely, `medium` if has `unsafe-inline`/`unsafe-eval` |
|
|
40
|
+
| `Strict-Transport-Security` | `max-age>=31536000; includeSubDomains` | `medium` (localhost exempt) |
|
|
41
|
+
| `X-Content-Type-Options` | `nosniff` | `medium` |
|
|
42
|
+
| `X-Frame-Options` | `DENY` or `SAMEORIGIN` (check CSP `frame-ancestors` too) | `medium` |
|
|
43
|
+
| `Referrer-Policy` | `strict-origin-when-cross-origin` or stricter | `low` |
|
|
44
|
+
| `Permissions-Policy` | Present, restricts `camera`, `microphone`, `geolocation` at minimum | `low` |
|
|
45
|
+
| `X-XSS-Protection` | `0` (modern recommendation — CSP supersedes; `1; mode=block` causes info leaks in old IE) | `info` |
|
|
46
|
+
|
|
47
|
+
### Headers that SHOULD NOT be present
|
|
48
|
+
|
|
49
|
+
| Header | Why | Severity |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| `Server` with version (e.g. `nginx/1.24.0`) | Reveals infrastructure version — aids targeted exploits | `low` |
|
|
52
|
+
| `X-Powered-By` | Reveals framework (Express, PHP, ASP.NET) | `low` |
|
|
53
|
+
| `X-AspNet-Version` / `X-AspNetMvc-Version` | .NET version disclosure | `low` |
|
|
54
|
+
|
|
55
|
+
### Playwright probe pattern
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
const response = await page.goto(targetUrl, { waitUntil: 'domcontentloaded' });
|
|
59
|
+
const headers = response.headers();
|
|
60
|
+
|
|
61
|
+
// Check presence and value of each security header
|
|
62
|
+
const csp = headers['content-security-policy'] || '';
|
|
63
|
+
const hsts = headers['strict-transport-security'] || '';
|
|
64
|
+
const xcto = headers['x-content-type-options'] || '';
|
|
65
|
+
const xfo = headers['x-frame-options'] || '';
|
|
66
|
+
const rp = headers['referrer-policy'] || '';
|
|
67
|
+
const pp = headers['permissions-policy'] || '';
|
|
68
|
+
|
|
69
|
+
// Disclosure headers (should NOT be present with version info)
|
|
70
|
+
const server = headers['server'] || '';
|
|
71
|
+
const poweredBy = headers['x-powered-by'] || '';
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**ASVS:** V3.4 (CSP), V12.1 (HSTS), V13.1.5 (security headers), V14.3.3 (server disclosure).
|
|
75
|
+
|
|
76
|
+
## Phase 2 — Cookie Security Audit
|
|
77
|
+
|
|
78
|
+
After authentication (if credentials are available), inspect all cookies set by the application.
|
|
79
|
+
|
|
80
|
+
### Required attributes for session/auth cookies
|
|
81
|
+
|
|
82
|
+
| Attribute | Expected | Severity if missing |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| `Secure` | `true` (except localhost) | `high` |
|
|
85
|
+
| `HttpOnly` | `true` for session tokens | `high` |
|
|
86
|
+
| `SameSite` | `Lax` or `Strict` | `medium` |
|
|
87
|
+
| `Path` | Narrowest scope needed (prefer `/` only if necessary) | `info` |
|
|
88
|
+
| `__Host-` prefix | Recommended for session cookies — enforces Secure + Path=/ + no Domain | `info` |
|
|
89
|
+
| `__Secure-` prefix | Alternative — enforces Secure flag | `info` |
|
|
90
|
+
| Max-Age / Expires | Session cookies should not persist beyond browser close unless explicitly justified | `low` |
|
|
91
|
+
|
|
92
|
+
### Playwright probe pattern
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
const cookies = await context.cookies();
|
|
96
|
+
for (const cookie of cookies) {
|
|
97
|
+
const isSession = /session|token|auth|sid|jwt/i.test(cookie.name);
|
|
98
|
+
if (isSession) {
|
|
99
|
+
// Check Secure flag
|
|
100
|
+
if (!cookie.secure) { /* HIGH finding */ }
|
|
101
|
+
// Check HttpOnly flag
|
|
102
|
+
if (!cookie.httpOnly) { /* HIGH finding */ }
|
|
103
|
+
// Check SameSite
|
|
104
|
+
if (cookie.sameSite === 'None' && !cookie.secure) { /* MEDIUM finding */ }
|
|
105
|
+
if (!cookie.sameSite || cookie.sameSite === 'None') { /* MEDIUM finding — CSRF surface */ }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**ASVS:** V7.1.1 (cookie attributes), V7.1.2 (HttpOnly), V7.1.3 (SameSite).
|
|
111
|
+
|
|
112
|
+
## Phase 3 — Client-Side Storage Audit
|
|
113
|
+
|
|
114
|
+
Check localStorage and sessionStorage for sensitive data that should never be stored client-side.
|
|
115
|
+
|
|
116
|
+
### Sensitive patterns to flag
|
|
117
|
+
|
|
118
|
+
| Pattern | Risk | Severity |
|
|
119
|
+
|---|---|---|
|
|
120
|
+
| JWT tokens (eyJ...) | Token theft via XSS gives full account takeover | `high` |
|
|
121
|
+
| API keys (sk-*, pk_*, AKIA*, AIzaSy*) | Direct API abuse | `critical` |
|
|
122
|
+
| Passwords / password hashes | Direct compromise | `critical` |
|
|
123
|
+
| PII (email + name + phone + address combined) | Privacy violation, GDPR exposure | `medium` |
|
|
124
|
+
| Credit card numbers / CVV | PCI-DSS violation | `critical` |
|
|
125
|
+
| Session IDs | Session hijacking via XSS | `high` |
|
|
126
|
+
|
|
127
|
+
### Playwright probe pattern
|
|
128
|
+
|
|
129
|
+
```javascript
|
|
130
|
+
const storageData = await page.evaluate(() => {
|
|
131
|
+
const data = { localStorage: {}, sessionStorage: {} };
|
|
132
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
133
|
+
const key = localStorage.key(i);
|
|
134
|
+
data.localStorage[key] = localStorage.getItem(key);
|
|
135
|
+
}
|
|
136
|
+
for (let i = 0; i < sessionStorage.length; i++) {
|
|
137
|
+
const key = sessionStorage.key(i);
|
|
138
|
+
data.sessionStorage[key] = sessionStorage.getItem(key);
|
|
139
|
+
}
|
|
140
|
+
return data;
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Check each value against SECRET_PATTERNS and JWT regex
|
|
144
|
+
const jwtRegex = /eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}/;
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**ASVS:** V14.1.3 (sensitive data in client storage), V8.2.2 (no sensitive data in browser storage).
|
|
148
|
+
|
|
149
|
+
## Phase 4 — CORS Misconfiguration
|
|
150
|
+
|
|
151
|
+
Test the server's CORS policy by sending requests with crafted `Origin` headers.
|
|
152
|
+
|
|
153
|
+
### Probes
|
|
154
|
+
|
|
155
|
+
1. **Wildcard origin**: send `Origin: https://evil.com` — if response has `Access-Control-Allow-Origin: *`, flag it.
|
|
156
|
+
2. **Reflected origin**: send `Origin: https://evil.com` — if response reflects `Access-Control-Allow-Origin: https://evil.com`, flag it.
|
|
157
|
+
3. **Null origin**: send `Origin: null` — some misconfigured servers allow this.
|
|
158
|
+
4. **Credentials with wildcard**: `Access-Control-Allow-Credentials: true` with `Access-Control-Allow-Origin: *` is a browser-rejected but server-misconfigured pattern.
|
|
159
|
+
5. **Subdomain regex bypass**: `Origin: https://evil-example.com` or `Origin: https://example.com.evil.com` — catches poor regex matching.
|
|
160
|
+
|
|
161
|
+
### Playwright probe pattern
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
// Playwright doesn't set custom Origin on navigation, use page.evaluate with fetch
|
|
165
|
+
const corsResult = await page.evaluate(async (targetUrl) => {
|
|
166
|
+
try {
|
|
167
|
+
const res = await fetch(targetUrl, { mode: 'cors', credentials: 'include' });
|
|
168
|
+
return {
|
|
169
|
+
acao: res.headers.get('access-control-allow-origin'),
|
|
170
|
+
acac: res.headers.get('access-control-allow-credentials')
|
|
171
|
+
};
|
|
172
|
+
} catch { return { blocked: true }; }
|
|
173
|
+
}, apiEndpoint);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
For deeper CORS testing, use `page.route()` to intercept and modify request headers, or use the Playwright `request` API directly.
|
|
177
|
+
|
|
178
|
+
**ASVS:** V4.3.1, V4.3.2 (CORS policy).
|
|
179
|
+
|
|
180
|
+
## Phase 5 — Source Map Exposure
|
|
181
|
+
|
|
182
|
+
Source maps (`.js.map`) in production reveal the full original source code, including comments, variable names, and internal logic.
|
|
183
|
+
|
|
184
|
+
### Probes
|
|
185
|
+
|
|
186
|
+
1. Capture all JS file URLs loaded by the page.
|
|
187
|
+
2. For each `*.js` URL, try fetching `*.js.map`.
|
|
188
|
+
3. Check the HTML source for `//# sourceMappingURL=` directives.
|
|
189
|
+
4. Check response headers for `SourceMap:` or `X-SourceMap:` headers.
|
|
190
|
+
|
|
191
|
+
### Playwright probe pattern
|
|
192
|
+
|
|
193
|
+
```javascript
|
|
194
|
+
const jsFiles = [];
|
|
195
|
+
page.on('response', (response) => {
|
|
196
|
+
if (response.url().endsWith('.js') && response.status() === 200) {
|
|
197
|
+
jsFiles.push(response.url());
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
await page.goto(targetUrl, { waitUntil: 'networkidle' });
|
|
202
|
+
|
|
203
|
+
for (const jsUrl of jsFiles) {
|
|
204
|
+
const mapUrl = jsUrl + '.map';
|
|
205
|
+
try {
|
|
206
|
+
const mapResponse = await page.goto(mapUrl, { waitUntil: 'commit', timeout: 3000 });
|
|
207
|
+
if (mapResponse && mapResponse.status() === 200) {
|
|
208
|
+
const body = await mapResponse.text();
|
|
209
|
+
if (body.includes('"sources"') || body.includes('"mappings"')) {
|
|
210
|
+
// HIGH finding — source map accessible
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
} catch { /* not accessible — good */ }
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**Severity:** `high` (reveals full source code including business logic, API routes, internal comments).
|
|
218
|
+
|
|
219
|
+
**Fix:** Remove source maps from production builds. Configure bundler (webpack/vite/next) to exclude `.map` files from production output, or restrict via web server rules.
|
|
220
|
+
|
|
221
|
+
## Phase 6 — Clickjacking (Frame Injection)
|
|
222
|
+
|
|
223
|
+
Test if the target page can be embedded in an iframe on an attacker-controlled domain.
|
|
224
|
+
|
|
225
|
+
### Probes
|
|
226
|
+
|
|
227
|
+
1. Check `X-Frame-Options` header (covered in Phase 1).
|
|
228
|
+
2. Check CSP `frame-ancestors` directive (more granular than X-Frame-Options).
|
|
229
|
+
3. If neither is set, attempt to iframe the page:
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
// Create a test page that iframes the target
|
|
233
|
+
await page.setContent(`
|
|
234
|
+
<iframe id="target" src="${targetUrl}" width="800" height="600"></iframe>
|
|
235
|
+
`);
|
|
236
|
+
await page.waitForTimeout(2000);
|
|
237
|
+
|
|
238
|
+
const iframeLoaded = await page.evaluate(() => {
|
|
239
|
+
const iframe = document.getElementById('target');
|
|
240
|
+
try {
|
|
241
|
+
// Cross-origin iframe access will throw — but loading without error means framing is allowed
|
|
242
|
+
return iframe.contentWindow.location.href !== 'about:blank';
|
|
243
|
+
} catch { return true; } // cross-origin = loaded but blocked by same-origin policy (still frameable)
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**ASVS:** V3.7 (clickjacking), V13.1.5 (frame protection).
|
|
248
|
+
|
|
249
|
+
## Phase 7 — Subresource Integrity (SRI)
|
|
250
|
+
|
|
251
|
+
Scripts and stylesheets loaded from CDNs or third-party origins should have `integrity` attributes to prevent supply-chain attacks (CDN compromise, DNS hijacking).
|
|
252
|
+
|
|
253
|
+
### Probes
|
|
254
|
+
|
|
255
|
+
```javascript
|
|
256
|
+
const sriIssues = await page.evaluate(() => {
|
|
257
|
+
const issues = [];
|
|
258
|
+
const scripts = document.querySelectorAll('script[src]');
|
|
259
|
+
for (const s of scripts) {
|
|
260
|
+
const src = s.getAttribute('src') || '';
|
|
261
|
+
const isExternal = src.startsWith('http') && !src.includes(window.location.hostname);
|
|
262
|
+
if (isExternal && !s.getAttribute('integrity')) {
|
|
263
|
+
issues.push({ type: 'script', src: src.substring(0, 120) });
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
const links = document.querySelectorAll('link[rel="stylesheet"][href]');
|
|
267
|
+
for (const l of links) {
|
|
268
|
+
const href = l.getAttribute('href') || '';
|
|
269
|
+
const isExternal = href.startsWith('http') && !href.includes(window.location.hostname);
|
|
270
|
+
if (isExternal && !l.getAttribute('integrity')) {
|
|
271
|
+
issues.push({ type: 'stylesheet', src: href.substring(0, 120) });
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return issues;
|
|
275
|
+
});
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
**Severity:** `medium` per external resource without SRI. `high` if the resource is a payment or auth SDK.
|
|
279
|
+
|
|
280
|
+
**ASVS:** V15.2 (SRI).
|
|
281
|
+
|
|
282
|
+
## Phase 8 — Error Page Information Disclosure
|
|
283
|
+
|
|
284
|
+
Trigger error conditions and inspect the response for framework-default error pages that leak internal information.
|
|
285
|
+
|
|
286
|
+
### Probes
|
|
287
|
+
|
|
288
|
+
1. **404 page**: navigate to a random non-existent path. Check for stack traces, framework names, file paths.
|
|
289
|
+
2. **500 trigger**: if any form/endpoint is accessible, submit malformed data designed to cause server errors.
|
|
290
|
+
3. **Verbose errors**: check if the response contains path separators (`/`, `\`), line numbers (`at line`), or framework markers (`Django`, `Rails`, `Express`, `Next.js`, `Laravel`, `Spring`).
|
|
291
|
+
|
|
292
|
+
```javascript
|
|
293
|
+
const errorPage = await page.goto(`${targetUrl}/nonexistent-${Date.now()}`, {
|
|
294
|
+
waitUntil: 'domcontentloaded', timeout: 5000
|
|
295
|
+
});
|
|
296
|
+
const errorHtml = await page.content();
|
|
297
|
+
|
|
298
|
+
const leakPatterns = [
|
|
299
|
+
/at\s+\w+\s+\(.*:\d+:\d+\)/, // JS stack trace
|
|
300
|
+
/File ".*", line \d+/, // Python traceback
|
|
301
|
+
/vendor\/.*\.php:\d+/, // PHP stack trace
|
|
302
|
+
/SQLSTATE\[/, // SQL error
|
|
303
|
+
/Traceback \(most recent/, // Python traceback header
|
|
304
|
+
/(Django|Laravel|Rails|Express|Spring|Next\.js) (Debug|Error)/i
|
|
305
|
+
];
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
**Severity:** `medium` for framework name disclosure, `high` for full stack traces with file paths.
|
|
309
|
+
|
|
310
|
+
**ASVS:** V13.1.3 (error handling), V16.2 (information disclosure).
|
|
311
|
+
|
|
312
|
+
## Phase 9 — HTML Meta & Comment Leaks
|
|
313
|
+
|
|
314
|
+
Inspect the HTML source for metadata and comments that disclose internal information.
|
|
315
|
+
|
|
316
|
+
### Probes
|
|
317
|
+
|
|
318
|
+
```javascript
|
|
319
|
+
const metaLeaks = await page.evaluate(() => {
|
|
320
|
+
const issues = [];
|
|
321
|
+
|
|
322
|
+
// Generator meta tags
|
|
323
|
+
const generator = document.querySelector('meta[name="generator"]');
|
|
324
|
+
if (generator) issues.push({ type: 'generator', value: generator.content });
|
|
325
|
+
|
|
326
|
+
// HTML comments with sensitive content
|
|
327
|
+
const walker = document.createTreeWalker(document, NodeFilter.SHOW_COMMENT);
|
|
328
|
+
while (walker.nextNode()) {
|
|
329
|
+
const text = walker.currentNode.textContent.trim();
|
|
330
|
+
if (/(TODO|FIXME|HACK|password|secret|key|token|debug)/i.test(text)) {
|
|
331
|
+
issues.push({ type: 'comment', value: text.substring(0, 100) });
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Hidden inputs with sensitive-looking names
|
|
336
|
+
const hiddenInputs = document.querySelectorAll('input[type="hidden"]');
|
|
337
|
+
for (const input of hiddenInputs) {
|
|
338
|
+
const name = input.name || '';
|
|
339
|
+
if (/(token|secret|key|csrf|nonce)/i.test(name) && input.value.length > 20) {
|
|
340
|
+
issues.push({ type: 'hidden_input', name, valueLength: input.value.length });
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return issues;
|
|
345
|
+
});
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
**Severity:** `low` for generator tags, `medium` for TODO/debug comments, `info` for CSRF tokens in hidden inputs (expected pattern, but verify they rotate).
|
|
349
|
+
|
|
350
|
+
## Integration with pentester findings artifact
|
|
351
|
+
|
|
352
|
+
Map every finding from this playbook to the standard pentester finding schema:
|
|
353
|
+
|
|
354
|
+
```json
|
|
355
|
+
{
|
|
356
|
+
"id": "SF-{slug}-NN",
|
|
357
|
+
"feature_slug": "{slug}",
|
|
358
|
+
"surface": "app_target_browser_exposure",
|
|
359
|
+
"severity": "...",
|
|
360
|
+
"title": "...",
|
|
361
|
+
"hypothesis": "Browser-based DAST probe via Playwright",
|
|
362
|
+
"preconditions": ["Application running at {url}", "Playwright + Chromium installed"],
|
|
363
|
+
"reproduction_steps": ["1. Run aioson qa:run --persona=hacker", "2. ..."],
|
|
364
|
+
"evidence": ["Response header dump", "Screenshot path"],
|
|
365
|
+
"impact": "...",
|
|
366
|
+
"affected_artifacts": ["URL or source file path"],
|
|
367
|
+
"suggested_fix": "...",
|
|
368
|
+
"recommended_owner": "dev",
|
|
369
|
+
"recommended_gate_status": "...",
|
|
370
|
+
"status": "open",
|
|
371
|
+
"safe_to_reproduce": true,
|
|
372
|
+
"asvs_ids": ["V..."]
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## Summary — probe priority order
|
|
377
|
+
|
|
378
|
+
| Phase | What | Time estimate | Severity ceiling |
|
|
379
|
+
|---|---|---|---|
|
|
380
|
+
| 0 | `qa:run --persona=hacker` + `qa:scan` baseline | 2-5 min | critical |
|
|
381
|
+
| 1 | Security headers | 30s | high |
|
|
382
|
+
| 2 | Cookie attributes | 30s | high |
|
|
383
|
+
| 3 | Client-side storage | 30s | critical |
|
|
384
|
+
| 4 | CORS misconfiguration | 1 min | high |
|
|
385
|
+
| 5 | Source map exposure | 1 min | high |
|
|
386
|
+
| 6 | Clickjacking | 30s | medium |
|
|
387
|
+
| 7 | SRI (CDN resources) | 30s | medium |
|
|
388
|
+
| 8 | Error page disclosure | 30s | high |
|
|
389
|
+
| 9 | HTML meta & comment leaks | 30s | medium |
|
|
390
|
+
|
|
391
|
+
Total additional time beyond Phase 0: ~5-6 minutes of automated probing.
|
|
392
|
+
|
|
393
|
+
## References
|
|
394
|
+
|
|
395
|
+
- OWASP ASVS 5.0: Chapters V3, V4, V7, V8, V12, V13, V14, V15, V16
|
|
396
|
+
- OWASP Testing Guide v4.2: OTG-CONFIG, OTG-INFO, OTG-SESS
|
|
397
|
+
- Mozilla Observatory scoring methodology
|
|
398
|
+
- Playwright API: https://playwright.dev/docs/api/class-response
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-structural-contract
|
|
3
|
+
description: Contrato estrutural que todo agente AIOSON deve seguir — seções obrigatórias, ordem de observabilidade, padrão de handoff, e integridade de comandos CLI
|
|
4
|
+
priority: 5
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Agent Structural Contract
|
|
9
|
+
|
|
10
|
+
Every AIOSON agent file (`template/.aioson/agents/*.md`) must comply with this structural contract. Violations are caught by `@qa` during Gate D and by `@sheldon` during enrichment reviews.
|
|
11
|
+
|
|
12
|
+
## 1. Language boundary (mandatory, line 3)
|
|
13
|
+
|
|
14
|
+
Every agent MUST start with:
|
|
15
|
+
|
|
16
|
+
```markdown
|
|
17
|
+
> **LANGUAGE BOUNDARY:** Agent instructions are canonical in English. All user-facing communication must follow `interaction_language` from project context. If it is absent, fall back to `conversation_language`.
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 2. Mandatory sections
|
|
21
|
+
|
|
22
|
+
Every agent that interacts with the user MUST have these sections (order may vary):
|
|
23
|
+
|
|
24
|
+
| Section | Purpose | Required for |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `## Mission` | What the agent does in 1-2 lines | All agents |
|
|
27
|
+
| `## Required input` | What files must be read before acting | All agents |
|
|
28
|
+
| `## Hard constraints` | Non-negotiable rules | All agents |
|
|
29
|
+
| Observability block | `agent:done` + `pulse:update` at session end | All agents |
|
|
30
|
+
|
|
31
|
+
Agents that are part of the SDD workflow additionally MUST have:
|
|
32
|
+
|
|
33
|
+
| Section | Purpose | Required for |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| Handoff section | Structured next-agent recommendation | briefing, product, sheldon, analyst, architect, pm, orchestrator |
|
|
36
|
+
| `## Feature dossier` | Dossier read/write integration | product, sheldon, analyst, architect, pm, orchestrator |
|
|
37
|
+
|
|
38
|
+
## 3. Observability command order (session end)
|
|
39
|
+
|
|
40
|
+
At session end, commands MUST appear in this exact order. Missing steps are acceptable when marked N/A — wrong order is not.
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
1. gate:approve (if this agent owns a gate — analyst=A, architect=B, pm=C, qa=D)
|
|
44
|
+
2. op:capture (if user confirmed decisions — product, sheldon, pm)
|
|
45
|
+
3. pulse:update (ALL agents — automated project-pulse update)
|
|
46
|
+
4. agent:done (ALL agents — ALWAYS LAST)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`runtime:emit` milestones happen DURING the session at strategic moments, NOT in the session-end block. Each agent should emit at least 2 milestones during execution.
|
|
50
|
+
|
|
51
|
+
### Milestone timing per agent
|
|
52
|
+
|
|
53
|
+
| Agent | Milestone 1 (emit during work) | Milestone 2 (emit during work) |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| @briefing | Briefing draft written | Briefing approved |
|
|
56
|
+
| @product | PRD written | Feature registered in features.md |
|
|
57
|
+
| @sheldon | Sizing decided | Enrichment applied |
|
|
58
|
+
| @analyst | Requirements written | Spec skeleton created |
|
|
59
|
+
| @architect | Architecture decided | Gate B check |
|
|
60
|
+
| @pm | Implementation plan written | Gate C approved |
|
|
61
|
+
| @orchestrator | Lanes initialized | Merge complete |
|
|
62
|
+
| @dev | Slice started | Slice landed |
|
|
63
|
+
| @qa | Review started | Verdict decided |
|
|
64
|
+
|
|
65
|
+
## 4. Handoff contract
|
|
66
|
+
|
|
67
|
+
Every workflow agent MUST end with a handoff block following this template:
|
|
68
|
+
|
|
69
|
+
```markdown
|
|
70
|
+
**Handoff message:**
|
|
71
|
+
```
|
|
72
|
+
[Artifact produced]: .aioson/context/[artifact].md
|
|
73
|
+
[Gate status]: Gate [X]: [approved|pending]
|
|
74
|
+
Next agent: @[name] ([condition or rationale])
|
|
75
|
+
Action: /[agent-name]
|
|
76
|
+
```
|
|
77
|
+
> Recommended: `/clear` before activating — fresh context window.
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Rules:
|
|
81
|
+
- The handoff message MUST include at least: artifact path, next agent, and rationale.
|
|
82
|
+
- `/clear` recommendation MUST be present.
|
|
83
|
+
- Do NOT continue into the next agent's work — output only the handoff and stop.
|
|
84
|
+
|
|
85
|
+
## 5. CLI error handling
|
|
86
|
+
|
|
87
|
+
Every `aioson` CLI command in an agent file MUST end with `2>/dev/null || true` to prevent silent failures from breaking the session.
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
aioson <command> . --flag=value 2>/dev/null || true
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The ONLY exception is commands inside "Quick start" or "Prerequisites" sections where the user runs them manually (not the agent).
|
|
94
|
+
|
|
95
|
+
## 6. CLI flag integrity
|
|
96
|
+
|
|
97
|
+
Agent files must reference CLI commands with correct flag names. When adding a new command reference:
|
|
98
|
+
|
|
99
|
+
1. Check `src/commands/<command>.js` for the actual option names.
|
|
100
|
+
2. Use `--flag=value` syntax (not positional arguments) for clarity.
|
|
101
|
+
3. Never guess flags — verify against the source.
|
|
102
|
+
|
|
103
|
+
Known correct signatures (reference table):
|
|
104
|
+
|
|
105
|
+
| Command | Correct flags |
|
|
106
|
+
|---|---|
|
|
107
|
+
| `gate:approve` | `--feature=<slug> --gate=<A\|B\|C\|D>` |
|
|
108
|
+
| `gate:check` | `--feature=<slug> --gate=<A\|B\|C\|D>` |
|
|
109
|
+
| `pulse:update` | `--agent=<name> --feature=<slug> --action="<summary>" --next="<recommendation>"` |
|
|
110
|
+
| `op:capture` | `--signal=<type> --quote="<verbatim>" --proposal="<paraphrase>" --source-agent=<name>` |
|
|
111
|
+
| `brain:query` | `--tags=<csv> --min-quality=<n> --format=<compact\|json\|ids>` |
|
|
112
|
+
| `artifact:validate` | `--feature=<slug>` (NOT `--spec=<file>`) |
|
|
113
|
+
| `dossier:audit` | `--check=<template-parity\|coverage>` (NOT `--slug=<slug>`) |
|
|
114
|
+
| `dossier:add-finding` | `--slug=<slug> --agent=<name> --section="<section>" --content="<text>"` |
|
|
115
|
+
| `dossier:add-codemap` | `--slug=<slug> --file=<path> --role=<role> --coupling=<low\|medium\|high> --added-by=<agent>` |
|
|
116
|
+
| `dossier:link-rule` | `--slug=<slug> --rule=<path> --reason="<text>"` |
|
|
117
|
+
| `runtime:emit` | `--agent=<name> --type=<milestone\|gate_check> --summary="<text>"` |
|
|
118
|
+
| `memory:search` | `--query="<text>"` |
|
|
119
|
+
| `context:search` | `--query="<text>"` |
|
|
120
|
+
| `preflight` | `--agent=<name> --feature=<slug>` |
|
|
121
|
+
| `dev:state:write` | `--feature=<slug> --phase=<n> --next="<description>" --context=<tokens>` |
|
|
122
|
+
|
|
123
|
+
## 7. Template-workspace parity
|
|
124
|
+
|
|
125
|
+
Agent files in `template/.aioson/agents/` are the canonical source. Workspace files in `.aioson/agents/` are copies synced via `npm run sync:agents`.
|
|
126
|
+
|
|
127
|
+
Rules:
|
|
128
|
+
- Edits MUST be made in `template/` first, then synced to workspace.
|
|
129
|
+
- After any agent edit session, verify parity with `diff template/.aioson/agents/<file> .aioson/agents/<file>`.
|
|
130
|
+
- Drift between template and workspace is a bug — the template always wins.
|
|
131
|
+
|
|
132
|
+
## On violation detected
|
|
133
|
+
|
|
134
|
+
When an agent file violates this contract:
|
|
135
|
+
|
|
136
|
+
1. **During @qa Gate D:** flag as a Medium finding with `recommended_owner: dev`.
|
|
137
|
+
2. **During @sheldon enrichment:** flag in `sheldon-enrichment-{slug}.md` improvements list.
|
|
138
|
+
3. **During @deyvin pair session:** fix inline if the touched file is already in scope.
|
|
139
|
+
4. **Never block a feature** for structural violations alone — document and fix as follow-up.
|
|
@@ -12,7 +12,7 @@ activation: |
|
|
|
12
12
|
|
|
13
13
|
## When to use
|
|
14
14
|
|
|
15
|
-
Load this skill before the first user-facing decision in any agent that interacts directly with the user. Mandatory in V1 for: `@neo`, `@setup`, `@product`, `@dev`, `@deyvin`.
|
|
15
|
+
Load this skill before the first user-facing decision in any agent that interacts directly with the user. Mandatory in V1 for: `@neo`, `@setup`, `@product`, `@dev`, `@deyvin`, `@pentester`.
|
|
16
16
|
|
|
17
17
|
Activation mode is decided by `profile` in `project.context.md`:
|
|
18
18
|
|
|
@@ -92,7 +92,7 @@ When this skill is active, every user-facing decision produces:
|
|
|
92
92
|
|
|
93
93
|
The doctor check `jargon_leak_detection` (defined in this same feature) verifies adherence in CI:
|
|
94
94
|
|
|
95
|
-
- scope filter: only events from `[neo, setup, product, dev, deyvin]`
|
|
95
|
+
- scope filter: only events from `[neo, setup, product, dev, deyvin, pentester]`
|
|
96
96
|
- profile filter: only runs when active project has `profile=creator`
|
|
97
97
|
- success threshold: `count=0` jargon leaks in a feature MICRO completa run with `profile=creator`
|
|
98
98
|
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "AIOSON — Domain discovery and entity mapping (SMALL/MEDIUM)"
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
---
|
|
2
|
+
description: "AIOSON — Domain discovery and entity mapping (SMALL/MEDIUM)"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
If $ARGUMENTS is exactly "--help" or starts with "--help":
|
|
6
|
+
Do NOT activate the agent. Instead, display this help and stop:
|
|
7
|
+
|
|
8
|
+
@analyst — Domain discovery and entity mapping (SMALL/MEDIUM)
|
|
9
|
+
Usage: /aioson:agent:analyst [task description]
|
|
10
|
+
Requires:
|
|
11
|
+
.aioson/context/project.context.md
|
|
12
|
+
Produces: .aioson/context/discovery.md
|
|
13
|
+
Instruction file: .aioson/agents/analyst.md
|
|
14
|
+
CLI help: aioson agent:help analyst
|
|
15
|
+
|
|
16
|
+
Otherwise: Read `.aioson/agents/analyst.md` and follow all instructions. $ARGUMENTS
|
|
@@ -1,5 +1,17 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "AIOSON — Project structure and technical decisions (SMALL/MEDIUM)"
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
---
|
|
2
|
+
description: "AIOSON — Project structure and technical decisions (SMALL/MEDIUM)"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
If $ARGUMENTS is exactly "--help" or starts with "--help":
|
|
6
|
+
Do NOT activate the agent. Instead, display this help and stop:
|
|
7
|
+
|
|
8
|
+
@architect — Project structure and technical decisions (SMALL/MEDIUM)
|
|
9
|
+
Usage: /aioson:agent:architect [task description]
|
|
10
|
+
Requires:
|
|
11
|
+
.aioson/context/project.context.md
|
|
12
|
+
.aioson/context/discovery.md
|
|
13
|
+
Produces: .aioson/context/architecture.md
|
|
14
|
+
Instruction file: .aioson/agents/architect.md
|
|
15
|
+
CLI help: aioson agent:help architect
|
|
16
|
+
|
|
17
|
+
Otherwise: Read `.aioson/agents/architect.md` and follow all instructions. $ARGUMENTS
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "AIOSON — Pre-production briefings and planning"
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
---
|
|
2
|
+
description: "AIOSON — Pre-production briefings and planning"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
If $ARGUMENTS is exactly "--help" or starts with "--help":
|
|
6
|
+
Do NOT activate the agent. Instead, display this help and stop:
|
|
7
|
+
|
|
8
|
+
@briefing — Pre-production briefings and planning
|
|
9
|
+
Usage: /aioson:agent:briefing [task description]
|
|
10
|
+
Requires:
|
|
11
|
+
.aioson/context/project.context.md
|
|
12
|
+
Produces: .aioson/briefings/{slug}/
|
|
13
|
+
Instruction file: .aioson/agents/briefing.md
|
|
14
|
+
CLI help: aioson agent:help briefing
|
|
15
|
+
|
|
16
|
+
Otherwise: Read `.aioson/agents/briefing.md` and follow all instructions. $ARGUMENTS
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "AIOSON — Professional Git commit generation from changes and context"
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
---
|
|
2
|
+
description: "AIOSON — Professional Git commit generation from changes and context"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
If $ARGUMENTS is exactly "--help" or starts with "--help":
|
|
6
|
+
Do NOT activate the agent. Instead, display this help and stop:
|
|
7
|
+
|
|
8
|
+
@committer — Professional Git commit generation from changes and context
|
|
9
|
+
Usage: /aioson:agent:committer [task description]
|
|
10
|
+
Requires:
|
|
11
|
+
(none)
|
|
12
|
+
Produces: git commit(s)
|
|
13
|
+
Instruction file: .aioson/agents/committer.md
|
|
14
|
+
CLI help: aioson agent:help committer
|
|
15
|
+
|
|
16
|
+
Otherwise: Read `.aioson/agents/committer.md` and follow all instructions. $ARGUMENTS
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "AIOSON — Conversion-focused marketing copy"
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
---
|
|
2
|
+
description: "AIOSON — Conversion-focused marketing copy"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
If $ARGUMENTS is exactly "--help" or starts with "--help":
|
|
6
|
+
Do NOT activate the agent. Instead, display this help and stop:
|
|
7
|
+
|
|
8
|
+
@copywriter — Conversion-focused marketing copy
|
|
9
|
+
Usage: /aioson:agent:copywriter [task description]
|
|
10
|
+
Requires:
|
|
11
|
+
(none)
|
|
12
|
+
Produces: marketing copy + content assets
|
|
13
|
+
Instruction file: .aioson/agents/copywriter.md
|
|
14
|
+
CLI help: aioson agent:help copywriter
|
|
15
|
+
|
|
16
|
+
Otherwise: Read `.aioson/agents/copywriter.md` and follow all instructions. $ARGUMENTS
|