Skip to content

Releases: wardcore-dev/onyx-server

beta 0.3

26 Mar 09:41

Choose a tag to compare

v0.3-beta

Security

  • Path traversal in media file handling (media/local.rs)
    User-supplied filenames from URL path were passed directly into PathBuf::join without sanitization, allowing requests like /../../../etc/passwd to escape the storage directory.
    Fixed by rejecting filenames containing /, \, or .., and verifying the canonicalized path stays within the storage root.

  • Unbounded nonce store DoS (auth.rs, handlers/auth_handlers.rs)
    Challenge nonces were stored in an unbounded HashMap with no expiry, allowing an attacker to grow server memory indefinitely by looping /auth/challenge.
    Fixed by attaching a timestamp to each entry (TTL: 60s), pruning expired entries on every insert, and capping the store at 10,000 entries. Expired nonces are now rejected in /auth/verify.

  • Partial token exposure in logs (auth.rs, handlers/auth_handlers.rs)
    The first 16 characters of the auth token were logged on 401 responses and on successful registration, risking credential leakage via log aggregators or shared environments.
    Fixed by removing token content from all log output.

  • Timing side-channel on password hash comparison (handlers/auth_handlers.rs)
    Password hashes were compared with standard string equality, which short-circuits on the first differing byte and enables byte-by-byte recovery of the stored hash via timing differences.
    Fixed by double-hashing both values through SHA-256 before comparison, producing fixed-length digests that eliminate timing signal.

  • Auth token accepted via query string on HTTP routes (auth.rs)
    The auth middleware accepted tokens from ?token= query parameters on all routes, causing tokens to appear in proxy logs, browser history, and Referer headers.
    Fixed by restricting the HTTP auth middleware to Authorization: Bearer headers only. The /data/media/:filename download route retains ?token= support as a deliberate exception — client image/media widgets cannot set custom headers when loading a URL directly.

  • Invite token exposed on unauthenticated endpoint (handlers/info.rs)
    GET /group is a public, unauthenticated route that returned invite_token in its response, allowing anyone with network access to extract the token and bypass invite-only access control.
    Fixed by removing invite_token from the GET /group response entirely. On the authenticated GET /groups route, invite_link is now returned only to users with the owner or moderator role.

  • File type bypass via client-supplied Content-Type (handlers/media.rs)
    File type validation relied on the Content-Type header supplied by the client. An attacker could upload HTML containing JavaScript with a spoofed Content-Type: image/png, achieving stored XSS when the file was later served.
    Fixed by detecting the actual file type from magic bytes, ignoring the client-supplied header entirely. Download responses now include X-Content-Type-Options: nosniff and Content-Disposition: attachment to prevent browsers from rendering served files inline.

Features

  • Rate limiting enforced (rate_limit.rs, handlers/messages.rs, server.rs)
    max_messages_per_minute and max_joins_per_minute were defined in config but never checked anywhere in the codebase.
    Implemented a per-user sliding window rate limiter. Limits are now enforced at the start of the /send, /groups/{id}/send, and /groups/join/{token} handlers.

  • Configurable CORS policy (config.rs, server.rs)
    CorsLayer::permissive() was hardcoded, allowing requests from any origin regardless of deployment context.
    Added security.allowed_origins to config. Resolution order: explicit origins list → server.public_url → permissive fallback (appropriate for LAN and native client deployments).

beta 0.2

15 Mar 10:55

Choose a tag to compare

Changelog:

  • Fixed a bug related to uploading large files.

beta 0.1

14 Mar 11:48

Choose a tag to compare

v0.1-beta

init