fix: reject protocol-relative deep_link

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BCrwHHnGCB5XH968Nxokqw
This commit is contained in:
nikita.hohlov
2026-09-04 08:28:36 -03:00
parent 86b02f3d36
commit 95c0e53eb8
4 changed files with 15 additions and 3 deletions

View File

@@ -91,7 +91,7 @@ class InboxController extends Controller
/** Пропускает только относительные пути и http(s)-ссылки; прочее (напр. javascript:) отбрасывает. */
public static function safeLink(?string $link): ?string
{
return $link !== null && preg_match('#^(/|https?://)#i', $link) === 1 ? $link : null;
return $link !== null && preg_match('#^(/(?!/)|https?://)#i', $link) === 1 ? $link : null;
}
public static function relative(int $diff): string

View File

@@ -27,7 +27,7 @@ class UpsertEventsRequest extends FormRequest
'events.*.payload' => ['required', 'array'],
'events.*.payload.title' => ['required', 'string'],
'events.*.payload.subtitle' => ['sometimes', 'nullable', 'string'],
'events.*.payload.deep_link' => ['sometimes', 'nullable', 'string', 'max:2048', 'regex:#^(/|https?://)#'],
'events.*.payload.deep_link' => ['sometimes', 'nullable', 'string', 'max:2048', 'regex:#^(/(?!/)|https?://)#'],
'events.*.payload.done_label' => ['sometimes', 'nullable', 'string', 'max:64'],
];
}