fix(security): harden authorization and resource limits - #3688
Merged
Conversation
Existing tasks-only tokens that used expand=comments, expand=reactions or expand=time_entries_count will start receiving 401; they need to add the tasks_comments, reactions or time_entries read_all scope respectively.
Also fixes IsErrInvalidFilterExpression to use errors.As: the parse paths return pointer errors while the checker asserted a value type, so an unparsable saved filter hard-failed its view instead of being skipped.
Decoding now validates image dimensions before allocating pixels (imaging.Fit replaces unbounded Resize so neither side can blow up), backgrounds decode once and reuse the image for the blur hash, and DownloadImage is bounded at the configured max file size. Small sources now keep their native size (Fit does not upscale); the frontend scales via CSS.
Per-job budget: 128 MiB aggregate response bytes (counted while decoding, not from Content-Length), 64 MiB retained attachments, 50,000 decoded entities and 2,000 outbound request attempts counted at the transport level so retries cannot multiply work. The per-response cap drops to 4 MiB. Budget exhaustion aborts the import with a typed error; ordinary 404/timeout attachment failures keep the log-and-skip.
Preflight over the declared uncompressed sizes (overflow-safe), a file count cap and a per-user storage quota bound the import before anything is read; the actual decompressed bytes are still counted against the same budget while reading. Attachments and backgrounds now stream through a lazy provider: one zip entry is decompressed into a private temp file at a time. A failed import deletes the file blobs it wrote, which were orphaned for every migrator before.
tink-bot
temporarily deployed
to
preview-trusted
August 31, 2026 15:44 — with
GitHub Actions
Inactive
kolaente
enabled auto-merge (rebase)
August 31, 2026 15:44
Preview DeploymentPreview deployments for this PR are available at:
The preview environment will start automatically on first visit. Subsequent pushes to this PR will update the Run locally with Dockerdocker pull ghcr.io/go-vikunja/vikunja:pr-3688
docker run -p 3456:3456 ghcr.io/go-vikunja/vikunja:pr-3688Last updated for commit d55cfbc |
tink-bot
temporarily deployed
to
preview-trusted
August 31, 2026 15:59 — with
GitHub Actions
Inactive
tink-bot
temporarily deployed
to
preview-trusted
August 31, 2026 16:11 — with
GitHub Actions
Inactive
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hardens shared authorization, parsing, media, rate-limit, and migration boundaries covered by the pending security advisory batch.
References: GHSA-xxc3-xpmc-vmvr, GHSA-pqf9-h8g4-8gmh, GHSA-wq92-8x3r-fm38, GHSA-4vh2-39rq-rq8j, GHSA-w7jp-mf2v-8342, GHSA-m469-88xx-8rx2, GHSA-8wvg-r2j4-3737, GHSA-w2ch-4xgr-22ww, GHSA-g38j-7v97-x298, GHSA-3hc7-r24j-rpwc, GHSA-jp29-jrxc-92vf, GHSA-39p5-2wrr-xh29, GHSA-vfxw-3x8p-2vjr, GHSA-88f6-4rjv-x774, GHSA-9rg3-v78m-26q8, GHSA-w39f-h553-h2mx, GHSA-qfwc-vx6f-3g6g.
How to verify
Configure low CSV and Vikunja-file import limits, then run an import at the limit, one above it, and two simultaneous imports for the same user.
Expected: The bounded import succeeds, oversized imports return a 4xx resource-limit error, overlapping imports return 412, and a failed import can be retried.
Create two users with access to different projects and teams, then exercise task relations, subtasks, favorites, positions, team attachment, user listings, and link-share reads across that boundary.
Expected: Authorized operations still work, while inaccessible tasks, users, team details, and link-share hashes are neither returned nor modified.
Enable TOTP, query its status and QR endpoint, submit repeated invalid BasicAuth requests, and upload both normal and oversized images.
Expected: Enabled TOTP secrets stay hidden, its QR endpoint is denied, failed BasicAuth attempts are limited without limiting successful requests, normal images work, and hostile dimensions return 400.