core-components: global override for window.open

Co-authored-by: Fredrik Adelöw <freben@gmail.com>
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2023-02-10 13:28:42 +01:00
parent e81a6e0ab5
commit 5637ebed92
3 changed files with 37 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core-components': patch
---
Added a global override for `window.open` that helps prevent security vulnerabilities.
@@ -183,3 +183,14 @@ describe('<Link />', () => {
);
});
});
describe('window.open', () => {
it('throws an error when attempting to open script code', () => {
expect(() =>
// eslint-disable-next-line no-script-url
window.open("javascript:alert('hello')"),
).toThrowErrorMatchingInlineSnapshot(
`"Rejected window.open() with a javascript: URL as a security precaution"`,
);
});
});
@@ -60,6 +60,27 @@ const scriptProtocolPattern =
// eslint-disable-next-line no-control-regex
/^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*\:/i;
// We install this globally in order to prevent javascript: URL XSS attacks via window.open
const originalWindowOpen = window.open as typeof window.open & {
__backstage?: true;
};
if (originalWindowOpen && !originalWindowOpen.__backstage) {
const newOpen = function open(
this: Window,
...args: Parameters<typeof window.open>
) {
const url = String(args[0]);
if (scriptProtocolPattern.test(url)) {
throw new Error(
'Rejected window.open() with a javascript: URL as a security precaution',
);
}
return originalWindowOpen.apply(this, args);
};
newOpen.__backstage = true;
window.open = newOpen;
}
export type LinkProps = Omit<MaterialLinkProps, 'to'> &
Omit<RouterLinkProps, 'to'> & {
to: string;