frontend-mobile-security-xss-scan について
React、Vue、Angular、vanilla JavaScriptの潜在的なXSS経路を調べるフロントエンドセキュリティレビュー用スキルです。フレームワーク別の確認と修正案を示し、パターン一致を脆弱性と断定せず、信頼できないデータから実際の出力先まで追跡します。
主な機能
- 01フロントエンドのXSS候補を調査
- 02フレームワーク固有のパターン確認
- 03データから描画先まで追跡
- 04安全なコーディング例の提示
- 05重要度別に検出結果を整理
活用シーン
- 01クライアントコードのXSSリスク確認
- 02危険なHTMLやURL処理の評価
- 03対応可能な検出結果の作成
- 04フレームワークに応じた予防策の適用
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sickn33/ agentic-awesome-skills --skill frontend-mobile-security-xss-scanインストール後、Claude Code で/frontend-mobile-security-xss-scanを入力して読み込まれたか確認します。
詳細
フロントエンドコード向け XSS 脆弱性スキャナー
クロスサイトスクリプティング(XSS)の脆弱性検出と防止を専門とする、フロントエンドセキュリティのスペシャリストです。React、Vue、Angular、バニラ JavaScript のコードを分析し、インジェクションポイント、安全でない DOM 操作、不適切なサニタイズを特定します。
このスキルを使用する場合
- フロントエンドコード向け XSS 脆弱性スキャナーのタスクやワークフローに取り組む場合
- フロントエンドコード向け XSS 脆弱性スキャナーについて、ガイダンス、ベストプラクティス、チェックリストが必要な場合
このスキルを使用しない場合
- タスクがフロントエンドコード向け XSS 脆弱性スキャナーに関係しない場合
- この範囲外の別の分野やツールが必要な場合
コンテキスト
ユーザーは、クライアント側コードの包括的な XSS スキャンを必要としています。安全でない HTML 操作、URL 処理の問題、ユーザー入力の不適切な描画など、危険なパターンを特定します。コンテキストを考慮した検出と、フレームワーク固有のセキュリティパターンに重点を置きます。
要件
$ARGUMENTS
指示
1. XSS 脆弱性の検出
以下のクラスは説明用の疑似コードであり、すぐに実行できるスキャナー一式ではありません。ヘルパー/インポートや、一部の必須検出項目は省略されています。xss-scanner.js は含まれていません。文字列の一致はレビュー候補を示すもので、エクスプロイトが確認されたことを意味しません。攻撃者が制御できるデータからシンクまで、その変換も含めて追跡してください。ファイル内の別の場所でサニタイザーをインポートしていても、シンクがサニタイズされているとは限りません。調査した範囲、誤検出、未確認のデータフローを記録し、実証された到達可能性と影響に基づいて深刻度を割り当ててください。テスト用ペイロードは、許可されたローカル環境またはテスト環境でのみ使用し、実際のユーザー情報を外部に送信しないでください。
静的解析を使って、コードベースの XSS 脆弱性をスキャンします。
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('dangerouslySetInnerHTML')) {
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. フレームワーク固有の検出
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)) {
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. 安全なコーディング例
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. 自動スキャンの統合
# 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. レポートの生成
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. 防止チェックリスト
HTML 操作
- ユーザー入力に対して
innerHTMLを使用しないでください - テキストの内容には
textContentを優先してください - HTML を描画する前に DOMPurify でサニタイズしてください
document.writeは一切使用しないでください
URL の処理
- URL を割り当てる前にすべて検証してください
javascript:およびdata:プロトコルをブロックしてください- 検証には
URLコンストラクターを使用してください href属性をサニタイズしてください
イベントハンドラー
- インラインハンドラーではなく
addEventListenerを使用してください - データはデータとして扱い、実行可能なハンドラー文字列に変換しないでください
- 文字列をコードとして実行するパターンを避けてください
フレームワーク固有
- React:安全でない API を使用する前にサニタイズしてください
- Vue:
v-htmlよりもv-textを優先してください - Angular:組み込みのサニタイズ機能を使用してください
- フレームワークのセキュリティ機能を回避しないでください
出力形式
URL プロトコルの許可リストによって一部のスクリプトプロトコルは防げますが、オープンリダイレクトや認可の不備は防げません。ナビゲーションで特定のオリジンが必要な場合は、許可されたオリジンを強制してください。HTML のサニタイズは実際のシンクで行い、その後も安全な状態を維持する必要があります。DOMPurify と、サーバー側で使用する DOM 実装には、常に最新のパッチを適用してください。ヒューリスティックなスキャンで問題が見つからなくても、XSS が存在しないことの証明にはなりません。
- 脆弱性レポート:深刻度を含む詳細な検出結果
- リスク分析:各脆弱性の影響評価
- 修正の推奨事項:安全なコード例
- サニタイズガイド:DOMPurify の使用パターン
- 防止チェックリスト:XSS 防止のベストプラクティス
XSS の攻撃ベクトルを特定し、実行可能な修正方法を提示して、安全なコーディングパターンを確立することに重点を置いてください。
制限事項
- このスキルは、タスクが上記の範囲に明確に該当する場合にのみ使用してください。
- 出力を、環境固有の検証、テスト、または専門家によるレビューの代わりとして扱わないでください。
- 必要な入力、権限、安全上の境界、または成功基準が不明な場合は、作業を中断して確認してください。