Skip to content

feat: support .md and .mdx file uploads - #8995

Open
sriramveeraghanta wants to merge 5 commits into
previewfrom
feat/file-uploads-md-mdx-support
Open

sriramveeraghanta wants to merge 5 commits into
previewfrom
feat/file-uploads-md-mdx-support

Conversation

@sriramveeraghanta

@sriramveeraghanta sriramveeraghanta commented May 2, 2026 •

Copy link
Copy Markdown
Member

Description

Adds .md, .markdown, and .mdx support to the work-item attachment flow.

  • Falls back to a validated filename extension when signature detection cannot identify plain-text Markdown files.
  • Represents MDX uploads as the existing text/markdown MIME type, so no API or editor allow-list change is required.
  • Rejects invalid filenames and dangerous extension chains before extension fallback, including names such as file.exe.safe.md.
  • Uses the text-file icon for Markdown and MDX extensions case-insensitively, including the attachment detail view.

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)

N/A — this changes attachment upload validation and icon selection without introducing new UI.

Test Scenarios

  • pnpm --filter=@plane/services test — 15 tests passed.
  • pnpm --filter=web test — 7 tests passed.
  • Services and web format, lint, and type checks passed.
  • Services and web production builds passed.
  • Full workspace pnpm build passed.
  • Full pnpm check reaches an existing formatting failure in packages/i18n/src/types/keys.generated.ts; that file is unchanged by this PR, and all affected-package checks pass.

References

N/A

Summary by CodeRabbit

  • New Features
    • Markdown files are recognized as text/markdown and display the text-file icon, including uppercase extensions.
  • Bug Fixes
    • File validation now rejects filenames containing unsafe extensions between the first and final filename components.
    • File extensions shown for attachments are determined from the file’s name.
    • When a file signature is detected, it takes precedence over the filename extension. Unsupported files without a recognized signature remain unclassified.
  • Tests
    • Added automated tests for file type detection, icon selection, and validation.

Copilot AI lite review requested due to automatic review settings May 2, 2026 18:31
@coderabbitai

coderabbitai Bot commented May 2, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 5863e6d1-e632-4f51-a817-4bc1a398e5c8
📥 Commits

Reviewing files that changed from the base of the PR and between 4e9c5ea and 09cc3f1.

📒 Files selected for processing (2)
  • packages/services/src/file/helper.test.ts
  • packages/services/src/file/helper.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The upload helper now recognizes Markdown MIME types and checks dangerous filename extensions across intermediate filename components. Web attachment components recognize Markdown extensions, and tests cover the updated behavior.

Changes

Markdown attachment handling

