Fix building the server docker image & security hardening#6
Conversation
Add IsPublicMode static property to CalcpadApiService, controlled by CALCPAD_PUBLIC_MODE env var. In public mode, #include directives are blocked to prevent path traversal. In local mode, file reading is unrestricted (trust local user). Dockerfile sets the env var.
Add SanitizeHtml to strip dangerous HTML tags (script, iframe, object, embed, form, etc.) and event handler attributes from Calcpad output. Add Content-Security-Policy meta tag to HTML wrapper. These protections apply in both public and local modes.
Add wall-clock timeout for expression parsing. Public mode: 15 seconds. Local mode: 300 seconds (5 minutes) for long computations. Uses Task.Run with cancellation to enforce the limit.
Inject Content-Security-Policy meta tag into HTML before Chromium renders it, blocking all external resource loading. Switch from Networkidle0 to DOMContentLoaded to avoid waiting for blocked fetches. Applies in both public and local modes.
Add fixed-window rate limiting: convert=20/min, pdf=5/min, general=100/min in public mode. In local mode, limits are set to int.MaxValue (effectively unlimited). Add [EnableRateLimiting] attributes to controller endpoints.
Limit request body via Kestrel: 512 KB in public mode, 50 MB in local mode. The Kestrel-level limit is sufficient; no per-endpoint attributes needed.
In public mode, return generic error messages to avoid leaking internal details. In local mode, return detailed error messages for debugging. Uses CalcpadApiService.IsPublicMode for the check.
In public mode, restrict CORS to origins from CALCPAD_CORS_ORIGINS env var (default: https://calcpad-ce.org). In local mode, allow any origin so the browser-based client works from any address.
Only expose Swagger UI in local mode. In public mode, the API documentation is hidden to reduce the attack surface.
Remove --single-process flag (security risk: disables Chromium sandbox). Add --disable-remote-fonts, --disable-background-networking, --disable-sync, --disable-translate to minimize attack surface. Applies in both public and local modes.
Add response headers middleware: X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Cache-Control: no-store, Referrer-Policy: no-referrer. Applies in both public and local modes.
Add ValidateSettings method to validate request parameters: decimals range, degrees values, scale factors, string lengths. Called in both convert endpoints. Applies in both public and local modes.
|
Some of these will block features I was hoping the server would have, so let's discuss these one by one. You can add the build step in this PR but let's discuss the security features in more detail before pushing. Another thing is that we should work on another branch for this if you just want to get something quick up for the website. Anything that makes it to the main branch should be more tested. I also need to do more work on the experimental branch before I want it deployed anywhere, so I figured we could add a branch for you to do WIP items on, then I will merge with mine once it is done. Another thing I should have made more clear, Calcpad.Server is going away entirely once Calcpad.Web in the experimental branch is ready, so I wouldn't spend much time fixing it. I did some bad practice and tried to add a lot of features at once (which was fine when I was the only dev, but is causing some issues now that it is public). But I am working on getting the new features stable and that will make it easier to collaborate in the future. |
|
Is my understanding correct that Calpad.Web can replace the server and the editor on the website once it is finished? If so, I won't spent much effort merging this, but keep this just open for tracking the website's current code. |
|
Yes that is correct. It might be good to open an issue for the calcpad-experimental branch so we can discuss how to approach XSS and some of the other security concerns without losing critical functionality. That sounds good for now. |
This adds a GitHub Actions Workflow to build the docker image for Calcpad.Server. This API server helps serving the CalcpadCE website. It seemed the Dockerfile of the server was not up-to-date in recent commits as it didn't build. This fixes it.
I introduced a public mode in which the server has stricter security settings, i.e., don't disclose any stack trace when an exception is thrown, rate limits, input validation, and so on...