Skip to content

feat(api): allow text/html attachments - #9552

Open
Semih702 wants to merge 1 commit into
makeplane:previewfrom
Semih702:fix/9543-allow-html-attachments
Open

feat(api): allow text/html attachments#9552
Semih702 wants to merge 1 commit into
makeplane:previewfrom
Semih702:fix/9543-allow-html-attachments

Conversation

@Semih702

@Semih702 Semih702 commented Aug 5, 2026

Copy link
Copy Markdown

Description

text/html and application/xhtml+xml were missing from ATTACHMENT_MIME_TYPES, so uploading an .html file to a work item fails with 400 {"error": "Invalid file type."}. HTML reports (Playwright, Jest, Lighthouse, JaCoCo), exported emails and BI exports are common things to attach to a work item, and the workaround today is to zip the file or rename it to .txt, which loses the extension.

This adds both types to the allowlist. No other change is needed.

On the security side: the obvious objection here is stored XSS, but that path is already closed. Both types are already members of SCRIPT_CAPABLE_MIME_TYPES, and since #9312 / GHSA-ch8j-vr4r-qf6h every asset download path pins those types to Content-Disposition: attachment:

  • GenericAssetEndpoint.getapps/api/plane/api/views/asset.py
  • StaticFileAssetEndpoint.getapps/api/plane/app/views/asset/v2.py
  • EntityAssetEndpoint.getapps/api/plane/space/views/asset.py

The two work item attachment download endpoints (IssueAttachmentV2Endpoint.get and its /api/v1 sibling) hardcode disposition="attachment" regardless of type. I went through every S3Storage.generate_presigned_url call site in the repo — all of them either hardcode attachment or derive it from SCRIPT_CAPABLE_MIME_TYPES, none fall through to the inline default. So an uploaded HTML file gets downloaded, never rendered on the app's origin.

The precedent is image/svg+xml, which is equally script-capable, already uploadable, and protected by exactly this mechanism.

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)

Not applicable — no UI change. The upload dropzone has no client-side accept filter, so the server allowlist is the only gate.

Test Scenarios

Added apps/api/plane/tests/contract/app/test_issue_attachment_mime_types_app.py covering IssueAttachmentV2Endpoint:

  • uploading text/html and application/xhtml+xml returns 200 and stores the type (fails on preview without this change)
  • a type outside the allowlist still gets rejected with 400 and creates no asset row
  • downloading an HTML attachment asks S3 for disposition="attachment"
  • both types stay in SCRIPT_CAPABLE_MIME_TYPES — this is the guard that keeps the allowlist entry safe, so it fails loudly if someone ever drops them from there

Run via docker-compose-test.yml:

plane/tests/contract/app/test_issue_attachment_mime_types_app.py .......
7 passed

Full API suite: 523 passed with this branch, against a 516-passed baseline on preview (7 new tests, nothing else changed). ruff check and ruff format are clean on both files.

I did leave ACCEPTED_ATTACHMENT_MIME_TYPES in packages/editor alone — that list gates editor drag-and-drop, which is a separate surface from work item attachments, and I didn't want to change its behaviour in this PR. Happy to add it there too if you'd prefer them kept in sync.

References

Closes #9543
Related: #9312 / GHSA-ch8j-vr4r-qf6h

text/html and application/xhtml+xml were missing from ATTACHMENT_MIME_TYPES,
so uploading an .html file to a work item failed with "Invalid file type."
HTML reports (Playwright, Jest, Lighthouse, JaCoCo) are a common thing to
attach, and the workaround so far has been to zip the file or rename it to
.txt, which loses the extension.

Both types are already members of SCRIPT_CAPABLE_MIME_TYPES, so every asset
download path already pins them to Content-Disposition: attachment (makeplane#9312 /
GHSA-ch8j-vr4r-qf6h). The browser downloads them rather than rendering them,
which is the same protection image/svg+xml has had since that fix.

Closes makeplane#9543
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The attachment allowlist now accepts text/html and application/xhtml+xml. Contract tests cover upload persistence, download attachment disposition, unsupported MIME rejection, and consistency with the script-capable allowlist.

Changes

HTML attachment support

Layer / File(s) Summary
MIME allowlist update
apps/api/plane/settings/common.py
Adds text/html and application/xhtml+xml to ATTACHMENT_MIME_TYPES.
Attachment behavior contract tests
apps/api/plane/tests/contract/app/test_issue_attachment_mime_types_app.py
Tests upload acceptance, persisted MIME types, download attachment disposition, rejection of application/hta, and membership in both MIME allowlists.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • makeplane/plane#8524: Updates attachment MIME-type allowlists for additional text-based file types.

Suggested reviewers: dheeru0198

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR satisfies issue #9543 by allowing both MIME types, preserving attachment download protection, and testing unsupported-type rejection.
Out of Scope Changes check ✅ Passed The changes are limited to the attachment MIME allowlist and related contract tests described in issue #9543.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title clearly and concisely describes the main change: allowing HTML attachments in the API.
Description check ✅ Passed The description covers the change, type, security considerations, tests, screenshots status, and issue references.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

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.

[feature]: allow text/html attachments now that script-capable types are served as downloads

2 participants