| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
| |
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).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
| |
This reverts commit 13226aaeb7c4dc1ce01074ef1ba1eeb87b53d5f5.
|
| |
|
|
|
|
|
| |
setShadowHidden is async and hits Supabase. The PUT handler called it
without await, so the handler could respond before the database write
landed (and any error was silently lost). Add the missing await so the
response only goes out after the update settles.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
The refresh endpoint accepted a ?redirect query param and, when
present, called redirect(303, "/") instead of returning the refreshed
token as JSON. The target was hardcoded to "/" regardless of the
param's value, so the feature was dead — and the pattern of reading
a "redirect" param invited future open-redirect bugs if someone wired
the value through to redirect() directly.
The sole in-tree caller (feeds/activity-notifications) reads the JSON
response, so always return JSON and drop the redirect import.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
The PUT ?incrementClickCount path ran before any auth guard, letting
unauthenticated callers spam-increment arbitrary badges. Require the
request Origin to match appOrigin() so legitimate in-browser clicks
(authenticated or not) still count while direct scripted calls are
rejected.
Also convert the shared `unauthorised` Response singleton into a
factory. The singleton's body was consumed on first use, so subsequent
401 paths returned a `Response body is locked` error instead of the
intended "Unauthorised" body.
|
| |
|
|
|
|
|
| |
The `tz` query value was interpolated raw into the upstream URL, letting
callers append arbitrary query segments (e.g. `tz=foo&f=hax`). Wrap the
value in encodeURIComponent and rename the local variable away from the
banned `tz` abbreviation.
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|