fix: drop executable grab urls
This commit is contained in:
parent
2812c79011
commit
e24c2cf532
|
|
@ -122,4 +122,30 @@ describe('clampGrabPayload', () => {
|
|||
expect(payload?.target.reactComponents?.length).toBeLessThanOrEqual(512)
|
||||
expect(payload?.target.sourceFile).toBe('src/Button.tsx:12:4')
|
||||
})
|
||||
|
||||
it('drops executable and embedded URL schemes from page and attribute URLs', () => {
|
||||
const payload = clampGrabPayload(
|
||||
makeRawPayload({
|
||||
page: {
|
||||
...(makeRawPayload().page as Record<string, unknown>),
|
||||
sanitizedUrl: 'javascript:alert(1)'
|
||||
},
|
||||
target: {
|
||||
...(makeRawPayload().target as Record<string, unknown>),
|
||||
attributes: {
|
||||
href: 'javascript:alert(1)',
|
||||
src: 'data:text/html,<script>alert(1)</script>',
|
||||
action: 'vbscript:msgbox(1)',
|
||||
title: 'Safe label'
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
expect(payload?.page.sanitizedUrl).toBe('')
|
||||
expect(payload?.target.attributes.href).toBe('')
|
||||
expect(payload?.target.attributes.src).toBe('')
|
||||
expect(payload?.target.attributes.action).toBe('')
|
||||
expect(payload?.target.attributes.title).toBe('Safe label')
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import {
|
|||
GRAB_SECRET_PATTERNS
|
||||
} from '../../shared/browser-grab-types'
|
||||
|
||||
const SAFE_GRAB_URL_PROTOCOLS = new Set(['http:', 'https:', 'file:'])
|
||||
|
||||
/**
|
||||
* Re-validate and clamp all string, array, and budget fields in a grab payload
|
||||
* before forwarding to the renderer. This is the main-side safety net: even if
|
||||
|
|
@ -66,6 +68,12 @@ export function clampGrabPayload(raw: unknown): BrowserGrabPayload | null {
|
|||
}
|
||||
try {
|
||||
const url = new URL(str)
|
||||
if (url.protocol === 'about:') {
|
||||
return url.toString() === 'about:blank' ? 'about:blank' : ''
|
||||
}
|
||||
if (!SAFE_GRAB_URL_PROTOCOLS.has(url.protocol)) {
|
||||
return ''
|
||||
}
|
||||
url.search = ''
|
||||
url.hash = ''
|
||||
return url.toString()
|
||||
|
|
|
|||
|
|
@ -121,6 +121,13 @@ describe('buildGuestOverlayScript', () => {
|
|||
expect(script).toContain("return '';")
|
||||
})
|
||||
|
||||
it('arm script rejects executable and embedded URL schemes', () => {
|
||||
const script = buildGuestOverlayScript('arm')
|
||||
|
||||
expect(script).toContain('SAFE_URL_PROTOCOLS')
|
||||
expect(script).toContain('!SAFE_URL_PROTOCOLS.has(u.protocol)')
|
||||
})
|
||||
|
||||
it('arm script slices text nodes before normalizing bounded text', () => {
|
||||
const script = buildGuestOverlayScript('arm')
|
||||
|
||||
|
|
|
|||
|
|
@ -93,6 +93,8 @@ const ARM_SCRIPT = `(function() {
|
|||
'secret', 'password', 'passwd'
|
||||
];
|
||||
|
||||
var SAFE_URL_PROTOCOLS = new Set(['http:', 'https:', 'file:']);
|
||||
|
||||
var STYLE_PROPS = [
|
||||
'display', 'position', 'width', 'height', 'margin', 'padding',
|
||||
'color', 'backgroundColor', 'border', 'borderRadius', 'fontFamily',
|
||||
|
|
@ -118,6 +120,12 @@ const ARM_SCRIPT = `(function() {
|
|||
function sanitizeUrl(url) {
|
||||
try {
|
||||
var u = new URL(url);
|
||||
if (u.protocol === 'about:') {
|
||||
return u.toString() === 'about:blank' ? 'about:blank' : '';
|
||||
}
|
||||
if (!SAFE_URL_PROTOCOLS.has(u.protocol)) {
|
||||
return '';
|
||||
}
|
||||
u.search = '';
|
||||
u.hash = '';
|
||||
return u.toString();
|
||||
|
|
|
|||
Loading…
Reference in New Issue