aboutsummaryrefslogtreecommitdiff
path: root/src/lib/Utility
Commit message (Collapse)AuthorAgeFilesLines
* fix(security): sanitize badge_wall_css server-side, render via textContentFuwn22 hours2-0/+133
| | | | | | | | | | | | | | | | Custom badge-wall CSS was sanitised only client-side with a fragile regex and injected via innerHTML, while the stored value stayed raw. Sanitise at the write boundary instead (setCSS, covering both the REST and GraphQL paths) with a css-tree pass that parses leniently and drops @import, behavior/-moz-binding, expression()/javascript: values, and </style> break-out attempts; render with textContent instead of innerHTML so break-out is impossible by construction (CSP already blocks inline script). css-tree stays server-only. A behaviour-gate test confirms ordinary CSS (backdrop-filter, content, url(), @media, @keyframes) is preserved while the dangerous constructs are removed. The previous regex also silently stripped all `content:` declarations; those now render correctly.
* fix(security): sanitize third-party RSS HTML before {@html}Fuwn31 hours2-0/+89
| | | | | | | | | | | The /updates page rendered manga/novel feed fields (content, titles, series names) from mangaupdates/syosetu/wlnupdates via {@html} with no sanitization. CSP already blocks script execution, but injected markup could still phish, redirect, or track. Add sanitizeFeedHtml (DOMPurify with a small safe allow-list) and apply it on ingest. A behaviour-gate test plus a check against the live mangaupdates feed confirm legitimate formatting (entities, <i>/<b>/<a href>) is preserved while <script>, event handlers, <iframe>/<meta>/<style> and javascript: URLs are removed.
* fix(security): allow-list web-push endpoints to stop SSRFFuwn31 hours2-0/+75
| | | | | | | | | | | Stored push subscriptions carry a client-supplied `endpoint`, and the notifications job POSTed to it with no host check, so a subscription with an internal/metadata URL turned the Trigger.dev worker into a blind SSRF primitive. Add isAllowedPushEndpoint (https + known vendor hosts: FCM, Mozilla, Apple, WNS), skip non-conforming endpoints in the job, and reject them at subscribe time. Browser-minted subscriptions always match a vendor host, so real delivery is unchanged; a behaviour-gate test asserts vendor endpoints pass and internal/non-https/look-alikes fail.
* fix(security): authorize shadowHide target in badges endpoint (IDOR)Fuwn32 hours2-0/+29
| | | | | | | | | | PUT /api/badges?shadowHide=<userId> called setShadowHidden on an arbitrary user_id with no ownership/privilege check, so any logged-in user could flip shadow_hidden on another user's badges (e.g. un-hide moderator-hidden ones). The GraphQL path already guarded this; the REST twin didn't. Extract the owner-or-privileged check into a shared isOwnerOrPrivileged helper, use it in both the REST endpoint and the GraphQL resolver, and add a regression test.
* fix(security): mark auth cookies Secure outside localhostFuwn34 hours1-1/+0
| | | | | | | | | | The user and logout cookies were set with secure:false, so the AniList tokens the user cookie carries could traverse plaintext HTTP. Drop the override and let SvelteKit's default apply (Secure everywhere except http://localhost), giving Secure in production and on https://due.localhost while keeping plain-http local dev working. httpOnly is unchanged (the client reads the token from layout data; tightening that is tracked separately as the architectural part of C2).
* style: apply biome autofixes and resolve remaining lint findingsFuwn4 days6-8/+8
| | | | | | | | | | | | | | Auto-fixed cosmetic findings (import ordering, obj["k"]->obj.k, optional chaining, template literals, Date.now, parseInt radix, useless ternaries/ switch cases). Resolved the non-autofixable rest by hand: - Senpy: static-only class -> object literal (no this/static reliance). - app.html: var global shim -> window.global = window (keeps the shim, drops the unused-var flag). - biome-ignore with rationale for the logout document.cookie clear and the holodule scrape non-null assertion. Verified: biome check 0 diagnostics, svelte-check 0/0, 24/24 unit tests.
* refactor(locale): move hardcoded UI strings into english localeFuwn9 days1-1/+5
| | | | | | | | | | | | | | | | | Adds optional namespaces (common, errors, commandPalette, headTitle, notifications, schedule, events, home, reader, routes, badgePreview, badgeWall) and extends existing ones (settings.*, lists.*, tools.*, user.*, hololive.*) on the Locale interface. New fields are optional so japanese.ts can omit them; svelte-i18n's fallbackLocale handles the runtime miss. HeadTitle gains an optional routeKey prop for type-safe lookup. defaultActions becomes a factory so the command palette re-reads locale on language toggle. The existing JP feedback translation in routes/settings is preserved via japanese.ts. Out of scope (kept hardcoded): service-worker.ts, app.html, Landing*.svelte, tools.ts registry, Easter Event 2025 pages.
* fix(utility): treat .localhost subdomains as private in appOriginFuwn2026-04-181-0/+1
|
* revert(ui): remove april fools executive modeFuwn2026-04-021-51/+0
|
* feat(ui): add april fools executive modeFuwn2026-04-011-0/+51
|
* fix(notifications): stabilize browser subscription identityFuwn2026-03-281-15/+10
|
* fix(notifications): support per-device push subscriptionsFuwn2026-03-281-1/+1
|
* fix(cache): respect AniList media list recache windowsFuwn2026-03-281-5/+14
|
* refactor(proxy): move manga chapter counts behind indexed cacheFuwn2026-03-271-2/+15
|
* refactor: centralise site origin usageFuwn2026-03-221-0/+10
|
* refactor: extract app origin configFuwn2026-03-224-8/+38
|
* chore(biome): drop formatter style overridesFuwn2026-03-0113-269/+285
|
* chore(biome): enable svelte formattingFuwn2026-03-011-3/+3
|
* chore(biome): re-enable useIterableCallbackReturn ruleFuwn2026-03-011-3/+9
|
* chore(biome): re-enable noDoubleEquals ruleFuwn2026-03-011-1/+1
|
* perf: optimise list hot paths and shared timersFuwn2026-03-011-30/+79
|
* fix: Resolve all ESLint errors and warningsFuwn2026-01-292-2/+2
|
* deps(sveltekit): Migrate to SvelteKit 2Fuwn2026-01-221-1/+1
|
* fix: Throw redirectsFuwn2025-12-011-1/+1
|
* refactor(stores): Generic persistent storage facilityFuwn2025-06-111-0/+19
|
* deps(SvelteKit): Migrate to SvelteKit 2Fuwn2025-06-091-1/+1
|
* feat(oauth): Expire session after 180 daysFuwn2025-05-271-1/+1
|
* fix(badges): Properly set badge time when mutatingFuwn2025-05-021-7/+1
|
* style: Run formatterFuwn2025-02-141-10/+11
|
* feat(notifications): initial notification update on first visitFuwn2025-01-281-1/+1
|
* feat(notifications): fallback on service-worker-less notificationsFuwn2025-01-281-0/+26
|
* fix(notifications): better permission request flowFuwn2025-01-281-14/+20
|
* refactor(authorised): move authorised user functionality to moduleFuwn2024-11-181-0/+5
|
* chore(prettier): use spaces instead of tabsFuwn2024-10-0912-194/+194
|
* feat(notifications): fingerprint for multiple grantsFuwn2024-08-242-3/+19
|
* fix(notifications): allow silent notificationsFuwn2024-07-251-1/+1
|
* feat: background notificationsFuwn2024-07-241-0/+22
|
* feat(proxy): drop headersFuwn2024-07-231-1/+1
|
* fix(proxy): proxy by defaultFuwn2024-07-231-1/+1
|
* feat(proxy): enable level two proxy encodingFuwn2024-07-231-3/+11
|
* feat(proxy): encode proxy requestsFuwn2024-07-121-1/+1
|
* refactor(image): move cdn to imageFuwn2024-04-192-22/+46
|
* fix(time): proper database time updateFuwn2024-02-121-1/+17
|
* fix(time): database time to dateFuwn2024-02-121-2/+1
|
* fix(hololive): proxy scheduleFuwn2024-02-071-1/+1
|
* feat: stronger logoutFuwn2024-02-061-3/+2
|
* fix(cdn): don't proxy catboxFuwn2024-02-041-1/+2
|
* feat(schedule): shorten long titlesFuwn2024-02-021-0/+2
|
* fix(html): height observer memory leakFuwn2024-02-011-26/+33
|
* fix(updates): no details observerFuwn2024-01-261-4/+6
|