Layer / File(s) Summary
MIME detection and filename validation
packages/services/src/file/helper.ts, packages/services/src/file/helper.test.ts
The upload helper maps Markdown extensions to text/markdown, checks intermediate extensions for dangerous values, and falls back to the filename extension when signature detection finds no MIME type. Tests cover these cases and PNG signature precedence.
Web attachment extension handling
apps/web/components/icons/attachment/*, apps/web/components/issues/attachment/attachment-detail.tsx, apps/web/package.json, apps/web/vitest.config.ts
The icon lookup handles uppercase extensions and maps Markdown extensions to the text icon. Attachment details derive the extension from the attachment name. Vitest configuration and tests support and cover icon selection.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Merge Risk: ⚪ Minimal · up to 09cc3

Markdown and MDX MIME types pass through the attachment API and storage flow; no merge-blocking issue is evident.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: support for Markdown and MDX file uploads.
Description check ✅ Passed The description covers the change, marks it as a feature, explains screenshots are not applicable, lists test scenarios and results, and addresses references.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 6…
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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.

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/services/src/file/helper.ts (1)

112-135: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Do not fall back to the extension after filename validation fails.

validateFilename() already flags suspicious names such as foo.exe.md, but the result is only logged. With the new extension fallback, those files still resolve to text/markdown / text/mdx and can pass the allow-list, which defeats the double-extension safeguard.

Suggested fix
 const validateAndDetectFileType = async (file: File): Promise<string> => {
   // Basic filename validation
   const filenameError = validateFilename(file.name);
   if (filenameError) {
     console.warn(`File validation warning: ${filenameError}`);
+    return "";
   }
 
   try {
     const signatureType = await detectMimeTypeFromSignature(file);
     if (signatureType) {
       return signatureType;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/services/src/file/helper.ts` around lines 112 - 135, If
validateFilename(file.name) returns an error, stop and do not use the extension
fallback; in validateAndDetectFileType, after calling validateFilename use the
returned filenameError to short-circuit and return an empty string (or otherwise
mark the file as unknown/rejected) instead of continuing to
detectMimeTypeFromExtension. Keep the existing signature-based detection path
(detectMimeTypeFromSignature) but only run it when validateFilename passed;
reference validateAndDetectFileType, validateFilename,
detectMimeTypeFromSignature, and detectMimeTypeFromExtension when making this
change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/services/src/file/helper.ts`:
- Around line 112-135: If validateFilename(file.name) returns an error, stop and
do not use the extension fallback; in validateAndDetectFileType, after calling
validateFilename use the returned filenameError to short-circuit and return an
empty string (or otherwise mark the file as unknown/rejected) instead of
continuing to detectMimeTypeFromExtension. Keep the existing signature-based
detection path (detectMimeTypeFromSignature) but only run it when
validateFilename passed; reference validateAndDetectFileType, validateFilename,
detectMimeTypeFromSignature, and detectMimeTypeFromExtension when making this
change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ba97d0e1-9b14-4903-9ecf-89c664a15ef5

📥 Commits

Reviewing files that changed from the base of the PR and between a62fe8a and 86c6b69.

📒 Files selected for processing (4)
  • apps/api/plane/settings/common.py
  • apps/web/core/components/icons/attachment/attachment-icon.tsx
  • packages/editor/src/core/constants/config.ts
  • packages/services/src/file/helper.ts

Copilot AI 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.

Pull request overview

This PR extends Plane’s attachment upload flow to recognize Markdown and MDX files end-to-end by adding extension-based MIME fallback in the shared upload helper, allowing text/mdx through the editor/API allow-lists, and showing text-file icons for markdown attachments.

Changes:

  • Added extension-based MIME detection for plain-text uploads (.md, .markdown, .mdx) when signature detection returns no type.
  • Updated frontend and backend attachment MIME allow-lists to include MDX support.
  • Mapped markdown-family file extensions to the existing text attachment icon.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
packages/services/src/file/helper.ts Adds filename-extension fallback for markdown MIME detection in the shared upload metadata helper.
packages/editor/src/core/constants/config.ts Adds text/mdx to the editor attachment MIME allow-list.
apps/web/core/components/icons/attachment/attachment-icon.tsx Routes md / markdown / mdx extensions to the text-file icon.
apps/api/plane/settings/common.py Adds text/mdx to the backend attachment MIME allow-list and removes a duplicate markdown entry.

Comment thread packages/services/src/file/helper.ts
Comment thread packages/editor/src/core/constants/config.ts Outdated
Comment thread apps/web/components/icons/attachment/attachment-icon.tsx
sriramveeraghanta and others added 3 commits August 4, 2026 21:25
Plain-text files have no magic bytes, so the file-type signature
detector returned an empty MIME type and the backend rejected them.
Add an extension-based fallback for markdown/mdx, allow text/mdx in
the API and editor allow-lists, and pick a file icon for these
extensions.
- Short-circuit validateAndDetectFileType when validateFilename flags a
  suspicious name so files like foo.exe.md cannot bypass the attachment
  allowlist via the new extension MIME fallback.
- Lowercase fileType in getFileIcon so uppercase extensions (e.g. .MD,
  .PDF) resolve to the correct icon.
Copilot AI review requested due to automatic review settings August 4, 2026 16:06
@vihar
vihar force-pushed the feat/file-uploads-md-mdx-support branch from b374796 to 8eeb8d7 Compare August 4, 2026 16:06
@github-actions

github-actions Bot commented Aug 4, 2026 •

Copy link
Copy Markdown

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit 09cc3f1.

Copilot AI 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.

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file
Suppressed comments (2)

apps/web/vitest.config.ts:17

  • resolve.tsconfigPaths = true is not a valid Vite/Vitest config option (tsconfig-path resolution is typically provided via the vite-tsconfig-paths plugin). As-is, Vitest may fail to resolve @/... imports used by tests (e.g. attachment-icon.test.tsx). Configure vite-tsconfig-paths as a plugin (similar to apps/web/vite.config.ts) instead of this custom resolve flag.
import { defineConfig } from "vitest/config";

export default defineConfig({
  resolve: {
    tsconfigPaths: true,
  },
  test: {
    environment: "node",
    include: ["core/**/*.test.{ts,tsx}"],
  },

packages/services/src/file/helper.ts:21

  • The extension fallback maps mdx to text/markdown, but the PR description and related allow-list/accept-list updates reference text/mdx. This mismatch can lead to inconsistent MIME values across the upload pipeline (and makes the text/mdx changes potentially ineffective). Please pick one MIME for .mdx and align this map, the frontend accept list, backend allow-list, and these tests accordingly.
const EXTENSION_MIME_TYPE_MAP: Record<string, string> = {
  md: "text/markdown",
  markdown: "text/markdown",
  mdx: "text/markdown",
};

@vihar

vihar commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

@dheeru0198 @pablohashescobar This PR has been rebased onto current preview, the review feedback is resolved, and the refreshed CI suite is green. The scope is now limited to work-item Markdown and MDX attachments, with MDX using text/markdown and unit coverage added. Could one of you take a final look when you have a chance?

…md-mdx-support

# Conflicts:
#	apps/web/components/icons/attachment/attachment-icon.test.tsx
#	pnpm-lock.yaml
Suspicious filenames now only block the extension-based MIME fallback,
so files whose signature identifies them (e.g. deploy.sh.png) upload as
before. The extension lookup also ignores inherited object properties
such as constructor and __proto__.

This branch has not been deployed

No deployments
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.

3 participants