mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
Update the security doc's capability section with the deny list, the fact that `http:allow-fetch` is the only URL-scoped HTTP identifier, and why the https wildcard cannot be removed without moving the link-preview fetch into Rust. Note under Known Limitations that narrowing the plugin scope alone does not bound exfiltration while CSP `connect-src` allows `https:` to any host. Add a capability row to the client architecture doc and mark the design note implemented.
6.7 KiB
6.7 KiB
Security Policy
Security guidelines and vulnerability reporting for OwnCord.
Reporting Vulnerabilities
Use GitHub Security Advisories to report vulnerabilities: go to Settings > Security > Advisories and create a new advisory.
Do NOT open public issues for security bugs.
Response Timeline
- Acknowledgment: Within 48 hours
- Critical fixes: Within 7 days
- Non-critical fixes: Included in the next release
Two-Factor Authentication
OwnCord supports TOTP-based 2FA:
- Users enroll via Settings > Account (QR code + backup codes)
- Admins can enforce server-wide 2FA via the
require_2fasetting in the admin panel require_2farequires all users to have 2FA enabled and registration to be closed- Login flow returns
requires_2fa: truewith apartial_token(10-min TTL, 5-attempt limit) - Auth challenges are rate-limited to 10 req/min per IP
- TOTP code verification uses constant-time comparison (
subtle.ConstantTimeCompare) to prevent timing side-channel attacks
Account Deletion
Users can delete their own account via DELETE /api/v1/auth/account with password confirmation. The last admin account cannot be deleted. After 3 failed password attempts, the endpoint locks out for 15 minutes.
Audit Logging
Security-relevant actions are recorded in the audit_log table with actor, action, target, and detail:
- Auth:
user_register,user_login,user_logout,login_blocked_banned,account_deleted - 2FA:
totp_enabled,totp_verified,totp_disabled - Admin:
role_change,user_ban,user_unban,force_logout,setting_change,server_setup - Content:
channel_create,channel_update,channel_delete,message_delete - Ops:
backup_create,backup_delete,backup_restore,ws_connect
Client Security Hardening
The Tauri desktop client implements the following security measures:
Credential Storage
- Credentials are stored in Windows Credential Manager via DPAPI (per-user scope,
CRED_PERSIST_ENTERPRISE) - Plaintext passwords are never returned to the frontend over IPC — only tokens are accessible from JavaScript
- Auto-login uses stored tokens for reconnection, not passwords
Tauri Capabilities (Least Privilege)
- Filesystem write access is scoped to
$APPDATA/**and$APPLOG/**only - DevTools command is gated behind the
devtoolsfeature flag (excluded from release builds) - HTTP fetch is restricted to
https://origins plushttp://127.0.0.1:*(the Rust TOFU proxy's loopback tunnel), and denieshttps://localhost[:*]andhttps://127.0.0.1[:*]— no legitimate flow reaches loopback over https, so the deny list keeps the renderer from probing other local services http:allow-fetchis the only URL-scoped HTTP identifier.tauri-plugin-httpvalidates the URL exactly once, in thefetchcommand;fetch_sendandfetch_read_bodyoperate on an already-validatedResourceIdand never consult a scope, soallow/denyblocks on those identifiers are inert and were removed rather than left in place advertising a control that does not exist- The
https://*wildcard cannot be removed today: link previews (embeds.ts) fetch arbitrary user-posted URLs by design, and Tauri scopes per command, not per JS caller. Bounded in TypeScript byisPrivateHost/isBlockedForPreview, a 5 s timeout and a 50 KB body cap; the response is regex-scraped forog:tags and never executed - Regression-guarded by
tests/unit/capabilities-scope.test.ts; rationale and the follow-up that would remove the wildcard are in docs/plans/tauri-capability-narrowing.md
TLS and Certificate Pinning (TOFU)
- Self-signed certificates are supported via Trust-On-First-Use (TOFU) pinning
- The WebSocket proxy (
ws_proxy) pins the server certificate fingerprint on first connection - The LiveKit proxy (
livekit_proxy) reuses the pinned fingerprint from the WS proxy - Certificate mismatch triggers a modal requiring user acknowledgment
- Update downloads validate
server_urluseshttps://and rejects URLs with userinfo
Input Validation
- IPC commands validate host format, string lengths, and character allowlists
- PTT virtual key codes are validated to the Win32 range (1–254)
- LiveKit proxy
remote_hostis validated against CRLF injection - API client validates host format before constructing URLs
- File uploads enforce a MIME type allowlist (images, video, audio, PDF, text)
- Error messages from server responses are capped at 200 characters
- Notification titles are sanitized (control chars stripped, length capped)
XSS Prevention
- All user-generated content is rendered via
textContent/setText— neverinnerHTML - The single
innerHTMLusage (SVG icons) operates on compile-time constants with a runtime guard - URLs are validated via
isSafeUrl(rejectsjavascript:,data:,vbscript:) - YouTube embeds use
sandboxattribute on iframes image/svg+xmlis excluded from safe MIME types for data URIs- Tenor GIF URLs are validated against trusted CDN origins
- Linkified URLs strip trailing punctuation to prevent misleading destinations
Search and Rate Limiting
- Client-side search requests are rate-limited (500ms minimum interval + 300ms debounce)
Known Limitations
- Server auto-updates depend on a dedicated pinned minisign/Ed25519 server release key in Server/updater/server_update_public_key.txt and a signed release manifest that binds the shipped binary hash to the release version; Windows Authenticode/SmartScreen code signing is still separate work
- The Tenor API key is hardcoded (Google's public anonymous key) — consider build-time injection for production
- CSP
connect-srcallowshttps:to any host (necessary for self-hosted server URLs not known at build time). Because of this, narrowing the Taurihttp:allow-fetchscope alone would not bound exfiltration from a compromised renderer — the webview's ownfetchreaches the same hosts without going through the plugin. Closing that requires narrowingconnect-srcand moving the link-preview fetch into Rust in the same change
Security Hardening Checklist for Operators
- Enable TLS (self-signed is the default; custom certs recommended for production)
- Keep invite-only registration enabled (default)
- Set a strong admin password
- Configure rate limits (defaults are sensible but review for your use case)
- Run regular backups via the admin panel
- Keep the server updated (admin panel shows available updates)
- Firewall: only expose port 8443 (HTTPS) and 7880 (LiveKit WebSocket for voice/video)
- Enable server-wide 2FA requirement once all users have enrolled
- Set
admin_allowed_cidrsto restrict admin panel access to trusted networks