Security

Security.

The controls in place today, where each one lives, and how to report a problem.

Last reviewed 2 Nov 2026

This page lists only the controls that are in place today. Each one names the code or server file that does it. When a control ships, it is added here; nothing is listed ahead of time.

Report a problem

Write to hello@zten.in. Our security.txt says the same. Please give us a reasonable time to fix an issue before you make it public.

Orders and your Zerodha account

ControlWhere it lives
MyZTEN can make only six Kite calls: four reads (profile, funds, positions, orders) plus the daily session exchange and logout. Any other call, such as an order, is refused before it leaves the server.MyZTEN backend/app/kite.py
Tests fail if order code appears anywhere in the MyZTEN backend, or if any file other than kite.py calls Kite.MyZTEN backend/tests/test_kite.py
Your Kite secret and each day's access token are stored encrypted (Fernet), never returned to the browser and never logged. The API key is only ever shown masked.MyZTEN backend/app/kite.py, backend/app/db.py
Your Zerodha password and 2FA are typed on Zerodha's page. MyZTEN gets only that day's access token, which Zerodha expires at 6:00 am.MyZTEN backend/app/kite.py
The Zerodha login callback is tied to your account by a signed code that lasts 15 minutes.MyZTEN backend/app/security.py
Disconnect logs the token out at Zerodha and deletes the key, secret and token.MyZTEN backend/app/kite.py

Accounts

ControlWhere it lives
Passwords are stored as bcrypt hashes (over a SHA-256 pre-hash), never in plain text.MyZTEN backend/app/security.py, ZTEN core/shadow/auth.py
Sign-in, sign-up and one-time-code entry allow 5 tries in 15 minutes, then refuse.MyZTEN backend/app/routers/auth.py, ZTEN core/shadow/guard.py
The MyZTEN session is a signed token in a cookie that scripts cannot read (HttpOnly), sent only over HTTPS (Secure) and only to my.zten.in (SameSite=Strict). It lasts 1 day.MyZTEN backend/app/routers/auth.py, backend/app/security.py
Sign-up and reset codes expire after 10 minutes.MyZTEN backend/app/security.py, ZTEN main.py
ZSIM Lab's guest limit keeps a salted hash of the IP address, never the address.MyZTEN backend/app/db.py

Market data

ControlWhere it lives
Today's paper fill and exit prices are held back by the server until the 15:30 close, not only hidden on screen.MyZTEN backend/app/dics/engine.py
ZTEN Shadow does not send option leg prices to the browser.ZTEN core/shadow/ic_data.py

Web servers

ControlWhere it lives
Every site is served over HTTPS only, with HSTS.nginx site files
Every site sends X-Frame-Options DENY, X-Content-Type-Options nosniff, a strict Referrer-Policy and a Permissions-Policy that turns off camera, microphone, location, payment and USB. A Content Security Policy runs in report-only mode while we check it breaks nothing.nginx snippets/zten-security-headers.conf
The server does not reveal its software version.nginx nginx.conf (server_tokens off)

Server files live on our server, and our code repositories are private. The rules a strategy follows are public in the MyZTEN config panel.