Oikoumene is a research simulation, not a multi-tenant production service. This document records the threat model the code is hardened against, the threats that are explicitly out of scope, and how to report a security issue responsibly.
The default deployment target is a single researcher running the simulator
on their own workstation and reaching it via http://localhost:5000. All
security defaults are tuned for that scenario.
| Threat | Mitigation |
|---|---|
Path traversal via crafted run_id in /api/logger/download/<run_id> |
run_id is regex-validated to the YYYYMMDD_HHMMSS format produced by sim_logger.py; the resolved path is verified to stay under the repository's logs/ directory (app.py). |
| Predictable Flask session-signing key | If FLASK_SECRET_KEY is unset, a per-process random key is generated (secrets.token_hex(32)) and a warning is printed (app.py). |
| Cross-origin requests driving the SocketIO API | cors_allowed_origins defaults to http://localhost:5000 and http://127.0.0.1:5000. Override via CORS_ALLOWED_ORIGINS (comma-separated) only when fronted by an authenticated reverse proxy. |
| LAN exposure of the unauthenticated control surface | The server binds to 127.0.0.1 by default. BIND_HOST=0.0.0.0 is only honoured when explicitly set, and a warning is printed in that case. |
Leakage of LLM api_key to clients |
LLMModule.get_status() returns provider / model / base_url but never the key. world.get_full_state() (sent over SocketIO and dumped to snapshots) inherits this whitelist. |
| Threat | Why it's out of scope |
|---|---|
| Multi-user authentication / authorization | The simulator has no user concept. Every endpoint is unauthenticated by design. If you need multi-user access, place the app behind an authenticated reverse proxy (Caddy + basic_auth, oauth2-proxy, Cloudflare Access, etc.). |
| Rate limiting on HTTP routes | A local single user cannot meaningfully DoS themselves. Apply rate limiting at the reverse proxy layer if the simulator is exposed. |
| CSRF on SocketIO events | Mitigated implicitly by the localhost CORS default. If you broaden CORS, consider adding a CSRF token check on socket events. |
| Sandboxing of the LLM provider URL | The user controls base_url; the simulator will dutifully call whatever URL is configured. This is intentional for self-hosted Ollama or air-gapped Mistral deployments. Do not point this at untrusted hosts. |
Hardening of god_mode interventions |
God mode lets the operator drop drought, plague, technology, and direct messages into the simulation. It is a debugging / experimentation feature, not a privilege boundary. Anyone who can reach the SocketIO endpoint can use it. |
- Set
FLASK_SECRET_KEYto a stable random string (python -c "import secrets; print(secrets.token_hex(32))"). - Set
CORS_ALLOWED_ORIGINSto your real frontend origin only. - Set
BIND_HOSTonly after putting the app behind an authenticated reverse proxy. - Treat
logs/and anymetadata.jsonas potentially-disclosable artifacts (they contain seeds and scenario configs, but not API keys). - Verify your
requirements.txtinstall resolves to the latest patch versions offlask,flask-socketio, andeventlet— these are the network-facing dependencies.
Please do not open a public GitHub issue for security problems.
Preferred channel — GitHub private vulnerability reporting. Submit your report at github.com/GeoLambdaAI/oikoumene/security/advisories/new. This gives you an authenticated, end-to-end private thread with the maintainers, and the resulting advisory becomes citable once we publish the fix.
Cannot use GitHub? Reach us through the contact form at
www.geolambda.ai and reference Oikoumene
plus the word security in your message.
In either channel, please include:
- A clear description of the issue and the threat scenario.
- Reproduction steps (or a proof-of-concept).
- Affected version (Git commit hash if available).
- Whether you are willing to be credited in
CHANGELOG.mdonce the issue is fixed.
You should expect an acknowledgement within 5 working days and a triage update within 15 working days. We aim to ship a fix and coordinated disclosure within 90 days for high-severity issues.
The simulator's network-facing surface comes from four packages:
flaskandflask-socketio— HTTP and WebSocket transport.eventlet— green-thread runtime under SocketIO. Has had several past CVEs; the lower boundeventlet>=0.35.0requires fixes from the 2024-09 release. Production deployments should pin to the latest patch.requests— outbound HTTP to LLM providers and data-source APIs. TLS verification uses the library default (verify=True).
numpy, scipy, networkx, shapely are computational dependencies
with no network surface.
This security policy was drafted as part of the v0.1.0 hardening pass.
See CHANGELOG.md for the corresponding entries.