The Attack Surface of a Retail Trading Firm
When you build an automated trading firm β even a small one β you create an attack surface that most people don't think about. You're running:
- Brokerage API keys with trading permissions (IBKR, Alpaca, Binance)
- Claude/OpenAI API keys with spending authority tied to your credit card
- Telegram bot tokens that can trigger real trades via command
- Public-facing web properties revealing your strategies, positions, and infrastructure
- A machine running 24/7 connected to the internet and your home network
Any single one of these, compromised, can result in financial loss β and the attacker doesn't need to be sophisticated. Credential stuffing, phishing, open ports, and misconfigured cloud services are the vectors that actually cause breaches, not Hollywood hacking.
The Threat Landscape
| Attack Vector | Likelihood | Impact | Where It Hits |
|---|---|---|---|
| API key in public repo | Very High | Catastrophic | GitHub, Gist, Pastebin |
| Hardcoded creds in scripts | High | Catastrophic | Any shared machine |
| Open brokerage API (no IP whitelist) | Medium | Account wipe | Stolen key scenario |
| Unprotected dashboard | Medium | Strategy exposure | *.workers.dev URLs |
| Local network attacker | Medium | Full machine access | Same WiFi network |
| Phishing / credential theft | Medium | Account takeover | Email, Telegram |
| Unsecured SSH port | Medium | Full remote access | Remote machine |
The Mindset Shift
Security is not a feature you add at the end. It's a property of every decision you make while building. The good news: 90% of retail trader breaches are preventable with a small set of non-negotiable practices β all covered in this course. None of them require enterprise tools or a security team.
The Old Model vs. Zero Trust
The traditional security model assumes everything inside your network is safe. Zero Trust flips this: trust is never implicit, always earned, and always time-limited. Every request must authenticate, every session must be authorized, and every access must be logged.
| Dimension | Traditional | Zero Trust |
|---|---|---|
| Default assumption | Inside = trusted | Nothing is trusted |
| Identity | Network location | Verified per-request |
| Access scope | Broad (once in, broad access) | Least-privilege only |
| Breach impact | Lateral movement is easy | Blast radius is contained |
| Monitoring | Perimeter only | Every request logged |
Cloudflare Zero Trust β What It Is and Its Limits
Cloudflare Zero Trust (Access) is a free service that places an identity gate in front of any application on a domain you control. Anyone trying to visit your dashboard is required to authenticate via email OTP, Google, or GitHub SSO before seeing any content.
Critical limitation: Cloudflare Zero Trust only protects domains in your Cloudflare account DNS zone. The *.workers.dev subdomain is a Cloudflare-managed domain β it is NOT in your DNS zone and CANNOT be protected by Zero Trust Access. This is why the client-side password gate exists for the DeadCatFound courses.
Setting Up Zero Trust on Your Dashboard
Your firm dashboard (firm-dashboard.christopherpwhite31087.workers.dev) is currently accessible to anyone who knows the URL. If it's deployed under a custom domain, here's how to protect it:
- Go to Cloudflare Dashboard β Zero Trust β Access β Applications
- Click Add an Application β Self-hosted
- Enter your domain (e.g., dashboard.yourdomain.com)
- Create a policy: Email β Allow β your email address
- Choose login method: One-time PIN (email) β simplest, no OAuth setup needed
- Save and test in an incognito window β you should see a login prompt
Zero Trust Principles for the Firm
- Every external service requires authentication β no anonymous access to dashboards, no open APIs
- Least privilege on every API key β read-only when possible, trading permissions only when required
- Short-lived sessions β set Zero Trust session duration to 8 hours, not "never expire"
- Device posture checks (advanced) β require that the accessing device has disk encryption enabled
- Log everything β Cloudflare Zero Trust logs every access attempt; review weekly
The Cardinal Rules
2. Never commit a key to git. Even if the repo is private β employees get fired, accounts get compromised, repos get made public by accident.
3. Never share a key over Telegram, Slack, email, or Discord. Those channels are not encrypted end-to-end for this purpose.
4. Use the minimum permissions a key needs. A data-pull script doesn't need trading permissions.
How to Store API Keys Properly
| Method | Security | Convenience | Recommendation |
|---|---|---|---|
| Hardcoded in script | None | High | Never |
| Environment variable (shell) | Low | High | Dev only |
| JSON config file (chmod 600) | Medium | High | Acceptable for local scripts |
| macOS Keychain / secret store | High | Medium | Recommended |
| 1Password CLI (op run) | Very High | Medium | Recommended |
| Cloudflare Workers Secrets | Very High | Medium | For production Workers |
File Permissions β The Immediate Fix
If you're using JSON config files to store keys (like config/alpaca.json or config/ibkr.json), they should be readable only by your user account. This prevents other processes and users on the machine from reading them:
IP Whitelisting on Brokerage APIs
Most brokerages allow you to restrict API key usage to specific IP addresses. This is one of the highest-value, lowest-effort security controls available. Even if a key leaks, it cannot be used from any IP other than your home or server.
- IBKR: TWS API connections are bound to localhost by default β this is actually secure. For IB Gateway, keep the trusted IP list to your machine only.
- Alpaca: Go to Paper Trading API Keys β IP Restriction β add your static IP or home IP range.
- Binance: API Management β Edit β Restrict access to trusted IPs only. This is critical for crypto β do this now.
- Claude/OpenAI: These don't support IP whitelisting, so key rotation and spending limits are your controls instead. Set monthly spend limits in the API settings.
Key Rotation
Rotate every API key on a schedule β even if you don't think it's been compromised. Rotation limits the window of exposure if a key was silently stolen. Recommended cadence:
- Brokerage keys: every 90 days
- AI API keys: every 60 days, or any time you share access with a script/agent
- Telegram bot tokens: after any suspected compromise β invalidate immediately
What Your Dashboard Reveals
An unprotected trading dashboard exposes:
- Open positions β exactly what you're holding, at what size
- Entry prices β revealing your cost basis and likely stop levels
- Strategy logic β patterns in your trades reveal which signals you're using
- Infrastructure topology β Cloudflare Worker names, script paths, update cadence
- Account size β position sizing reveals approximate capital
Cloudflare-Specific Hardening
- Workers environment variables β use
wrangler secret put SECRET_NAMEto inject secrets as environment variables, never hardcode them in worker code - Disable directory listing β Cloudflare Workers with static assets do not expose directory listings, but ensure your
wrangler.jsoncis not committing credential files - Custom error pages β don't expose stack traces or internal paths in error messages visible to users
- Rate limiting β Cloudflare's WAF rules can block brute-force attempts on password-protected pages
- Audit log access β Cloudflare Zero Trust logs every successful and failed access attempt; review the logs weekly
Secrets in Cloudflare Workers
Security Headers
If you build a Worker that serves HTML, add these security headers to prevent clickjacking, XSS, and content injection:
The Public vs. Private Split
Decide intentionally what is public-facing and what is private. A reasonable split for a retail trading firm:
- Public: Educational courses (DeadCatFound), newsletter, about page
- Private (gated): Live positions dashboard, strategy details, trade history with sizing, agent logs
- Local only: API keys, brokerage configs, launchd plist details, Paperclip admin panel
The Local Network Attack Surface
When your trading machine is connected to any network β home WiFi, office ethernet, or a hotspot β other devices on that network can potentially reach your machine. The key question is: what are you listening on?
Same network segment
Unencrypted HTTP, DNS queries
HTTPS everywhere, VPN, static ARP
If your dashboard or scripts call any API over plain HTTP on the local network, an ARP-spoofing attacker can read or modify those responses. Always use HTTPS β never HTTP β even on local networks.
nmap, masscan, zmap
Paperclip (:3100), SSH (:22), Postgres (:5432)
macOS firewall, bind to localhost
Every service you run that listens on 0.0.0.0 (all interfaces) is visible to your entire network. Bind services to 127.0.0.1 (localhost only) unless they explicitly need to be network-accessible.
Any network device (smart TV, phone, printer)
Your trading machine with keys and scripts
Network segmentation, firewall, strong auth
A compromised IoT device β your smart thermostat, TV, or a guest's laptop β can be used as a jump host to scan and attack your trading machine. Network segmentation (putting IoT devices on a separate VLAN or guest network) eliminates this pivot path.
Coffee shops, airports, co-working
Login credentials, API calls, session tokens
VPN always on public WiFi
Never run trading scripts or access brokerage dashboards on public WiFi without a VPN. A VPN encrypts all traffic before it leaves your machine, making WiFi-level interception useless.
The Home Network Fix
- Put IoT devices (smart speakers, TVs, printers) on a separate guest WiFi β isolated from your trading machine
- Use WPA3 on your main WiFi if your router supports it
- Change your router admin password from the default
- Disable UPnP on your router β this allows devices to open ports to the internet without your knowledge
- Enable your router's firewall β most consumer routers have this off by default
macOS Firewall β Enable It Now
macOS ships with a built-in application-layer firewall that blocks incoming connections. It's off by default. Turn it on:
Bind Services to Localhost
Every service you run that only needs to be accessed from your own machine β Paperclip, Postgres, Ollama, llama.cpp server β should bind to 127.0.0.1 (localhost) instead of 0.0.0.0 (all interfaces). This makes them invisible to your network.
- Paperclip runs on
localhost:3100by default β good, don't change it - Postgres (Paperclip's embedded DB) binds to localhost β do not change the pg_hba.conf
- Ollama binds to
127.0.0.1:11434by default β do not expose this - IBKR TWS/Gateway API binds to localhost β only loosen this if you know exactly why
FileVault β Full Disk Encryption
If your machine is stolen or physically accessed, disk encryption is your last line of defense. macOS FileVault encrypts your entire disk. With a strong login password, a stolen machine reveals nothing.
SSH Hardening
If you use SSH to access your machine remotely, harden it:
- Disable password authentication β use SSH keys only
- Disable root login β
PermitRootLogin noin/etc/ssh/sshd_config - Change the default port (optional) β reduces automated scan noise
- Use AllowUsers to restrict which users can SSH in
- Consider Cloudflare Tunnel instead of exposing SSH to the internet at all
Software Hygiene
- Keep macOS updated β security patches, not just features
- Review installed npm/pip packages β supply chain attacks via package dependencies are real
- Don't run as root for any trading scripts β use your normal user account
- Lock your screen when away β set a 5-minute screen lock timeout
- Enable Find My Mac β remote wipe capability if the machine is stolen
1Password CLI β The Right Tool
1Password CLI (op) allows you to inject secrets from your 1Password vault into any script or environment at runtime β without ever writing them to disk in plaintext. Your scripts reference secrets by name; the actual values live only in the encrypted vault.
macOS Keychain
For simpler setups, macOS Keychain is a built-in secure secret store available to any script on your machine:
.gitignore β The Essential File
Every project that handles credentials needs a comprehensive .gitignore. Here's the minimum for a trading firm:
YubiKey β Hardware Authentication
A YubiKey is a physical hardware security key that acts as a second factor for logins. Even if an attacker has your password, they cannot log in without the physical key in your hand. Recommended for:
- Your brokerage account logins (IBKR, Alpaca, Binance)
- Your Cloudflare account (protects your Zero Trust config)
- Your GitHub account (protects your code repos)
- Your Google/Apple account (protects everything tied to it)
The YubiKey 5C NFC (~$55) supports USB-C and NFC and works with every major platform. It's the single highest-ROI security investment available to a retail trader.
2. chmod 600 all credential files β takes 30 seconds
3. IP whitelist your brokerage API keys β takes 5 minutes
4. Enable FileVault disk encryption β takes 1 minute
5. Enable macOS Firewall β takes 1 minute
6. Add YubiKey to brokerage accounts β takes 15 minutes
7. 1Password CLI for secret injection β takes 30 minutes to set up
The First 15 Minutes
If you suspect a breach β unauthorized trades, API calls you didn't make, unexpected charges, or a Telegram command you didn't send β the clock starts immediately. Here's the decision tree:
| Scenario | Immediate Action | Then |
|---|---|---|
| Unauthorized trades on brokerage | Cancel all open orders immediately | Revoke API key, call broker, document |
| Unexpected Claude/OpenAI charges | Revoke API key in dashboard NOW | Contact provider, request refund, rotate key |
| Telegram bot acting on commands you didn't send | Stop Telegram listener immediately | Revoke bot token, audit who has the token |
| Suspected malware on trading machine | Disconnect from network | Don't reboot β preserve evidence; restore from backup |
| GitHub repo with secrets was public | Rotate every key that was in the repo | Audit git log, remove from history with BFG |
Kill Switches β Build Them Before You Need Them
Your firm needs documented kill switches that can be executed in under 60 seconds. Write these down and test them:
Backing Up Before You Need It
Time Machine or equivalent backup of your trading machine protects against:
- Malware that encrypts your files (ransomware)
- Accidental deletion of strategies or configs
- Machine failure during market hours
Specifically back up: ~/christs-first-firm/config/, ~/christs-first-firm/strategies/, ~/christs-first-firm/memory/, and ~/Library/LaunchAgents/com.chris.*.plist. Your code should be in git β that's already a backup.
Post-Incident: What to Document
After containing a breach, write a brief incident report before you forget the details:
- Timeline: when did you first notice, what were the first signs?
- Scope: what was affected β keys, accounts, machines, data?
- Root cause: how did the attacker get in?
- Actions taken: what did you do and in what order?
- Gaps identified: what control would have prevented this?
The Ongoing Security Posture
- Weekly: review Cloudflare access logs, brokerage login history, API call volume for anomalies
- Monthly: rotate AI API keys, audit .gitignore, check for exposed ports with
sudo lsof -i -P | grep LISTEN - Quarterly: rotate brokerage API keys, review IP whitelist rules, update macOS and dependencies
- Annually: full security audit β every credential, every service, every exposed port
Your Firm Is Now Hardened.
Zero Trust, API key security, network threat awareness, machine hardening, credential management, and incident response β you have the complete operational security posture. The gap between you and an unprotected trader is now enormous.
Continue building on DeadCatFound β every track stacks together into a complete, professional trading operation.
Back to DeadCatFound βDeadCatFound is an educational platform only. Security advice in this course is general guidance, not professional security consulting. Threat landscapes change rapidly β always consult current resources and a qualified security professional for production environments handling significant capital.
All content is for educational and informational purposes only. By accessing this course you acknowledge that DeadCatFound bears no liability for any security outcomes.