Skip to content

Commit 11bc0d5

Browse files
committed
fix(notifications): Require absolute links for support of desktop and mobile clients
To align with the stricter validation introduced in nextcloud/server#59606. AI-Assisted-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Anna Larch <anna@nextcloud.com>
1 parent b4a754d commit 11bc0d5

File tree

1 file changed

+22
-4
lines changed

1 file changed

+22
-4
lines changed

lib/NotificationGenerator.php

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use OCP\Activity\IEvent;
1313
use OCP\Activity\IManager as ActivityManager;
1414
use OCP\IL10N;
15+
use OCP\IURLGenerator;
1516
use OCP\Notification\AlreadyProcessedException;
1617
use OCP\Notification\IManager as NotificationManager;
1718
use OCP\Notification\INotification;
@@ -28,9 +29,24 @@ public function __construct(
2829
protected UserSettings $userSettings,
2930
protected IL10N $l10n,
3031
protected LoggerInterface $logger,
32+
protected IURLGenerator $urlGenerator,
3133
) {
3234
}
3335

36+
private function sanitizeUrl(string $url): string {
37+
if (str_starts_with($url, 'http://') || str_starts_with($url, 'https://')) {
38+
return $url;
39+
}
40+
41+
// Reject non-HTTP(S) schemes (e.g. javascript:, nc://, data:)
42+
if (preg_match('/^[a-zA-Z][a-zA-Z0-9+\-.]*:/', $url)) {
43+
return '';
44+
}
45+
46+
// Relative URL — make it absolute
47+
return $this->urlGenerator->getAbsoluteURL($url);
48+
}
49+
3450
public function deferNotifications(): bool {
3551
return $this->notificationManager->defer();
3652
}
@@ -68,8 +84,9 @@ private function getNotificationForEvent(IEvent $event, int $activityId): INotif
6884
$notification->setMessage($event->getMessage(), $event->getMessageParameters());
6985
}
7086

71-
if ($event->getLink()) {
72-
$notification->setLink($event->getLink());
87+
$link = $event->getLink() ? $this->sanitizeUrl($event->getLink()) : '';
88+
if ($link !== '') {
89+
$notification->setLink($link);
7390
}
7491

7592
return $notification;
@@ -127,8 +144,9 @@ private function getDisplayNotificationForEvent(IEvent $event, int $activityId):
127144
$notification->setRichSubject($event->getRichSubject(), $event->getRichSubjectParameters());
128145
$notification->setParsedSubject($event->getParsedSubject());
129146

130-
if ($event->getIcon()) {
131-
$notification->setIcon($event->getIcon());
147+
$icon = $event->getIcon() ? $this->sanitizeUrl($event->getIcon()) : '';
148+
if ($icon !== '') {
149+
$notification->setIcon($icon);
132150
}
133151

134152
if ($event->getRichMessage()) {

0 commit comments

Comments
 (0)