fix: restrict deep_link to relative paths and http(s)

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:25:00 -03:00
parent 027c9f7784
commit 86b02f3d36
4 changed files with 46 additions and 2 deletions

View File

@@ -70,7 +70,7 @@ class InboxController extends Controller
'state' => $e->state->value,
'title' => $e->payload['title'],
'subtitle' => $e->payload['subtitle'] ?? null,
'link' => $e->payload['deep_link'] ?? null,
'link' => self::safeLink($e->payload['deep_link'] ?? null),
'done_label' => $e->payload['done_label'] ?? 'Сделано',
'can_remind' => $e->state !== EventState::Scheduled,
'source' => self::sourceLabel($e->source->name),
@@ -88,6 +88,12 @@ class InboxController extends Controller
return $name === 'manual' ? 'вручную' : $name;
}
/** Пропускает только относительные пути и http(s)-ссылки; прочее (напр. javascript:) отбрасывает. */
public static function safeLink(?string $link): ?string
{
return $link !== null && preg_match('#^(/|https?://)#i', $link) === 1 ? $link : null;
}
public static function relative(int $diff): string
{
$days = fn (int $n) => $n % 10 === 1 && $n % 100 !== 11 ? 'день' : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 12 || $n % 100 > 14) ? 'дня' : 'дней');

View File

@@ -27,11 +27,18 @@ 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'],
'events.*.payload.deep_link' => ['sometimes', 'nullable', 'string', 'max:2048', 'regex:#^(/|https?://)#'],
'events.*.payload.done_label' => ['sometimes', 'nullable', 'string', 'max:64'],
];
}
public function messages(): array
{
return [
'events.*.payload.deep_link.regex' => 'deep_link должен быть относительным путём или http(s)-ссылкой',
];
}
public function after(): array
{
return [function (Validator $v) {