fix(security): add comprehensive CSP and security headers#405
Open
DeryFerd wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Clopen currently lacks Content Security Policy (CSP) headers and other essential security headers, leaving the application vulnerable to several attack vectors:
X-Content-Type-Optionsallows browsers to incorrectly interpret file types, potentially executing malicious content disguised as benign filesWhile DOMPurify provides frontend XSS mitigation for markdown rendering, defense-in-depth requires server-side security headers as an additional layer of protection.
Why This Matters
Security headers are a fundamental defense mechanism that should be present in any web application handling sensitive data. Clopen manages:
A single XSS vulnerability or clickjacking attack could compromise any of these systems, leading to:
Implementing comprehensive security headers significantly raises the bar for attackers and provides multiple layers of defense even if other security mechanisms fail.
What Changed
New Security Middleware (
backend/middleware/security.ts)Created a comprehensive security headers middleware that applies the following protections to all HTTP responses:
Content Security Policy (CSP):
default-src 'self'- Restricts all resources to same-origin by defaultscript-src 'self' 'unsafe-inline' 'unsafe-eval'- Allows Monaco Editor's web workers and inline scripts while blocking external scriptsstyle-src 'self' 'unsafe-inline'- Supports Monaco Editor and Tailwind CSS inline stylesimg-src 'self' data: blob:- Enables base64 images and blob URLs from browser previewconnect-src 'self' ws: wss:- Permits WebSocket connections for real-time featuresfont-src 'self' data:- Supports custom fonts and data URIsframe-ancestors 'none'- Prevents embedding in iframes (clickjacking protection)frame-src 'self'- Allows same-origin iframes for browser preview functionalityworker-src 'self' blob:- Enables Monaco Editor's web workers from blob URLsAdditional Security Headers:
X-Content-Type-Options: nosniff- Forces browsers to respect declared content types, preventing MIME-sniffing attacksX-Frame-Options: DENY- Redundant clickjacking protection (defense-in-depth with CSPframe-ancestors)Referrer-Policy: strict-origin-when-cross-origin- Limits referrer information to origin only for cross-origin requestsPermissions-Policy- Restricts access to sensitive browser APIs (camera, microphone, geolocation, payment, USB, sensors)Integration (
backend/index.ts)securityMiddlewarein the Elysia application pipelineonAfterHandlehook to inject headers into all responses consistentlyDesign Decisions
Why allow
unsafe-inlineandunsafe-evalin CSP?Monaco Editor (the code editor component) requires these directives to function:
unsafe-evalis necessary for web workers that provide syntax highlighting, IntelliSense, and language featuresunsafe-inlineis needed for dynamic style injection used by Monaco's theming systemWhile these directives reduce CSP effectiveness, the alternatives are:
The implemented CSP still provides significant protection by blocking external scripts and resources while maintaining Monaco functionality.
Why use
onAfterHandleinstead of a separate middleware plugin?Elysia's lifecycle hooks ensure headers are applied consistently to all responses including:
This guarantees no response bypasses security headers.
Testing
Validation Performed
bun run lintpasses with no errorsbackend/middleware/(consistent withcors.ts,error-handler.ts,logger.ts)securityMiddlewareexports correctlyManual Testing Recommendations
After merging, verify headers are present in responses:
Expected headers in response:
Application Functionality Testing
These areas should be manually verified to ensure CSP doesn't break existing features:
Risk Assessment
Risk Level: Low
This is an additive change that:
Potential Issues:
Mitigation:
onAfterHandle(easily reversible)Backward Compatibility
✅ Fully backward compatible
Future Improvements
This PR establishes the foundation for additional security enhancements:
report-uridirective to monitor CSP violationsStrict-Transport-Securityfor HTTPS deployments