| title | Security |
|---|---|
| description | What an ibkr-httpapi deployment can reach, what it stores, how the bearer token works, and what to set before it leaves localhost. |
| nav_order | 10 |
Anyone who can send requests to this API can trade the brokerage account the gateway is logged into. Treat the API token like the account password.
- Read balances, positions, orders and executions for every account on the IBKR login.
- Place, cancel and exercise for real through
POST /v1/orders,POST /v1/options/combo,POST /v1/options/exercise,DELETE /v1/orders/{orderId}andDELETE /v1/orders. The last one cancels every open order on the account, including orders placed in other tools. - Do all of the above through MCP at
/mcpwith the same token.
The only built-in brake is IBKR's own: READ_ONLY_API=yes in .env.ibkr makes the gateway refuse orders. A paper login (TRADING_MODE=paper) keeps real money out of reach.
- One shared bearer token,
api_tokeninconfig.yamlorAPI_TOKENin the environment. The middleware inibkrapi/server.pychecks it on every path:/v1/*,/mcp,/docsand/openapi.json. It compares withhmac.compare_digest. - An empty token turns auth off for everything, with one warning line from
run.shat startup. - There are no users, scopes or read-only tokens. Whoever has the token has full access.
- Generate a long random token and keep
config/config.yamlout of Git (it is gitignored):
openssl rand -hex 32- nginx publishes the API on
127.0.0.1:8889by default (API_HOST_BIND,API_HOST_PORT). nginx itself speaks plain HTTP; there is no TLS in the stack. - The
apicontainer has no published port. The gateway's TWS socket is only on the internalbackendnetwork. VNC (5900) and port8001are published on127.0.0.1only. - wickworks sits on an
internal: truenetwork with no route out. - The MCP endpoint does not check the
Hostheader (the SDK's DNS rebinding protection is turned off), so a browser page could reach a loopback API without a token if you run it without one. Always set a token, even on localhost.
Before you bind to anything but loopback:
- Set a strong
api_token. - Put TLS in front: the commented
cloudflaredservice tunnels tohttp://nginx:80without a host port, and thetailscaleservice puts it on a tailnet. Add an access layer of your own (Cloudflare Access, tailnet ACLs) in front of the token. - Test the whole chain against a paper account from another network before you switch to live.
- Rotate the token after testing.
| Data | Location | Notes |
|---|---|---|
| IBKR username and password | .env.ibkr, passed only to the ibgateway container |
Gitignored. The API process never sees them. |
| API token | config/config.yaml, and .env (written by run.sh) |
Both gitignored. The startup log records only whether a token is set and its length. |
| Gateway settings | .data/ibgateway/ |
|
| Request logs | logs/full.log and container stdout |
Method, path, status, duration, client IP and user agent. No bodies, no tokens. |
| Market data and trading history | data/history/ |
Executions and completed orders include account numbers, prices and quantities. Protect backups accordingly. |
api, nginx and wickworks run read-only with all capabilities dropped and no-new-privileges; the api image runs as a non-root user with hash-checked dependencies. The gateway container cannot be locked down the same way. Details on the deployment page.
Python dependencies are hash-locked and pass a 7-day age gate before they can enter the lock, base images are pinned by digest, and make audit, make audit-go and make audit-compose scan the Python deps, the Go client and the compose files. See Development.