[feat] Serve static files with native content types#14090
[feat] Serve static files with native content types#14090lukasmasuch merged 6 commits intodevelopfrom
Conversation
Remove the SAFE_APP_STATIC_FILE_EXTENSIONS allowlist that forced non-allowlisted file types to be served as text/plain. Files are now served with their natural content type using guess_content_type(). Both Tornado and Starlette handlers now use the same guess_content_type function for consistent behavior. The X-Content-Type-Options: nosniff header remains in place to prevent MIME-type sniffing attacks.
✅ PR preview is ready!
|
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
There was a problem hiding this comment.
Pull request overview
This PR removes the content-type allowlist for static files served from the app/static/ directory, allowing files to be served with their native MIME types instead of forcing non-allowlisted types to text/plain. The change enables developers to serve HTML, CSS, and JavaScript files with proper content types while maintaining security through the X-Content-Type-Options: nosniff header.
Changes:
- Removed
SAFE_APP_STATIC_FILE_EXTENSIONSallowlist that restricted which file types could be served with native content types - Both Tornado and Starlette handlers now consistently use
guess_content_type()for determining content types - Updated tests to verify correct content-type headers for JavaScript files while maintaining nosniff header checks
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| lib/streamlit/web/server/app_static_file_handler.py | Removed allowlist constant and logic; added get_content_type() override to use guess_content_type() |
| lib/streamlit/web/server/starlette/starlette_routes.py | Removed allowlist usage and now directly passes guess_content_type() result to FileResponse |
| lib/tests/streamlit/web/server/app_static_file_handler_test.py | Updated tests to verify JavaScript files get appropriate content types instead of text/plain |
- Add comment explaining unused path parameter in set_extra_headers - Add test coverage for HTML and CSS file content types
## Describe your changes Automated snapshot updates for #14090 created via the snapshot autofix CI workflow. This workflow was triggered by adding the `update-snapshots` label to a PR after Playwright E2E tests failed with snapshot mismatches. **Updated snapshots:** 1 file(s)⚠️ **Please review the snapshot changes carefully** - they could mask visual bugs if accepted blindly. This PR targets a feature branch and can be merged without review approval. Co-authored-by: Streamlit Bot <[email protected]>
Consolidated Code ReviewSummaryThis PR removes the Key changes:
Code QualityBoth reviewers agreed the implementation is clean, well-structured, and follows existing codebase patterns. Specific positives:
Minor observation (opus-4.6-thinking only): In Test CoverageBoth reviewers agreed the Tornado-side test updates are appropriate and well-constructed:
Disagreement on Starlette test coverage:
Resolution: After verifying the code, I agree with opus-4.6-thinking's assessment. The Starlette change at line 852 is a one-line change ( Backwards CompatibilityBoth reviewers agreed this is an intentional and beneficial behavior change:
Security & RiskBoth reviewers agreed the security posture is appropriate, with slightly different risk assessments:
Resolution: Risk is low-to-moderate but properly mitigated:
AccessibilityBoth reviewers agreed: No frontend UI changes; no accessibility concerns. Recommendations
VerdictAPPROVED: Clean, well-tested removal of an overcautious content-type restriction. The core logic is sound, properly tested on the Tornado side, uses the shared Consolidated review by 📋 Review by `gpt-5.3-codex-high`SummaryThis PR updates static file serving to use native MIME type detection instead of an extension allowlist, and aligns Tornado and Starlette behavior via Code QualityThe implementation is generally clean and improves consistency between server stacks. I found two issues that should be addressed before merge:
Test CoverageCoverage is improved for Tornado static file serving in
Backwards CompatibilityThis is an intentional behavior change: files that previously defaulted to Security & RiskRisk is moderate and mostly around behavioral surface area:
AccessibilityNo frontend code paths were modified, so there are no direct accessibility changes to assess in this PR. Recommendations
VerdictCHANGES REQUESTED: The core implementation is close, but missing Starlette-side behavioral tests and an unrelated snapshot binary change make this not ready to merge yet. This is an automated AI review by 📋 Review by `opus-4.6-thinking`SummaryThis PR removes the Key changes:
Code QualityThe code is clean, well-structured, and follows existing patterns in the codebase. Positives:
Minor observation:
Test CoverageThe test updates are appropriate and cover the behavioral change well:
Missing test coverage considerations:
Backwards CompatibilityThis is an intentional behavior change, but the PR author and team have assessed it:
This change is backwards compatible from the user-facing API perspective. The behavioral change (correct content types) is a feature improvement, not a regression. Security & RiskThis change has security implications that appear to have been properly evaluated (the PR has the
Risk level: Low. The security posture is appropriate given that static file serving is developer-controlled and already optional. AccessibilityNo frontend UI changes in this PR. The snapshot update for Recommendations
VerdictAPPROVED: Clean, well-tested removal of an overcautious content-type restriction for static file serving, with proper security mitigations retained. The change brings consistency between Tornado and Starlette handlers and aligns static file serving behavior with custom components. This is an automated AI review by |
Describe your changes
We have a bit overcautious limitation of our static file serving to only allow a couple of selected types to be served with the correct file type. This was put in place for the initial release with the goal reduce this limitation, but this never happened. In its current state, you can already serve any file type with custom components without limitations, and Starlette adds another way for developers to serve arbitrary files with correct file types. Based on that, there doesn't seem to be a reason why we would need this limitation for the static file serving feature. Especially since it's already behind a config option.
SAFE_APP_STATIC_FILE_EXTENSIONSallowlist that forced non-allowlisted file types (like.js,.html,.css) to be served astext/plainguess_content_type()guess_content_typefunction for consistent behaviorTesting Plan