Security: add rate limiting, input validation, and filter category
validation Backend: - Add rate limiting middleware (mw/ratelimit.go) - in-memory per-IP limiter - Apply rate limits per endpoint group: - Public read-only: 120/min - Registration: 10/min - Portfolio filters: 60/min - Authenticated users: 120/min - Admin: none (trusted) - Add 256 char input length validation on portfolio endpoints - Validate filter categories exist in DB before querying - Secure GetImage endpoint: only allow UUID or numeric timestamp (15-20 digits) - Remove pattern-based image lookup to prevent enumeration - Add services validation: name (100), duration (1-480), patch test (0-168) Frontend: - Add maxlength=256 to portfolio tag/search inputs - Add maxlength to registration: name (50), email (255), phone (20), password (72) - Add maxlength=100 to service name input
This commit is contained in:
@@ -469,6 +469,7 @@
|
||||
|
||||
<input
|
||||
type="search"
|
||||
maxlength={256}
|
||||
enterkeyhint="done"
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
|
||||
@@ -551,6 +551,7 @@
|
||||
<Input
|
||||
id="service-name"
|
||||
type="text"
|
||||
maxlength={100}
|
||||
placeholder="e.g., Haircut, Color, Blowdry"
|
||||
bind:value={newService.name}
|
||||
onblur={validateNameField}
|
||||
|
||||
@@ -371,6 +371,7 @@
|
||||
<Input
|
||||
id="firstName"
|
||||
placeholder="John"
|
||||
maxlength={50}
|
||||
bind:value={formData.firstName}
|
||||
onblur={() => (formData.firstName = formData.firstName.trim())}
|
||||
required
|
||||
@@ -381,6 +382,7 @@
|
||||
<Input
|
||||
id="lastName"
|
||||
placeholder="Doe"
|
||||
maxlength={50}
|
||||
bind:value={formData.lastName}
|
||||
onblur={() => (formData.lastName = formData.lastName.trim())}
|
||||
required
|
||||
@@ -394,6 +396,7 @@
|
||||
id="phone"
|
||||
type="tel"
|
||||
placeholder="07123 456789 or +44 7123 456789"
|
||||
maxlength={20}
|
||||
value={formData.phone}
|
||||
oninput={handlePhoneInput}
|
||||
onblur={() => validatePhone(formData.phone)}
|
||||
@@ -428,6 +431,7 @@
|
||||
id="email"
|
||||
type="email"
|
||||
placeholder="john@example.com"
|
||||
maxlength={255}
|
||||
bind:value={formData.email}
|
||||
onblur={() => validateEmail(formData.email)}
|
||||
required
|
||||
@@ -443,6 +447,7 @@
|
||||
id="password"
|
||||
type="password"
|
||||
placeholder="Enter your password"
|
||||
maxlength={72}
|
||||
bind:value={formData.password}
|
||||
required
|
||||
/>
|
||||
|
||||
@@ -599,6 +599,7 @@
|
||||
<div class="flex gap-2 lg:border-l lg:pl-4">
|
||||
<Input
|
||||
placeholder="Search tags"
|
||||
maxlength={256}
|
||||
bind:value={searchQuery}
|
||||
onkeydown={(e) => {
|
||||
if ((e as KeyboardEvent).key === 'Enter') applySearch();
|
||||
|
||||
Reference in New Issue
Block a user