apply security audit
This commit is contained in:
@@ -25,6 +25,20 @@ import type { Notification, NotificationSchwere } from '../../types/notification
|
||||
|
||||
const POLL_INTERVAL_MS = 60_000; // 60 seconds
|
||||
|
||||
/**
|
||||
* Only allow window.open for URLs whose origin matches the current app origin.
|
||||
* External-looking URLs (different host or protocol-relative) are rejected to
|
||||
* prevent open-redirect / tab-napping via notification link data from the backend.
|
||||
*/
|
||||
function isTrustedUrl(url: string): boolean {
|
||||
try {
|
||||
const parsed = new URL(url, window.location.origin);
|
||||
return parsed.origin === window.location.origin;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function schwerebColor(schwere: NotificationSchwere): 'error' | 'warning' | 'info' {
|
||||
if (schwere === 'fehler') return 'error';
|
||||
if (schwere === 'warnung') return 'warning';
|
||||
@@ -103,7 +117,11 @@ const NotificationBell: React.FC = () => {
|
||||
handleClose();
|
||||
if (n.link) {
|
||||
if (n.link.startsWith('http://') || n.link.startsWith('https://')) {
|
||||
window.open(n.link, '_blank');
|
||||
if (isTrustedUrl(n.link)) {
|
||||
window.open(n.link, '_blank');
|
||||
} else {
|
||||
console.warn('NotificationBell: blocked navigation to untrusted URL', n.link);
|
||||
}
|
||||
} else {
|
||||
navigate(n.link);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user