Skip to content

fix(api): accept MIME types with parameters or whitespace (CS-217)#2576

Merged
tofikwest merged 2 commits intomainfrom
tofik/cs-217-mime-type-validation
Apr 16, 2026
Merged

fix(api): accept MIME types with parameters or whitespace (CS-217)#2576
tofikwest merged 2 commits intomainfrom
tofik/cs-217-mime-type-validation

Conversation

@tofikwest
Copy link
Copy Markdown
Contributor

@tofikwest tofikwest commented Apr 16, 2026

Summary

Fixes CS-217 — customer file upload endpoints returning 400 Invalid MIME type format for legitimate application/pdf and application/vnd.openxmlformats-officedocument.spreadsheetml.sheet values.

Root cause: Four DTOs (attachments, tasks/dto, task-management/dto, org-chart/dto) each declared @Matches(/^[a-zA-Z0-9\-]+\/[a-zA-Z0-9\-\+\.]+$/) with no trim or parameter strip. So the regex itself accepts bare application/pdf, but the customer's HTTP client is almost certainly sending the Content-Type with a parameter (e.g. application/pdf;charset=utf-8) or trailing whitespace/newline, which the regex rejects.

Fix: Extracted a shared IsMimeTypeField decorator + normalizeMimeType helper in apps/api/src/utils/mime-type.validator.ts. It:

  • Strips RFC 7231 media-type parameters (;...) and whitespace before validation
  • Lowercases the value
  • Validates against the RFC 6838 restricted-name-chars grammar

Applied the new decorator to all four DTOs and removed the now-duplicated inline regex. Also removed dead BLOCKED_MIME_TYPES constants from two DTOs — the real enforcement lives in attachments.service.ts and always operated on the lowercased value.

Test plan

  • 18 unit tests in mime-type.validator.spec.ts cover:
    • Regression: application/pdf, application/pdf;charset=utf-8, the full xlsx vendor type, trailing whitespace/newline, uppercase, application/vnd.api+json, image/svg+xml
    • Negative: empty, missing slash, leading/trailing slash, spaces inside type, multiple slashes, non-strings
  • cd apps/api && npx jest src/utils/mime-type.validator → 18/18 pass
  • Full API typecheck: no new errors on changed files (pre-existing unrelated failures only)
  • Manual: re-run customer's failing upload (application/pdf;charset=utf-8) against staging — should succeed
  • Manual: attempt to upload application/javascript;charset=utf-8 — should still be rejected by attachments.service.ts blocklist

Notes

  • The customer's report says uploads "worked previously". The current regex has been in place since Nov 20, 2025 (commit 6c2844b replaced an @IsIn allow-list with it). So the "worked previously" timeframe predates the regex; likely the customer's HTTP client changed recently and began including ;charset=... parameters in the fileType field.
  • No schema changes. No new DB fields.

🤖 Generated with Claude Code


Summary by cubic

Fixes CS-217 by accepting MIME types with parameters or whitespace in file upload requests. Adds a shared IsMimeTypeField validator to normalize and validate values, preventing 400s for legitimate types like application/pdf;charset=utf-8.

  • Bug Fixes
    • Added IsMimeTypeField with normalizeMimeType to strip parameters/whitespace, lowercase, and validate per RFC 6838.
    • Replaced inline regex in four DTOs (attachments, tasks, task-management, org-chart); removed unused BLOCKED_MIME_TYPES constants (blocklist stays in attachments.service.ts).
    • Added 18 unit tests covering regressions (application/pdf, vendor xlsx type, +json, case/whitespace) and invalid inputs.

Written for commit 911a790. Summary will update on new commits.

File upload endpoints were rejecting valid Content-Type values like
`application/pdf;charset=utf-8` or `application/pdf\n` with a 400
"Invalid MIME type format" error, because each DTO enforced the regex
/^[a-zA-Z0-9\-]+\/[a-zA-Z0-9\-\+\.]+$/ with no trim or parameter strip.

Extracts a shared `IsMimeTypeField` decorator (+ `normalizeMimeType`
helper) that:
- strips RFC 7231 media-type parameters (`;charset=...`) and whitespace
- lowercases the value before validation and persistence
- matches the RFC 6838 restricted-name-chars grammar

Applied to all four upload DTOs:
- attachments/upload-attachment.dto.ts
- tasks/dto/upload-attachment.dto.ts
- task-management/dto/upload-task-item-attachment.dto.ts
- org-chart/dto/upload-org-chart.dto.ts

Also removes dead `BLOCKED_MIME_TYPES` constants from two DTOs — the
actual blocklist lives in `attachments.service.ts` and operates on
the already-lowercased fileType.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
app Ready Ready Preview, Comment Apr 16, 2026 9:11pm
comp-framework-editor Ready Ready Preview, Comment Apr 16, 2026 9:11pm
portal Ready Ready Preview, Comment Apr 16, 2026 9:11pm

Request Review

@linear
Copy link
Copy Markdown

linear Bot commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 6 files

Auto-approved: Fixes MIME type validation bug (CS-217) by normalizing inputs. Low risk, high test coverage (18 unit tests), and cleans up redundant DTO code.

Linked issue analysis

Linked issue: CS-217: Invalid MIME type format error in API

Status Acceptance criteria Notes
Strip RFC 7231 media-type parameters and whitespace before validation (accept application/pdf;charset=utf-8 and trailing whitespace) normalizeMimeType strips parameters/whitespace; decorator transforms value
Lowercase the value before validation normalizeMimeType lowercases the value
Validate against the RFC 6838 restricted-name-chars grammar MIME_TYPE_REGEX implements restricted-name-chars grammar
Add shared IsMimeTypeField decorator and normalizeMimeType helper in apps/api/src/utils/mime-type.validator.ts New file exports IsMimeTypeField and normalizeMimeType
Apply the new decorator to four DTOs (attachments, tasks/dto, task-management/dto, org-chart/dto) DTOs now import and use @IsMimeTypeField() for fileType
Remove duplicated inline regex from those DTOs Inline @matches regex removed from the DTOs
Remove dead BLOCKED_MIME_TYPES constants from two DTOs (attachments and tasks) BLOCKED_MIME_TYPES arrays deleted from DTO files
Ensure blocklist enforcement remains in attachments.service.ts and operates on the lowercased value No changes or references to attachments.service.ts in diffs
Add unit tests covering regressions and negative cases (18 tests) mime-type.validator.spec.ts with the described test cases was added
Full API typecheck: no new errors on changed files No CI/typecheck output or artifacts included in diffs
Manual: re-run customer's failing upload (application/pdf;charset=utf-8) against staging — should succeed No evidence of manual staging test or results in the PR
Manual: attempt to upload application/javascript;charset=utf-8 — should still be rejected by attachments.service.ts blocklist No tests or code changes shown that exercise attachments.service.ts blocklist
Keep validation message 'Invalid MIME type format' for consistency Matches(...) retains message 'Invalid MIME type format' in validator
No schema changes or DB fields Changed files are DTOs and utils; no DB/schema files modified

@tofikwest tofikwest merged commit 0f2244f into main Apr 16, 2026
11 checks passed
@tofikwest tofikwest deleted the tofik/cs-217-mime-type-validation branch April 16, 2026 21:13
@claudfuen
Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.23.2 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants