| name | perseus-client |
| description | Client-side security analysis (DOM XSS, React/Vue/Angular, SSR, prototype pollution) |
Perseus Client-Side Specialist
Context & Authorization
IMPORTANT: This skill performs client-side security analysis on the user's own codebase. This is defensive security testing to find browser-side vulnerabilities.
Authorization: The user owns this codebase and has explicitly requested this specialized analysis.
Multi-Framework Support
| Framework | Versions | Special Considerations |
|---|
| React | 16+, 18+, 19+ | RSC, Server Actions, JSX injection |
| Next.js | 12+, 13+, 14+, 15+ | App Router, Server Components, Middleware |
| Vue | 2, 3 | v-html, template injection |
| Angular | 12+ | bypassSecurityTrust*, template injection |
| Svelte | 3, 4, 5 | {@html}, SSR |
| SolidJS | 1.x | innerHTML, SSR |
| Vanilla JS | ES6+ | Direct DOM manipulation |
| jQuery | All | .html(), .append() |
Overview
This specialist skill performs deep client-side JavaScript security analysis, focusing on vulnerabilities in modern frameworks including React, Vue, Angular, and SSR frameworks.
When to Use: After /scan identifies significant client-side JavaScript, SPAs, or SSR applications.
Goal: Find DOM-based XSS, prototype pollution, and framework-specific vulnerabilities.
Engagement Mode Compatibility
| Mode | Specialist Behavior |
|---|
PRODUCTION_SAFE | Code-level and rendering-path analysis, minimal runtime probes |
STAGING_ACTIVE | Controlled browser-side verification with throttling |
LAB_FULL | Expanded dynamic client attack-surface validation |
LAB_RED_TEAM | End-to-end client attack-chain simulation in isolated lab |
Safety Gates (Required)
- Read
deliverables/engagement_profile.md before active runtime testing.
- Default to
PRODUCTION_SAFE when mode is not specified.
- Enforce kill-switch thresholds and stop on instability.
- Never execute persistent or user-impacting payloads in production.
Client-Side Risks Covered
| Risk | Description | Impact |
|---|
| DOM XSS | Client-side script injection | Account takeover, data theft |
| React XSS | Unsafe HTML rendering, href injection | XSS via JSX |
| SSR Injection | Server component injection | RCE, data leak |
| Prototype Pollution | Object prototype manipulation | XSS, DoS, logic bypass |
| PostMessage Abuse | Cross-origin message issues | Data leakage, XSS |
| DOM Clobbering | HTML overwriting JS variables | XSS, security bypass |
| Client Storage | Sensitive data exposure | Session hijacking |
Execution Instructions
Step 0: Mode & Scope Alignment
- Load mode/scope/limits from
deliverables/engagement_profile.md.
- Respect
deliverables/verification_scope.md when present.
- In
PRODUCTION_SAFE, prefer static and minimal observable checks only.
Phase 1: React/Next.js Security Analysis (5 Parallel Agents)
-
React XSS Analyst:
- "Find React-specific XSS vectors."
Vulnerable Patterns:
<div dangerouslySetInnerHTML={{ __html: userInput }} />
<a href={userUrl}>Click</a>
const Component = components[userInput];
return <Component />;
<div {...userProps} />
-
Next.js Server Component Analyst:
- "Analyze Next.js App Router and Server Components for security issues."
Patterns:
async function UserPage({ params }) {
const user = await db.query(`SELECT * FROM users WHERE id = ${params.id}`);
return <div>{user.name}</div>;
}
<ClientComponent apiKey={process.env.SECRET_KEY} />
import { redirect } from 'next/navigation';
redirect(userInput);
-
Next.js Server Actions Analyst:
- "Analyze Server Actions for security issues."
Patterns:
'use server'
async function deleteUser(userId: string) {
await db.users.delete(userId);
}
'use server'
async function searchUsers(query: string) {
return db.query(`SELECT * FROM users WHERE name LIKE '%${query}%'`);
}
-
Next.js Middleware Analyst:
- "Analyze Next.js middleware for security issues."
Patterns:
export function middleware(request: NextRequest) {
const url = request.nextUrl.searchParams.get('redirect');
return NextResponse.redirect(url);
}
export function middleware(request: NextRequest) {
if (request.headers.get('x-admin') === 'true') {
return NextResponse.next();
}
}
-
React State Exposure Analyst:
- "Check for sensitive data exposure in React state/props."
Patterns:
const [config, setConfig] = useState({
apiKey: 'sk-xxx',
adminToken: '...'
});
Phase 2: Vue Security Analysis (3 Parallel Agents)
-
Vue XSS Analyst:
- "Find Vue-specific XSS vectors."
Patterns:
<!-- VULNERABLE - v-html with user input -->
<div v-html="userContent"></div>
<!-- VULNERABLE - Dynamic component -->
<component :is="userComponent" />
<!-- VULNERABLE - Template compilation -->
<script>
new Vue({
template: userTemplate // If user controls this
});
</script>
<!-- VULNERABLE - javascript: in :href -->
<a :href="userUrl">Link</a>
-
Nuxt.js Analyst:
- "Analyze Nuxt.js specific security issues."
Patterns:
export default defineEventHandler((event) => {
const id = getQuery(event).id;
return db.query(`SELECT * FROM items WHERE id = ${id}`);
});
runtimeConfig: {
public: {
secretKey: process.env.SECRET
}
}
-
Vue State Analyst:
- "Check Vuex/Pinia state for sensitive data exposure."
Phase 3: Angular Security Analysis (2 Parallel Agents)
-
Angular XSS Analyst:
- "Find Angular-specific XSS vectors."
Patterns:
constructor(private sanitizer: DomSanitizer) {}
getHtml() {
return this.sanitizer.bypassSecurityTrustHtml(userInput);
}
@Component({
template: userTemplate
})
<div [innerHTML]="userContent"></div>
-
Angular SSR Analyst:
- "Analyze Angular Universal for security issues."
Phase 4: DOM XSS Analysis (4 Parallel Agents)
-
Source Identification Agent:
- "Identify all DOM XSS sources across frameworks."
Sources:
location.hash
location.search
location.href
document.URL
document.documentURI
document.referrer
localStorage.getItem()
sessionStorage.getItem()
document.cookie
window.addEventListener('message', (e) => e.data)
-
Sink Identification Agent:
- "Identify all DOM XSS sinks across frameworks."
Sinks:
element.innerHTML = data
element.outerHTML = data
document.write(data)
document.writeln(data)
$(selector).html(data)
$(selector).append(data)
$(data)
eval(data)
new Function(data)
setTimeout(data, 0)
setInterval(data, 0)
location.href = data
location.assign(data)
location.replace(data)
window.open(data)
-
Flow Tracer Agent:
- "Trace data flow from sources to sinks."
-
URL Scheme Analyst:
- "Check for javascript: and data: URL injection."
Patterns:
<a href={url}>
<iframe src={url}>
// Check validation:
if (!url.startsWith('https://')) { /* reject */ }
Phase 5: Prototype Pollution Analysis (3 Parallel Agents)
-
Pollution Source Analyst:
- "Find prototype pollution entry points."
Patterns:
function merge(target, source) {
for (let key in source) {
if (typeof source[key] === 'object') {
target[key] = merge(target[key] || {}, source[key]);
} else {
target[key] = source[key];
}
}
}
const params = Object.fromEntries(new URLSearchParams(location.search));
-
Gadget Finder Agent:
- "Find prototype pollution gadgets."
Patterns:
if (options.isAdmin) {
showAdminPanel();
}
element.setAttribute(key, config[key]);
-
Library Analyst:
- "Check for vulnerable libraries."
Phase 6: PostMessage Analysis (2 Parallel Agents)
-
PostMessage Receiver Analyst:
- "Find all postMessage listeners."
Patterns:
window.addEventListener('message', (e) => {
eval(e.data.code);
});
window.addEventListener('message', (e) => {
if (e.origin.includes('trusted.com')) {
}
});
window.addEventListener('message', (e) => {
if (e.origin !== 'https://trusted.com') return;
});
-
PostMessage Sender Analyst:
- "Check postMessage sends for data leakage."
Patterns:
parent.postMessage(sensitiveData, '*');
iframe.contentWindow.postMessage({ token: authToken }, '*');
Phase 7: Client Storage & Secrets (2 Parallel Agents)
-
Storage Security Analyst:
- "Analyze localStorage/sessionStorage usage."
Issues:
localStorage.setItem('authToken', token);
localStorage.setItem('user', JSON.stringify({
ssn: '123-45-6789',
creditCard: '4111...'
}));
-
Client Secret Analyst:
- "Find secrets in client-side code."
Patterns:
const API_KEY = 'sk-xxx';
const STRIPE_SECRET = 'sk_live_xxx';
Safe Payload Reference
| Attack | Safe Test Payload | Verification |
|---|
| DOM XSS | #<img src=x onerror=alert(1)> | Alert box appears |
| React href | javascript:alert(1) | Alert on click |
| Prototype Pollution | ?__proto__[test]=polluted | ({}).test === 'polluted' |
| PostMessage | Send from different origin | Check if processed |
Output Requirements
Create deliverables/client_side_analysis.md:
# Client-Side Security Analysis
## Summary
| Category | Issues Found | Critical | High | Medium |
|----------|--------------|----------|------|--------|
| React/Next.js XSS | X | Y | Z | W |
| Vue XSS | X | Y | Z | W |
| Angular XSS | X | Y | Z | W |
| DOM XSS | X | Y | Z | W |
| Server Components | X | Y | Z | W |
| Prototype Pollution | X | Y | Z | W |
| PostMessage | X | Y | Z | W |
| Client Storage | X | Y | Z | W |
## Framework Detected
- Primary: [React 18, Next.js 14, Vue 3, etc.]
- SSR: [Yes/No]
- Build Tool: [Vite, Webpack, Turbopack]
## Critical Findings
### [CLIENT-001] XSS via dangerouslySetInnerHTML
**Severity:** Critical
**Framework:** React
**Location:** `components/Comment.tsx:23`
**Vulnerable Code:**
```jsx
<div dangerouslySetInnerHTML={{ __html: comment.body }} />
Attack:
comment.body = "<img src=x onerror=alert(document.cookie)>"
Impact: Full XSS - can steal cookies, perform actions as user
Remediation:
import DOMPurify from 'dompurify';
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(comment.body) }} />
[CLIENT-002] SQL Injection in Server Action
Severity: Critical
Framework: Next.js 14
Location: app/actions/search.ts:12
Vulnerable Code:
'use server'
async function searchProducts(query: string) {
return db.query(`SELECT * FROM products WHERE name LIKE '%${query}%'`);
}
[CLIENT-003] Open Redirect in Next.js Middleware
Severity: High
Location: middleware.ts:8
Framework Security Matrix
| Framework | Auto-Escape | Common Pitfalls |
|---|
| React | Yes (JSX) | dangerouslySetInnerHTML, href |
| Next.js | Yes | Server Actions auth, middleware |
| Vue | Yes | v-html, :href |
| Angular | Yes | bypassSecurityTrust* |
Recommendations
- Sanitize all user content with DOMPurify before rendering
- Validate URLs before using in href/src attributes
- Add authentication checks to all Server Actions
- Validate redirect URLs in middleware
- Move tokens from localStorage to HttpOnly cookies
**Next Step:** DOM XSS findings can be verified with browser testing.