Skip to content

Fable5: Security hardening — default admin password, open CORS, plaintext secrets #22

Description

@etiennechabert

Problem

Several security-relevant defaults found during the review. None are fixed yet — they need product decisions.

1. Default admin password is "admin" (config.py)

ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", "admin") — anyone who can reach the Flask port can authenticate as admin (start/stop listening, spawn the Meet bot toward any URL, read the viewer password) unless the env var is set.

Suggested fix: refuse to start (or generate a random password and print it, like the viewer passphrase) when ADMIN_PASSWORD is unset.

2. cors_allowed_origins="*" on SocketIO (app.py)

Combined with the server binding 0.0.0.0, any website a LAN user visits can open a WebSocket to the app and attempt admin/viewer auth.

Suggested fix: restrict to the expected origin(s), or make it configurable with a safe default.

3. Viewer passphrase stored in plaintext (viewer_password.txt)

Low severity (it's a meeting-viewing passphrase, by design shared with viewers), but worth noting it persists across runs in the working directory.

4. Password comparisons are not constant-time

password == Config.ADMIN_PASSWORD etc. — use hmac.compare_digest(). Minor in practice, trivial to fix.

5. /api/viewer/password authenticates via raw Authorization header equality

The admin password is sent as a bare header value (no scheme), compared with ==. Works, but combine with 4 and consider a session check instead.

Status

Open — not addressed in PR #16/#17 (out of scope for the bug-fix pass).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions