We run generated code.
Here's how that's contained.
A product that executes Python written by a language model has an obvious question hanging over it. This page answers it in specifics rather than adjectives, including the parts that are still imperfect.
The sandbox
Generated Python never runs in the web page and never runs in the API process. It is handed to a separate execution service that does one thing: run a strategy and return numbers.
Before a single line executes, the code goes through a static check. If it fails, nothing runs — the request is rejected outright rather than being run with monitoring.
Static allowlist
The code is parsed into an abstract syntax tree and walked. It is rejected unless every import, name and call is on an allowlist. Concretely, that means:
- Imports are limited to the libraries a backtest actually needs —
backtesting,pandas,numpy,mathand a short list beside them.os,sys,subprocess,socket,shutiland their relatives are refused. - Dynamic execution is refused:
eval,exec,compile,__import__,globals,locals. - Attribute escapes are refused — the
__subclasses__/__globals__style of sandbox break-out is blocked at the AST level, not by string matching. - File and network access is refused. A strategy has no reason to open a socket, and one that tries does not run.
Process isolation
Code that passes the check still runs as though it had not been trusted:
- A separate subprocess, so a crash or a hang takes nothing with it.
- A scrubbed environment. The child gets an explicit allowlist of variables — path, home, temp, certificates — and nothing else. Service credentials are never in its environment to be read.
- A hard timeout, after which the whole process tree is killed rather than just the parent.
- Output scrubbing. As a backstop, if anything a strategy printed contains our internal execution secret, the response is discarded instead of returned.
- Bearer authentication between our API and the executor, compared in constant time, and required — the executor fails closed when deployed rather than open.
What we store
The short version: as little as will still make the product work.
| Data | Stored? | Why |
|---|---|---|
| Email address | Yes | It is your account. Handled by our auth provider, not by us directly. |
| Password | Never in readable form | Hashed by the auth provider. We cannot see it and cannot recover it. |
| Saved strategies | Yes, if you save one | So you can re-run them. Row-level security means your rows are readable only by your account. |
| Backtest results | Yes, if signed in | Your history. Same row-level isolation. |
| Payment details | No | There is nothing to pay for yet, so there is no card field anywhere in the product. |
| Voice from the mic button | No | Transcription happens in your browser via its own speech API. No audio reaches us. |
| Third-party analytics | No | No trackers, no advertising pixels, no session recording. |
The privacy policy covers retention and deletion in full.
Transport and headers
- HTTPS everywhere, with HSTS.
- A Content Security Policy on every page, restricting scripts, styles, fonts and connections to an explicit set of origins.
- Framing denied, so the app cannot be embedded and clickjacked.
- Requests are authenticated with a signed session token, verified server-side on every backtest — not merely checked in the browser.
- Rate limiting per account on the execution endpoint.
Known limits
Things a security page usually omits. These are real and we would rather you heard them from us.
- Rate limiting is per-instance and in-memory. It resets on a cold start and is not shared across instances. It is a courtesy limit, not a defence against a determined abuser.
- The demo run limit is client-side. Five free runs are counted in your browser's local storage. Clearing it resets the count. It is a trial boundary, not a security control, and we have not pretended otherwise.
- Same-user process inspection. The executor's subprocess runs as the same OS user as its parent, so on Linux it could in principle read the parent's process environment. We accepted this because that machine holds no other secrets — but it is a real gap rather than a theoretical one.
- No formal audit. Nobody independent has reviewed any of this. It is a young product built by a small team, and claiming otherwise would be the kind of thing this page exists to avoid.
Reporting a problem
If you find something, tell us before you tell anyone else and we will fix it fast. Email security@alphaback.app with enough detail to reproduce it.
We do not run a paid bug bounty — there is no revenue to fund one yet. What we can offer is a same-day acknowledgement, a real fix, and public credit if you want it. Please do not run automated scanners against the live service; they mostly generate noise and cost us the time we would rather spend on your actual finding.
Questions we didn't answer?
Ask directly. Security questions get answered by a person, not a form letter.