UNPKG

chrome-extension-test-framework

Version:

Universal testing framework for Chrome extensions - Fast static analysis without browser dependencies

258 lines (235 loc) 10.7 kB
/** * PermissionsAnalyzer * Chrome拡張機能の権限を詳細に分析するクラス */ class PermissionsAnalyzer { constructor() { // 権限の分類と説明 this.permissionCategories = { sensitive: { permissions: { 'debugger': 'Can attach to browser tabs and intercept network traffic', 'declarativeNetRequest': 'Can block or modify network requests', 'declarativeNetRequestFeedback': 'Can receive information about blocked requests', 'downloads': 'Can manage downloads', 'geolocation': 'Can access your location', 'management': 'Can manage other extensions', 'nativeMessaging': 'Can communicate with native applications', 'privacy': 'Can change privacy settings', 'proxy': 'Can control proxy settings', 'system.cpu': 'Can access CPU information', 'system.memory': 'Can access memory information', 'system.storage': 'Can access storage device information', 'vpnProvider': 'Can configure VPN connections', 'webRequest': 'Can observe and analyze network traffic', 'webRequestBlocking': 'Can block network requests' }, hostPermissions: { '<all_urls>': 'Can access data on all websites', 'http://*/*': 'Can access data on all HTTP websites', 'https://*/*': 'Can access data on all HTTPS websites', '*://*/*': 'Can access data on all websites', 'file:///*': 'Can access local files on your computer' } }, moderate: { permissions: { 'bookmarks': 'Can read and modify bookmarks', 'browsingData': 'Can remove browsing data', 'contentSettings': 'Can change content settings', 'cookies': 'Can access cookies', 'history': 'Can access browsing history', 'tabs': 'Can access browser tabs', 'topSites': 'Can access most visited sites', 'webNavigation': 'Can access browser navigation history' } }, low: { permissions: { 'activeTab': 'Can access current tab when clicked', 'alarms': 'Can schedule code to run periodically', 'contextMenus': 'Can add items to context menu', 'idle': 'Can detect when machine is idle', 'notifications': 'Can display notifications', 'storage': 'Can store data locally', 'unlimitedStorage': 'Can store unlimited amount of data' } } }; } /** * 権限を分析 */ analyze(manifest) { const results = { totalPermissions: 0, sensitivePermissions: [], moderatePermissions: [], lowRiskPermissions: [], unknownPermissions: [], hostPermissions: [], recommendations: [] }; // 通常の権限を分析 const permissions = manifest.permissions || []; permissions.forEach(permission => { results.totalPermissions++; if (this.permissionCategories.sensitive.permissions[permission]) { results.sensitivePermissions.push({ name: permission, description: this.permissionCategories.sensitive.permissions[permission], risk: 'high' }); } else if (this.permissionCategories.moderate.permissions[permission]) { results.moderatePermissions.push({ name: permission, description: this.permissionCategories.moderate.permissions[permission], risk: 'moderate' }); } else if (this.permissionCategories.low.permissions[permission]) { results.lowRiskPermissions.push({ name: permission, description: this.permissionCategories.low.permissions[permission], risk: 'low' }); } else { results.unknownPermissions.push({ name: permission, description: 'Unknown permission - may be custom or deprecated', risk: 'unknown' }); } }); // ホスト権限を分析 const hostPermissions = manifest.host_permissions || []; hostPermissions.forEach(pattern => { results.totalPermissions++; const sensitivePattern = this.permissionCategories.sensitive.hostPermissions[pattern]; if (sensitivePattern) { results.hostPermissions.push({ pattern: pattern, description: sensitivePattern, risk: 'high', scope: 'all-sites' }); } else if (pattern.includes('*')) { results.hostPermissions.push({ pattern: pattern, description: `Can access data on: ${pattern}`, risk: 'moderate', scope: this.analyzeHostScope(pattern) }); } else { results.hostPermissions.push({ pattern: pattern, description: `Can access data on: ${pattern}`, risk: 'low', scope: 'specific-site' }); } }); // 推奨事項を生成 this.generateRecommendations(results); return results; } /** * ホストパターンのスコープを分析 */ analyzeHostScope(pattern) { if (pattern.includes('://*/*')) { return 'all-sites'; } else if (pattern.includes('*://')) { return 'all-protocols'; } else if (pattern.includes('/*')) { return 'entire-domain'; } else { return 'specific-pages'; } } /** * 推奨事項を生成 */ generateRecommendations(results) { // 過剰な権限の警告 if (results.sensitivePermissions.length > 3) { results.recommendations.push({ type: 'warning', message: 'Extension requests many sensitive permissions. Consider if all are necessary.', details: 'Having too many permissions increases security risk and may deter users from installing.' }); } // 広範なホスト権限の警告 const broadHostPerms = results.hostPermissions.filter(h => h.scope === 'all-sites'); if (broadHostPerms.length > 0) { results.recommendations.push({ type: 'warning', message: 'Extension requests access to all websites. Consider using activeTab or specific domains.', details: 'Broad host permissions are a security risk. Use "activeTab" for user-initiated actions.' }); } // webRequestBlockingの警告 const hasWebRequestBlocking = results.sensitivePermissions.some(p => p.name === 'webRequestBlocking'); if (hasWebRequestBlocking) { results.recommendations.push({ type: 'info', message: 'Consider migrating to declarativeNetRequest API (Manifest V3).', details: 'webRequestBlocking is being phased out in favor of declarativeNetRequest.' }); } // 権限の組み合わせチェック const hasTabsAndHistory = results.moderatePermissions.some(p => p.name === 'tabs') && results.moderatePermissions.some(p => p.name === 'history'); if (hasTabsAndHistory) { results.recommendations.push({ type: 'info', message: 'Extension can track detailed browsing activity with tabs + history permissions.', details: 'This combination allows complete browsing history tracking.' }); } } /** * 詳細なレポートを生成 */ generateReport(results) { const lines = []; lines.push('📊 Permissions Analysis Report'); lines.push(` Total permissions requested: ${results.totalPermissions}`); if (results.sensitivePermissions.length > 0) { lines.push('\n🚨 Sensitive Permissions:'); results.sensitivePermissions.forEach(perm => { lines.push(` • ${perm.name}: ${perm.description}`); }); } if (results.moderatePermissions.length > 0) { lines.push('\n⚠️ Moderate Risk Permissions:'); results.moderatePermissions.forEach(perm => { lines.push(` • ${perm.name}: ${perm.description}`); }); } if (results.lowRiskPermissions.length > 0) { lines.push('\n✅ Low Risk Permissions:'); results.lowRiskPermissions.forEach(perm => { lines.push(` • ${perm.name}: ${perm.description}`); }); } if (results.hostPermissions.length > 0) { lines.push('\n🌐 Host Permissions:'); results.hostPermissions.forEach(host => { const riskIcon = host.risk === 'high' ? '🚨' : host.risk === 'moderate' ? '⚠️' : '✅'; lines.push(` ${riskIcon} ${host.pattern}: ${host.description}`); }); } if (results.recommendations.length > 0) { lines.push('\n💡 Recommendations:'); results.recommendations.forEach(rec => { lines.push(` ${rec.type === 'warning' ? '⚠️' : 'ℹ️'} ${rec.message}`); if (rec.details) { lines.push(` ${rec.details}`); } }); } return lines.join('\n'); } } module.exports = PermissionsAnalyzer;