mirror of
https://github.com/wshobson/agents.git
synced 2026-03-18 17:47:16 +00:00
style: format all files with prettier
This commit is contained in:
@@ -20,7 +20,7 @@ Scan codebase for XSS vulnerabilities using static analysis:
|
||||
interface XSSFinding {
|
||||
file: string;
|
||||
line: number;
|
||||
severity: 'critical' | 'high' | 'medium' | 'low';
|
||||
severity: "critical" | "high" | "medium" | "low";
|
||||
type: string;
|
||||
vulnerable_code: string;
|
||||
description: string;
|
||||
@@ -30,8 +30,12 @@ interface XSSFinding {
|
||||
|
||||
class XSSScanner {
|
||||
private vulnerablePatterns = [
|
||||
'innerHTML', 'outerHTML', 'document.write',
|
||||
'insertAdjacentHTML', 'location.href', 'window.open'
|
||||
"innerHTML",
|
||||
"outerHTML",
|
||||
"document.write",
|
||||
"insertAdjacentHTML",
|
||||
"location.href",
|
||||
"window.open",
|
||||
];
|
||||
|
||||
async scanDirectory(path: string): Promise<XSSFinding[]> {
|
||||
@@ -39,7 +43,7 @@ class XSSScanner {
|
||||
const findings: XSSFinding[] = [];
|
||||
|
||||
for (const file of files) {
|
||||
const content = await fs.readFile(file, 'utf-8');
|
||||
const content = await fs.readFile(file, "utf-8");
|
||||
findings.push(...this.scanFile(file, content));
|
||||
}
|
||||
|
||||
@@ -59,19 +63,20 @@ class XSSScanner {
|
||||
|
||||
detectHTMLManipulation(file: string, content: string): XSSFinding[] {
|
||||
const findings: XSSFinding[] = [];
|
||||
const lines = content.split('\n');
|
||||
const lines = content.split("\n");
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
if (line.includes('innerHTML') && this.hasUserInput(line)) {
|
||||
if (line.includes("innerHTML") && this.hasUserInput(line)) {
|
||||
findings.push({
|
||||
file,
|
||||
line: index + 1,
|
||||
severity: 'critical',
|
||||
type: 'Unsafe HTML manipulation',
|
||||
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'
|
||||
description:
|
||||
"User-controlled data in HTML manipulation creates XSS risk",
|
||||
fix: "Use textContent for plain text or sanitize with DOMPurify library",
|
||||
cwe: "CWE-79",
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -81,19 +86,20 @@ class XSSScanner {
|
||||
|
||||
detectReactVulnerabilities(file: string, content: string): XSSFinding[] {
|
||||
const findings: XSSFinding[] = [];
|
||||
const lines = content.split('\n');
|
||||
const lines = content.split("\n");
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
if (line.includes('dangerously') && !this.hasSanitization(content)) {
|
||||
if (line.includes("dangerously") && !this.hasSanitization(content)) {
|
||||
findings.push({
|
||||
file,
|
||||
line: index + 1,
|
||||
severity: 'high',
|
||||
type: 'React unsafe HTML rendering',
|
||||
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'
|
||||
description:
|
||||
"Unsanitized HTML in React component creates XSS vulnerability",
|
||||
fix: "Apply DOMPurify.sanitize() before rendering or use safe alternatives",
|
||||
cwe: "CWE-79",
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -103,19 +109,20 @@ class XSSScanner {
|
||||
|
||||
detectURLVulnerabilities(file: string, content: string): XSSFinding[] {
|
||||
const findings: XSSFinding[] = [];
|
||||
const lines = content.split('\n');
|
||||
const lines = content.split("\n");
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
if (line.includes('location.') && this.hasUserInput(line)) {
|
||||
if (line.includes("location.") && this.hasUserInput(line)) {
|
||||
findings.push({
|
||||
file,
|
||||
line: index + 1,
|
||||
severity: 'high',
|
||||
type: 'URL injection',
|
||||
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'
|
||||
description:
|
||||
"User input in URL assignment can execute malicious code",
|
||||
fix: "Validate URLs and enforce http/https protocols only",
|
||||
cwe: "CWE-79",
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -124,12 +131,19 @@ class XSSScanner {
|
||||
}
|
||||
|
||||
hasUserInput(line: string): boolean {
|
||||
const indicators = ['props', 'state', 'params', 'query', 'input', 'formData'];
|
||||
return indicators.some(indicator => line.includes(indicator));
|
||||
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');
|
||||
return content.includes("DOMPurify") || content.includes("sanitize");
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -143,18 +157,18 @@ class ReactXSSScanner {
|
||||
|
||||
// Check for unsafe React patterns
|
||||
const unsafePatterns = [
|
||||
'dangerouslySetInnerHTML',
|
||||
'createMarkup',
|
||||
'rawHtml'
|
||||
"dangerouslySetInnerHTML",
|
||||
"createMarkup",
|
||||
"rawHtml",
|
||||
];
|
||||
|
||||
unsafePatterns.forEach(pattern => {
|
||||
if (code.includes(pattern) && !code.includes('DOMPurify')) {
|
||||
unsafePatterns.forEach((pattern) => {
|
||||
if (code.includes(pattern) && !code.includes("DOMPurify")) {
|
||||
findings.push({
|
||||
severity: 'high',
|
||||
type: 'React XSS risk',
|
||||
severity: "high",
|
||||
type: "React XSS risk",
|
||||
description: `Pattern ${pattern} used without sanitization`,
|
||||
fix: 'Apply proper HTML sanitization'
|
||||
fix: "Apply proper HTML sanitization",
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -167,12 +181,12 @@ class VueXSSScanner {
|
||||
scanVueTemplate(template: string): XSSFinding[] {
|
||||
const findings: XSSFinding[] = [];
|
||||
|
||||
if (template.includes('v-html')) {
|
||||
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'
|
||||
severity: "high",
|
||||
type: "Vue HTML injection",
|
||||
description: "v-html directive renders raw HTML",
|
||||
fix: "Use v-text for plain text or sanitize HTML",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -216,10 +230,10 @@ const Component = ({ html }) => (
|
||||
<div dangerouslySetInnerHTML={{
|
||||
__html: DOMPurify.sanitize(html)
|
||||
}} />
|
||||
);`
|
||||
);`,
|
||||
};
|
||||
|
||||
return patterns[vulnerability] || 'No secure pattern available';
|
||||
return patterns[vulnerability] || "No secure pattern available";
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -245,7 +259,7 @@ class XSSReportGenerator {
|
||||
generateReport(findings: XSSFinding[]): string {
|
||||
const grouped = this.groupBySeverity(findings);
|
||||
|
||||
let report = '# XSS Vulnerability Scan Report\n\n';
|
||||
let report = "# XSS Vulnerability Scan Report\n\n";
|
||||
report += `Total Findings: ${findings.length}\n\n`;
|
||||
|
||||
for (const [severity, issues] of Object.entries(grouped)) {
|
||||
@@ -262,11 +276,14 @@ class XSSReportGenerator {
|
||||
}
|
||||
|
||||
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[]>);
|
||||
return findings.reduce(
|
||||
(acc, finding) => {
|
||||
if (!acc[finding.severity]) acc[finding.severity] = [];
|
||||
acc[finding.severity].push(finding);
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, XSSFinding[]>,
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -274,23 +291,27 @@ class XSSReportGenerator {
|
||||
### 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
|
||||
|
||||
Reference in New Issue
Block a user