Initial commit
This commit is contained in:
307
commands/xss-scan.md
Normal file
307
commands/xss-scan.md
Normal file
@@ -0,0 +1,307 @@
|
||||
# XSS Vulnerability Scanner for Frontend Code
|
||||
|
||||
You are a frontend security specialist focusing on Cross-Site Scripting (XSS) vulnerability detection and prevention. Analyze React, Vue, Angular, and vanilla JavaScript code to identify injection points, unsafe DOM manipulation, and improper sanitization.
|
||||
|
||||
## Context
|
||||
|
||||
The user needs comprehensive XSS vulnerability scanning for client-side code, identifying dangerous patterns like unsafe HTML manipulation, URL handling issues, and improper user input rendering. Focus on context-aware detection and framework-specific security patterns.
|
||||
|
||||
## Requirements
|
||||
|
||||
$ARGUMENTS
|
||||
|
||||
## Instructions
|
||||
|
||||
### 1. XSS Vulnerability Detection
|
||||
|
||||
Scan codebase for XSS vulnerabilities using static analysis:
|
||||
|
||||
```typescript
|
||||
interface XSSFinding {
|
||||
file: string;
|
||||
line: number;
|
||||
severity: 'critical' | 'high' | 'medium' | 'low';
|
||||
type: string;
|
||||
vulnerable_code: string;
|
||||
description: string;
|
||||
fix: string;
|
||||
cwe: string;
|
||||
}
|
||||
|
||||
class XSSScanner {
|
||||
private vulnerablePatterns = [
|
||||
'innerHTML', 'outerHTML', 'document.write',
|
||||
'insertAdjacentHTML', 'location.href', 'window.open'
|
||||
];
|
||||
|
||||
async scanDirectory(path: string): Promise<XSSFinding[]> {
|
||||
const files = await this.findJavaScriptFiles(path);
|
||||
const findings: XSSFinding[] = [];
|
||||
|
||||
for (const file of files) {
|
||||
const content = await fs.readFile(file, 'utf-8');
|
||||
findings.push(...this.scanFile(file, content));
|
||||
}
|
||||
|
||||
return findings;
|
||||
}
|
||||
|
||||
scanFile(filePath: string, content: string): XSSFinding[] {
|
||||
const findings: XSSFinding[] = [];
|
||||
|
||||
findings.push(...this.detectHTMLManipulation(filePath, content));
|
||||
findings.push(...this.detectReactVulnerabilities(filePath, content));
|
||||
findings.push(...this.detectURLVulnerabilities(filePath, content));
|
||||
findings.push(...this.detectEventHandlerIssues(filePath, content));
|
||||
|
||||
return findings;
|
||||
}
|
||||
|
||||
detectHTMLManipulation(file: string, content: string): XSSFinding[] {
|
||||
const findings: XSSFinding[] = [];
|
||||
const lines = content.split('\n');
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
if (line.includes('innerHTML') && this.hasUserInput(line)) {
|
||||
findings.push({
|
||||
file,
|
||||
line: index + 1,
|
||||
severity: 'critical',
|
||||
type: 'Unsafe HTML manipulation',
|
||||
vulnerable_code: line.trim(),
|
||||
description: 'User-controlled data in HTML manipulation creates XSS risk',
|
||||
fix: 'Use textContent for plain text or sanitize with DOMPurify library',
|
||||
cwe: 'CWE-79'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return findings;
|
||||
}
|
||||
|
||||
detectReactVulnerabilities(file: string, content: string): XSSFinding[] {
|
||||
const findings: XSSFinding[] = [];
|
||||
const lines = content.split('\n');
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
if (line.includes('dangerously') && !this.hasSanitization(content)) {
|
||||
findings.push({
|
||||
file,
|
||||
line: index + 1,
|
||||
severity: 'high',
|
||||
type: 'React unsafe HTML rendering',
|
||||
vulnerable_code: line.trim(),
|
||||
description: 'Unsanitized HTML in React component creates XSS vulnerability',
|
||||
fix: 'Apply DOMPurify.sanitize() before rendering or use safe alternatives',
|
||||
cwe: 'CWE-79'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return findings;
|
||||
}
|
||||
|
||||
detectURLVulnerabilities(file: string, content: string): XSSFinding[] {
|
||||
const findings: XSSFinding[] = [];
|
||||
const lines = content.split('\n');
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
if (line.includes('location.') && this.hasUserInput(line)) {
|
||||
findings.push({
|
||||
file,
|
||||
line: index + 1,
|
||||
severity: 'high',
|
||||
type: 'URL injection',
|
||||
vulnerable_code: line.trim(),
|
||||
description: 'User input in URL assignment can execute malicious code',
|
||||
fix: 'Validate URLs and enforce http/https protocols only',
|
||||
cwe: 'CWE-79'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return findings;
|
||||
}
|
||||
|
||||
hasUserInput(line: string): boolean {
|
||||
const indicators = ['props', 'state', 'params', 'query', 'input', 'formData'];
|
||||
return indicators.some(indicator => line.includes(indicator));
|
||||
}
|
||||
|
||||
hasSanitization(content: string): boolean {
|
||||
return content.includes('DOMPurify') || content.includes('sanitize');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Framework-Specific Detection
|
||||
|
||||
```typescript
|
||||
class ReactXSSScanner {
|
||||
scanReactComponent(code: string): XSSFinding[] {
|
||||
const findings: XSSFinding[] = [];
|
||||
|
||||
// Check for unsafe React patterns
|
||||
const unsafePatterns = [
|
||||
'dangerouslySetInnerHTML',
|
||||
'createMarkup',
|
||||
'rawHtml'
|
||||
];
|
||||
|
||||
unsafePatterns.forEach(pattern => {
|
||||
if (code.includes(pattern) && !code.includes('DOMPurify')) {
|
||||
findings.push({
|
||||
severity: 'high',
|
||||
type: 'React XSS risk',
|
||||
description: `Pattern ${pattern} used without sanitization`,
|
||||
fix: 'Apply proper HTML sanitization'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return findings;
|
||||
}
|
||||
}
|
||||
|
||||
class VueXSSScanner {
|
||||
scanVueTemplate(template: string): XSSFinding[] {
|
||||
const findings: XSSFinding[] = [];
|
||||
|
||||
if (template.includes('v-html')) {
|
||||
findings.push({
|
||||
severity: 'high',
|
||||
type: 'Vue HTML injection',
|
||||
description: 'v-html directive renders raw HTML',
|
||||
fix: 'Use v-text for plain text or sanitize HTML'
|
||||
});
|
||||
}
|
||||
|
||||
return findings;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Secure Coding Examples
|
||||
|
||||
```typescript
|
||||
class SecureCodingGuide {
|
||||
getSecurePattern(vulnerability: string): string {
|
||||
const patterns = {
|
||||
html_manipulation: `
|
||||
// SECURE: Use textContent for plain text
|
||||
element.textContent = userInput;
|
||||
|
||||
// SECURE: Sanitize HTML when needed
|
||||
import DOMPurify from 'dompurify';
|
||||
const clean = DOMPurify.sanitize(userInput);
|
||||
element.innerHTML = clean;`,
|
||||
|
||||
url_handling: `
|
||||
// SECURE: Validate and sanitize URLs
|
||||
function sanitizeURL(url: string): string {
|
||||
try {
|
||||
const parsed = new URL(url);
|
||||
if (['http:', 'https:'].includes(parsed.protocol)) {
|
||||
return parsed.href;
|
||||
}
|
||||
} catch {}
|
||||
return '#';
|
||||
}`,
|
||||
|
||||
react_rendering: `
|
||||
// SECURE: Sanitize before rendering
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
const Component = ({ html }) => (
|
||||
<div dangerouslySetInnerHTML={{
|
||||
__html: DOMPurify.sanitize(html)
|
||||
}} />
|
||||
);`
|
||||
};
|
||||
|
||||
return patterns[vulnerability] || 'No secure pattern available';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Automated Scanning Integration
|
||||
|
||||
```bash
|
||||
# ESLint with security plugin
|
||||
npm install --save-dev eslint-plugin-security
|
||||
eslint . --plugin security
|
||||
|
||||
# Semgrep for XSS patterns
|
||||
semgrep --config=p/xss --json
|
||||
|
||||
# Custom XSS scanner
|
||||
node xss-scanner.js --path=src --format=json
|
||||
```
|
||||
|
||||
### 5. Report Generation
|
||||
|
||||
```typescript
|
||||
class XSSReportGenerator {
|
||||
generateReport(findings: XSSFinding[]): string {
|
||||
const grouped = this.groupBySeverity(findings);
|
||||
|
||||
let report = '# XSS Vulnerability Scan Report\n\n';
|
||||
report += `Total Findings: ${findings.length}\n\n`;
|
||||
|
||||
for (const [severity, issues] of Object.entries(grouped)) {
|
||||
report += `## ${severity.toUpperCase()} (${issues.length})\n\n`;
|
||||
|
||||
for (const issue of issues) {
|
||||
report += `- **${issue.type}**\n`;
|
||||
report += ` File: ${issue.file}:${issue.line}\n`;
|
||||
report += ` Fix: ${issue.fix}\n\n`;
|
||||
}
|
||||
}
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
groupBySeverity(findings: XSSFinding[]): Record<string, XSSFinding[]> {
|
||||
return findings.reduce((acc, finding) => {
|
||||
if (!acc[finding.severity]) acc[finding.severity] = [];
|
||||
acc[finding.severity].push(finding);
|
||||
return acc;
|
||||
}, {} as Record<string, XSSFinding[]>);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6. Prevention Checklist
|
||||
|
||||
**HTML Manipulation**
|
||||
- Never use innerHTML with user input
|
||||
- Prefer textContent for text content
|
||||
- Sanitize with DOMPurify before rendering HTML
|
||||
- Avoid document.write entirely
|
||||
|
||||
**URL Handling**
|
||||
- Validate all URLs before assignment
|
||||
- Block javascript: and data: protocols
|
||||
- Use URL constructor for validation
|
||||
- Sanitize href attributes
|
||||
|
||||
**Event Handlers**
|
||||
- Use addEventListener instead of inline handlers
|
||||
- Sanitize all event handler input
|
||||
- Avoid string-to-code patterns
|
||||
|
||||
**Framework-Specific**
|
||||
- React: Sanitize before using unsafe APIs
|
||||
- Vue: Prefer v-text over v-html
|
||||
- Angular: Use built-in sanitization
|
||||
- Avoid bypassing framework security features
|
||||
|
||||
## Output Format
|
||||
|
||||
1. **Vulnerability Report**: Detailed findings with severity levels
|
||||
2. **Risk Analysis**: Impact assessment for each vulnerability
|
||||
3. **Fix Recommendations**: Secure code examples
|
||||
4. **Sanitization Guide**: DOMPurify usage patterns
|
||||
5. **Prevention Checklist**: Best practices for XSS prevention
|
||||
|
||||
Focus on identifying XSS attack vectors, providing actionable fixes, and establishing secure coding patterns.
|
||||
Reference in New Issue
Block a user