Skip to content

fix: enforce FILE_SIZE_LIMIT on published Space asset upload#9242

Open
sriramveeraghanta wants to merge 2 commits into
previewfrom
fix/space-asset-size-limit-bypass
Open

fix: enforce FILE_SIZE_LIMIT on published Space asset upload#9242
sriramveeraghanta wants to merge 2 commits into
previewfrom
fix/space-asset-size-limit-bypass

Conversation

@sriramveeraghanta

@sriramveeraghanta sriramveeraghanta commented Jun 16, 2026

Copy link
Copy Markdown
Member

Description

The published Space asset upload endpoint POST /api/public/assets/v2/anchor/{anchor}/ (apps/api/plane/space/views/asset.py) trusted the client-supplied size value end-to-end. It read size = int(request.data.get("size", settings.FILE_SIZE_LIMIT)), stored that value on the FileAsset, and passed it directly to storage.generate_presigned_post(..., file_size=size), which uses it as the upper bound of the signed S3/MinIO policy (["content-length-range", 1, file_size]).

Because the policy is signed by the backend, an authenticated user could intercept the asset-metadata request, set size above the instance limit, and obtain a presigned POST policy permitting an oversized upload — bypassing the configured FILE_SIZE_LIMIT and enabling storage abuse / resource exhaustion through published issue-comment uploads.

This was the only asset upload path missing the cap that every other endpoint (app/views/asset/v2.py, api/views/asset.py, app/views/issue/attachment.py) already applies.

Fix: cap the client-provided size with size_limit = min(size, settings.FILE_SIZE_LIMIT) and use size_limit consistently for the stored asset metadata (attributes + size) and the generate_presigned_post() call, so the signed policy can never exceed the instance limit.

Reported via responsible disclosure to security@plane.so.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Improvement (change that would cause existing functionality to not work as expected)
  • Code refactoring
  • Performance improvements
  • Documentation update

Screenshots and Media (if applicable)

Test Scenarios

  • With FILE_SIZE_LIMIT=5242880 (5 MB), call POST /api/public/assets/v2/anchor/{anchor}/ with size set to 10485760 (10 MB). Decode the returned presigned policy and confirm content-length-range upper bound is 5242880, not the requested 10485760.
  • Confirm the stored FileAsset.size and attributes.size equal the capped value (≤ FILE_SIZE_LIMIT), not the client-supplied value.
  • Attempt a direct MinIO/S3 upload of a file > 5 MB using the returned presigned fields and confirm it is rejected by the signed policy.
  • Regression: upload a normal image under the limit through a published Space issue comment and confirm it still succeeds end-to-end (presigned POST → upload → PATCH mark uploaded).

References

  • Responsible disclosure: "Published Space Asset Upload Size Limit Bypass" (security@plane.so)

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Improved file upload size handling by validating the provided size, rejecting invalid values, and enforcing the configured maximum size limit consistently.
    • Updated the upload policy used for direct uploads so it matches the capped size limit.

The public Space asset upload endpoint
(POST /api/public/assets/v2/anchor/{anchor}/) trusted the client-supplied
`size` value end-to-end: it was stored on the FileAsset and passed straight
to generate_presigned_post(), which uses it as the S3/MinIO policy bound
(["content-length-range", 1, file_size]). This let an authenticated user
obtain a signed upload policy exceeding the instance's FILE_SIZE_LIMIT.

Cap the value with `size_limit = min(size, settings.FILE_SIZE_LIMIT)` and use
it consistently for the stored asset metadata and the presigned POST policy,
matching every other asset upload endpoint.
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

In EntityAssetEndpoint.post, the client-provided size is now validated with a 400 error on invalid input, then capped to settings.FILE_SIZE_LIMIT via a size_limit variable. This capped value replaces the original size in FileAsset creation (attributes.size and size fields) and in the presigned upload policy generation (file_size parameter).

Changes

Upload Size Cap in EntityAssetEndpoint

Layer / File(s) Summary
Size validation, cap computation, FileAsset storage, and presigned URL enforcement
apps/api/plane/space/views/asset.py
Validates the client size parameter and returns HTTP 400 if not an integer. Computes size_limit = min(size, settings.FILE_SIZE_LIMIT) and uses it for FileAsset.attributes.size, FileAsset.size, and presigned upload file_size instead of the uncapped client value.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

🐇 A sneaky big file tried to slip through the gate,
But size_limit said, "Hold on, mate!"
Validated and clamped with a min() so tight,
The presigned URL blinks with delight.
No oversized uploads shall pass today —
The rabbit has bounded the bytes away! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and clearly describes the main change: enforcing FILE_SIZE_LIMIT on the published Space asset upload endpoint.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The pull request description thoroughly addresses all required template sections with comprehensive details about the security fix, including clear problem statement, solution, test scenarios, and references.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/space-asset-size-limit-bypass

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 16, 2026

Copy link
Copy Markdown

No React Doctor issues found. 🎉

Reviewed by React Doctor for commit f8a918e.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/api/plane/space/views/asset.py`:
- Around line 83-85: The size_limit calculation at line 85 only enforces an
upper bound but allows non-positive size values to pass through. Add validation
before the size_limit assignment to check if size is less than or equal to 0,
and if so, return a 400 Bad Request error response. Then update the size_limit
calculation to clamp the value to the range [1, FILE_SIZE_LIMIT] using max(1,
min(size, settings.FILE_SIZE_LIMIT)) to enforce both the lower and upper bounds,
ensuring only valid asset sizes are used for signing uploads.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d91f263a-6928-41d5-8251-51e7db161ffa

📥 Commits

Reviewing files that changed from the base of the PR and between f2feca6 and 5b37cac.

📒 Files selected for processing (1)
  • apps/api/plane/space/views/asset.py

Comment thread apps/api/plane/space/views/asset.py Outdated
Address review feedback: reject malformed (non-integer) `size` with 400 and
clamp the value to [1, FILE_SIZE_LIMIT] via max(1, min(...)) so the presigned
content-length-range is always valid and no non-positive size is persisted.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant