Security
Design
Section titled “Design”- No password is asked, sent to or stored by this app. Users type it only in their own mail client.
- No cookies, no analytics, no tracking, no third-party requests.
- The QR code is generated locally in the browser (
public/js/qr.js, MIT, after Nayuki’s implementation). - Only GET and HEAD are accepted.
HTTP headers
Section titled “HTTP headers”Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; manifest-src 'self'; base-uri 'none'; form-action 'self'; frame-ancestors 'none'. A remote logo origin is appended to img-src only when BRAND_LOGO_URL is an absolute URL.
Also sent: Strict-Transport-Security, X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Referrer-Policy: no-referrer, a restrictive Permissions-Policy, Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Resource-Policy: same-origin.
The /support page
Section titled “The /support page”- Disabled (404) while
SUPPORT_PASSWORDis empty. - HTTP Basic auth with constant-time comparison.
- 10 failed attempts from one address lock it for 15 minutes (HTTP 429).
- Responses carry
X-Robots-Tag: noindex, nofollowandCache-Control: no-store. - The client address comes from
CF-Connecting-IPif present, so only expose the app behind a proxy that controls this header.
Apple profile
Section titled “Apple profile”/profile.mobileconfig is not signed, so iOS and macOS display “Not signed” when installing it. It contains no password. Signing it is recommended in production, for example:
openssl smime -sign -signer cert.pem -inkey key.pem -certfile chain.pem \ -nodetach -outform der -in profile.mobileconfig -out signed.mobileconfigThe server does not sign on the fly; sign at a dedicated step or in front of the app, using a certificate trusted by Apple devices.
Deployment hardening
Section titled “Deployment hardening”Run behind an HTTPS reverse proxy (see Reverse proxy and HTTPS). The container is non-root, read-only, with all capabilities dropped and no-new-privileges.
What it does not protect
Section titled “What it does not protect”- It does not check that the servers it describes are reachable or correctly configured.
- The Apple profile is unsigned, see above.
/supportis one shared password over HTTP Basic: serve it over HTTPS only, and treat the password like any admin credential.- There are no published releases or images yet, so there is nothing to verify with a signature. Build from a tag or commit you have read.
Reporting
Section titled “Reporting”Do not open a public issue. Use GitHub private vulnerability reporting: https://github.com/yetysw/mccs/security/advisories/new. See SECURITY.md.