Version: 3.3.0 Applies to: AARK Kernel 3.x
Only the latest minor series receives security fixes.
| Version | Supported |
|---|---|
| 3.3.x | ✅ Active |
| 3.2.x | |
| 3.1.x and earlier | ❌ End of life |
Please do not report security issues in public issues or discussions. A public report exposes every deployment before a fix exists.
Report privately through one of these channels:
| Channel | Address |
|---|---|
| GitHub Security Advisories — preferred | New advisory |
security@ansariai.ir |
Use GitHub Security Advisories when you can. It is private by default, keeps
a tracked record of the report, and needs no mail setup on our side. The email
address becomes active once the ansariai.ir domain is connected to a mail
provider; until then an advisory is the reliable route.
Telegram, issues, discussions and pull requests are not accepted channels for security reports — they are public or unmoderated spaces, and a public report exposes every deployment before a fix exists.
- What the vulnerability is, and why it is dangerous
- How to reproduce it — exact steps, or a script
- Which version you tested against
- Impact — what an attacker gains
- Suggested fix, if you have one
| Time | Commitment |
|---|---|
| 24 hours | Acknowledgement that we received it |
| 72 hours | Initial assessment and severity rating |
| 7 days | A patch or a documented mitigation |
| 14 days | A release containing the fix |
If we cannot meet a deadline, we will tell you why and give a new date. You will be credited in the release notes and the Hall of Fame unless you prefer to stay anonymous.
- The FastAPI backend (
backend/app/) - The Next.js frontend (
frontend/src/) - Authentication, authorisation, and the key vault
- The Docker images and
docker-compose.yml - The install and update scripts
- Third-party dependencies (report those upstream, and tell us so we can track them)
- Issues requiring an already-compromised host
- Social engineering of maintainers or users
- Denial of service against a self-hosted instance you control
| Control | Detail |
|---|---|
| Password hashing | bcrypt, cost factor 12, $2b$ prefix, used directly without passlib |
| Token | JWT HS256, claims sub / iat / exp / role, 30-minute lifetime |
| Secret strength | API_SECRET_KEY is validated with min_length=32; there is no default value |
| Admin bootstrap | ADMIN_PASSWORD shorter than 12 characters is rejected |
| Secret storage | all secrets come from .env, which is in .gitignore |
| Control | Detail |
|---|---|
| RBAC | Admin / Trader / Viewer, enforced through FastAPI dependencies |
| User management | POST /auth/register and /auth/users/* require ADMIN |
| Audit trail | successful and failed logins, plus every user mutation, are recorded |
Exchange API keys never touch the database. They are written to a dedicated
directory with mode 0700, inside a file with mode 0600, using an atomic
write so a crash cannot leave a truncated key. The location is configurable via
AARK_VAULT_DIR and is backed by a persistent vaultdata volume in Compose.
| Control | Detail |
|---|---|
| Non-root | appuser (uid 1001) and nextjs (uid 1001) |
| Multi-stage builds | build tooling is not present in the runtime image |
| Health checks | curl on the backend, node fetch on the frontend |
| Network exposure | backend publishes on 127.0.0.1 by default |
./backup.sh produces AES-256-CBC encrypted archives containing .env, a
PostgreSQL dump, the Redis append-only file, and the key vault. The key is read
from BACKUP_ENCRYPTION_KEY. Store that key separately from the backups —
an encrypted backup next to its key is not encrypted.
These are disclosed deliberately. A hidden gap is worse than a tracked one.
| Item | Severity | Status |
|---|---|---|
Seven business routes are unauthenticated: POST /api/v1/agent/evaluate, /api/v1/agents/*, POST /api/v1/nobitex/save-key, DELETE /api/v1/nobitex/key, GET /api/v1/nobitex/status, POST /api/v1/integrations/accounting/sync |
High | ROADMAP.md phase 1 |
No rate limiting on /auth/login |
Medium | Phase 1 |
| No two-factor authentication | Medium | Phase 3 |
| WebSocket token passed as a query parameter | Low | Phase 3 — header-based upgrade is not possible in the browser API |
Until phase 1 closes, do one of the following:
- Keep the backend bound to
127.0.0.1(the Compose default), or - Place an authenticating reverse proxy in front of it, or
- Run it on an isolated network with no external route.
- Replace every placeholder secret in
.env -
chmod 600 .env - Confirm
.envis not tracked:git status --porcelainshows nothing - Set
BACKEND_CORS_ORIGINSto the exact origins you serve - Set
DEBUG=falseso Swagger UI stays disabled - Publish the backend on
127.0.0.1, never0.0.0.0, without a proxy - Put TLS in front of everything
- Store
BACKUP_ENCRYPTION_KEYaway from the backup archives - Mount
AARK_VAULT_DIRon a persistent, encrypted volume - Rotate
API_SECRET_KEYon a schedule — note that this invalidates live tokens - Subscribe to repository security advisories
We thank the following people for responsible disclosure. Add yourself by reporting privately.
| Researcher | Finding | Date |
|---|---|---|
| — | — | — |