Skip to content

feat: harden download endpoints and document API usage (#5) - #155

Open
iprasen wants to merge 1 commit into
tscircuit:mainfrom
iprasen:feat/harden-download-endpoints-5
Open

iprasen wants to merge 1 commit into
tscircuit:mainfrom
iprasen:feat/harden-download-endpoints-5

Conversation

@iprasen

@iprasen iprasen commented Sep 18, 2026

Copy link
Copy Markdown

Resolves #5

Summary

Hardens the download endpoints (/files/download?... and /files/download/[[file_path]]), improves header sanitization and binary edge case handling, and documents the download API in the README.

Key Changes

  1. Header Sanitization: Added formatDownloadContentDisposition utility to sanitize filename quotes and linebreaks in Content-Disposition: attachment; filename="..." to prevent header injection while maintaining compatibility with existing consumers.
  2. Empty Binary Files: Fixed condition if (!isText && file.binary_content_b64 !== undefined) so 0-byte binary files (binary_content_b64: "") are served as application/octet-stream with Content-Length: 0 instead of falling back to text.
  3. Documentation: Added comprehensive documentation in README.md for both query parameter style (/files/download?file_path=... and /files/download?file_id=...) and path parameter style (/files/download/path/to/file.txt).
  4. Test Suite: Added tests/routes/download-hardening.test.ts testing filenames with spaces, 0-byte binary files, and 404 responses across both query and path parameter styles.

Verification

  • bun test: All 32 tests passed across 10 files (0 failures, 188 assertions)
  • bun run format:check: Passed (Biome 100% clean)
  • bun run build: Winterspec bundle and tsup CLI build succeeded cleanly
  • bunx tsc --noEmit: Passed with 0 errors

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.

Create download endpoint /files/download?... as well as /files/download/[[file_path]]

1 participant