-
Notifications
You must be signed in to change notification settings - Fork 77
Add Permission Risk Explanation Engine & UI Breakdowns #155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,28 +9,52 @@ import { CheckCircle, AlertCircle, Info } from 'lucide-react'; | |
| import './LayerModal.scss'; | ||
|
|
||
| const FACTOR_HUMAN = { | ||
| SAST: { label: 'Code Safety', category: 'code', desc: 'Scans source code for known vulnerability patterns' }, | ||
| VirusTotal: { label: 'Malware Scan', category: 'threat', desc: 'Checks against 70+ antivirus engines for malicious code' }, | ||
| Obfuscation: { label: 'Hidden Code', category: 'code', desc: 'Detects deliberately obscured or unreadable code' }, | ||
| Manifest: { label: 'Extension Config', category: 'code', desc: 'Validates security settings in the extension manifest' }, | ||
| ChromeStats: { label: 'Threat Intel', category: 'threat', desc: 'Cross-references known threat databases' }, | ||
| Webstore: { label: 'Store Reputation', category: 'trust', desc: 'Chrome Web Store ratings and user reviews' }, | ||
| Maintenance: { label: 'Update Freshness', category: 'trust', desc: 'How recently the extension was updated by its developer' }, | ||
| PermissionsBaseline: { label: 'Permission Risk', category: 'access', desc: 'Evaluates the sensitivity of requested browser permissions' }, | ||
| PermissionCombos: { label: 'Dangerous Combos', category: 'access', desc: 'Flags risky combinations of permissions that enable data theft' }, | ||
| NetworkExfil: { label: 'Data Sharing', category: 'data', desc: 'Detects if data is sent to external servers' }, | ||
| CaptureSignals: { label: 'Screen Capture', category: 'data', desc: 'Checks for screen or tab recording capabilities' }, | ||
| ToSViolations: { label: 'Policy Violations', category: 'policy', desc: 'Checks compliance with Chrome Web Store policies' }, | ||
| Consistency: { label: 'Behavior Match', category: 'policy', desc: 'Compares stated purpose vs actual behavior' }, | ||
| DisclosureAlignment: { label: 'Disclosure Accuracy', category: 'policy', desc: 'Validates privacy policy against actual data collection' }, | ||
| SAST: { label: 'Code Safety', category: 'code', desc: 'Scans source code for known vulnerability patterns' }, | ||
| VirusTotal: { label: 'Malware Scan', category: 'threat', desc: 'Checks against 70+ antivirus engines for malicious code' }, | ||
| Obfuscation: { label: 'Hidden Code', category: 'code', desc: 'Detects deliberately obscured or unreadable code' }, | ||
| Manifest: { label: 'Extension Config', category: 'code', desc: 'Validates security settings in the extension manifest' }, | ||
| ChromeStats: { label: 'Threat Intel', category: 'threat', desc: 'Cross-references known threat databases' }, | ||
| Webstore: { label: 'Store Reputation', category: 'trust', desc: 'Chrome Web Store ratings and user reviews' }, | ||
| Maintenance: { label: 'Update Freshness', category: 'trust', desc: 'How recently the extension was updated by its developer' }, | ||
| PermissionsBaseline: { label: 'Permission Risk', category: 'access', desc: 'Evaluates the sensitivity of requested browser permissions' }, | ||
| PermissionCombos: { label: 'Dangerous Combos', category: 'access', desc: 'Flags risky combinations of permissions that enable data theft' }, | ||
| NetworkExfil: { label: 'Data Sharing', category: 'data', desc: 'Detects if data is sent to external servers' }, | ||
| CaptureSignals: { label: 'Screen Capture', category: 'data', desc: 'Checks for screen or tab recording capabilities' }, | ||
| ToSViolations: { label: 'Policy Violations', category: 'policy', desc: 'Checks compliance with Chrome Web Store policies' }, | ||
| Consistency: { label: 'Behavior Match', category: 'policy', desc: 'Compares stated purpose vs actual behavior' }, | ||
| DisclosureAlignment: { label: 'Disclosure Accuracy', category: 'policy', desc: 'Validates privacy policy against actual data collection' }, | ||
| }; | ||
|
|
||
| const PERMISSION_RISKS = { | ||
| tabs: 'Can read browsing activity', | ||
| webRequest: 'Can intercept and modify traffic (high risk)', | ||
| webRequestBlocking: 'Can block and modify network requests (high risk)', | ||
| cookies: 'Can read and modify site cookies', | ||
| history: 'Can read full browsing history', | ||
| clipboardRead: 'Can read copied text from clipboard', | ||
| clipboardWrite: 'Can modify clipboard contents', | ||
| desktopCapture: 'Can record your screen', | ||
| tabCapture: 'Can record browser tabs', | ||
| nativeMessaging: 'Can communicate with desktop apps', | ||
| proxy: 'Can route all traffic through external servers', | ||
| debugger: 'Can bypass security and monitor page internals', | ||
| management: 'Can disable or uninstall other extensions', | ||
| geolocation: 'Can access physical location', | ||
| bookmarks: 'Can read and modify bookmarks', | ||
| '<all_urls>': 'Can access data on all websites you visit', | ||
| '*://*/*': 'Can access data on all websites you visit', | ||
| 'http://*/*': 'Can access data on all HTTP websites', | ||
| 'https://*/*': 'Can access data on all HTTPS websites', | ||
| activeTab: 'Can access the current active tab', | ||
| storage: 'Can store data locally', | ||
| }; | ||
|
|
||
| const CATEGORY_LABELS = { | ||
| code: 'Code Checks', | ||
| code: 'Code Checks', | ||
| threat: 'Threat Detection', | ||
| trust: 'Trust Signals', | ||
| trust: 'Trust Signals', | ||
| access: 'Permissions', | ||
| data: 'Data Handling', | ||
| data: 'Data Handling', | ||
| policy: 'Policies', | ||
| }; | ||
|
|
||
|
|
@@ -83,8 +107,8 @@ function bandLabel(band) { | |
| switch (band) { | ||
| case 'GOOD': return 'Safe'; | ||
| case 'WARN': return 'Needs Review'; | ||
| case 'BAD': return 'Not Safe'; | ||
| default: return ''; | ||
| case 'BAD': return 'Not Safe'; | ||
| default: return ''; | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -152,9 +176,44 @@ const LayerModal = ({ | |
| style={{ animationDelay: `${(catIdx * 40 + (idx + 1) * 25)}ms` }} | ||
| role="listitem" | ||
| > | ||
| <div className="lm-check-left"> | ||
| <span className="lm-check-name">{item.label}</span> | ||
| {item.desc && <InfoTooltip text={item.desc} />} | ||
| <div className="lm-check-left" style={{ flexDirection: 'column', alignItems: 'flex-start', gap: '4px' }}> | ||
| <div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}> | ||
| <span className="lm-check-name">{item.label}</span> | ||
| {item.desc && <InfoTooltip text={item.desc} />} | ||
| </div> | ||
|
Comment on lines
+179
to
+183
|
||
|
|
||
| {/* Permission Risk Explanation Engine */} | ||
| {item.raw?.name === 'PermissionsBaseline' && item.raw?.details?.high_risk_permissions?.length > 0 && ( | ||
| <div style={{ marginTop: '2px', paddingLeft: '8px', borderLeft: '2px solid var(--risk-warn)', fontSize: '11px', color: 'var(--theme-text-muted)', display: 'flex', flexDirection: 'column', gap: '4px' }}> | ||
| {item.raw.details.high_risk_permissions.map(perm => ( | ||
| <div key={perm} style={{ display: 'flex', gap: '6px', lineHeight: '1.2' }}> | ||
| <span style={{ fontWeight: 600, color: 'var(--risk-warn)', flexShrink: 0 }}>{perm}</span> | ||
| <span style={{ opacity: 0.6 }}>→</span> | ||
|
Comment on lines
+187
to
+191
|
||
| <span>{PERMISSION_RISKS[perm] || `Has access to ${perm}`}</span> | ||
| </div> | ||
| ))} | ||
| </div> | ||
| )} | ||
|
|
||
| {/* Dangerous Combos Explanation Engine */} | ||
| {item.raw?.name === 'PermissionCombos' && item.raw?.details?.triggered_combos?.length > 0 && ( | ||
| <div style={{ marginTop: '2px', paddingLeft: '8px', borderLeft: '2px solid var(--risk-warn)', fontSize: '11px', color: 'var(--theme-text-muted)', display: 'flex', flexDirection: 'column', gap: '4px' }}> | ||
| {item.raw.details.triggered_combos.map(combo => { | ||
| const isBroad = combo === 'broad_host_access'; | ||
| const comboName = isBroad ? 'Broad Host Access' : combo.split('+').join(' + '); | ||
| const comboDesc = isBroad | ||
|
Comment on lines
+202
to
+204
|
||
| ? 'Can access and modify data on all websites' | ||
| : 'High risk when these are used together'; | ||
|
Comment on lines
+204
to
+206
|
||
| return ( | ||
| <div key={combo} style={{ display: 'flex', gap: '6px', lineHeight: '1.2' }}> | ||
| <span style={{ fontWeight: 600, color: 'var(--risk-warn)', flexShrink: 0 }}>{comboName}</span> | ||
| <span style={{ opacity: 0.6 }}>→</span> | ||
| <span>{comboDesc}</span> | ||
| </div> | ||
| ) | ||
| })} | ||
| </div> | ||
| )} | ||
| </div> | ||
| <span className="lm-status-wrap"> | ||
| {item.statusType === 'clear' ? ( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add missing high-risk explanation for
browsingData.high_risk_permissionscan includebrowsingData(from the backend risk set), but this map has no specific entry for it, so users get the generic fallback instead of a plain-English risk explanation.Proposed patch
const PERMISSION_RISKS = { tabs: 'Can read browsing activity', webRequest: 'Can intercept and modify traffic (high risk)', webRequestBlocking: 'Can block and modify network requests (high risk)', cookies: 'Can read and modify site cookies', + browsingData: 'Can clear browsing data (history, cache, cookies) and hide traces of activity', history: 'Can read full browsing history', clipboardRead: 'Can read copied text from clipboard',📝 Committable suggestion
🤖 Prompt for AI Agents