T09 · Insecure Skill Coding Practices
- Location
scripts/trading_bot.py:20- Finding
TLS certificate validation is disabled for a configurable brokerage API endpoint
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is for real brokerage automation and is broadly coherent, but it uses unsafe defaults around live trading, credentials, and gateway trust.
Install only in a dedicated, trusted environment, preferably with a paper IBKR account first. Do not use this for live trading unless you add explicit human approval for all order confirmations, enforce account/symbol/quantity/notional limits, secure or replace the plaintext .env credential flow, restrict the gateway to a verified local endpoint, and pin or verify all downloaded dependencies.
scripts/trading_bot.py:20TLS certificate validation is disabled for a configurable brokerage API endpoint
scripts/setup.sh:66Plaintext brokerage credential file is created without enforced restrictive permissions
scripts/setup.sh:43Unpinned Python dependencies and an unchecked gateway archive are installed
scripts/trading_bot.py:125Trading bot automatically accepts all order confirmation requests
The service base URL is taken from an environment variable and used for authenticated status checks with TLS verification disabled. If an attacker can influence the environment or network path, the script may send session-related traffic to a rogue endpoint or accept spoofed responses, which is especially dangerous in an IBKR trading automation context handling brokerage sessions.
def check_auth_status():
"""Check if session is authenticated."""
try:
r = requests.get(
f"{BASE_URL}/v1/api/iserver/auth/status",
verify=False,
timeout=10
The keepalive POST uses an environment-controlled URL with certificate verification disabled, so a manipulated environment or intercepted connection could redirect keepalive traffic to an attacker-controlled service. In a brokerage automation skill, this can expose session metadata, enable false session-state signaling, or facilitate broader man-in-the-middle abuse against trading infrastructure.
def tickle():
"""Send keepalive ping."""
try:
r = requests.post(
f"{BASE_URL}/v1/api/tickle",
verify=False,
timeout=10
Sourcing a .env file directly into the shell imports credentials into the current environment and encourages plaintext secret storage for IBKR account access. In a trading skill, those credentials can enable account session takeover or unauthorized actions if the file is exposed through logs, history, process environments, backups, or broader agent env access.
# 3. Run IBeam authentication
cd ~/trading
source venv/bin/activate
source .env
export DISPLAY=:99
Xvfb :99 -screen 0 1024x768x24 &
python -m ibeam --authenticate
The cancel-order endpoint accepts accountId and orderId directly and is documented without guardrails around authorization scope, confirmation, or validation. In an agentic context, uncontrolled parameter selection could let a prompt or upstream input cause cancellation of unintended orders, creating trading disruption or financial harm.
DELETE /v1/api/iserver/account/{accountId}/order/{orderId}
The code path is explicitly about creating a credential-bearing .env file for IBKR authentication. In the context of brokerage automation, collecting and later sourcing such credentials increases the risk of local secret disclosure and account compromise if the file is readable by other users or mishandled.
echo "✅ Python venv already exists"
fi
# Create .env template if not exists
if [ ! -f ".env" ]; then
echo ""
echo "📝 Creating .env template..."
Writing directly to .env establishes a plaintext secret store in the working directory. Because this skill targets financial account automation, compromise of that file can have direct monetary consequences and should be treated as high risk.
fi
# Create .env template if not exists
if [ ! -f ".env" ]; then
echo ""
echo "📝 Creating .env template..."
cat > .env << 'EOF'
The template explicitly labels IBKR credentials and prompts the user to insert a username and password into the file. Encouraging persistent plaintext storage of brokerage credentials is dangerous because it simplifies theft by local malware, other users, or accidental disclosure.
# Create .env template if not exists
if [ ! -f ".env" ]; then
echo ""
echo "📝 Creating .env template..."
cat > .env << 'EOF'
# IBKR Credentials - EDIT THESE
IBEAM_ACCOUNT=your_username
This line specifically includes a password field in .env, confirming storage of a reusable secret in plaintext. In a trading environment, theft of the password could enable account login or facilitate automated session establishment alongside 2FA workflows.
if [ ! -f ".env" ]; then
echo ""
echo "📝 Creating .env template..."
cat > .env << 'EOF'
# IBKR Credentials - EDIT THESE
IBEAM_ACCOUNT=your_username
IBEAM_PASSWORD='your_password'
Although this line only performs placeholder substitution in .env, it operates on the same credential-containing file without adding any protections. It reinforces reliance on an insecure secret file but is not independently as severe as the password template itself.
IBEAM_OAUTH_TIMEOUT=180
IBEAM_PAGE_LOAD_TIMEOUT=60
EOF
sed -i "s|\${TRADING_DIR}|$TRADING_DIR|g" .env
echo "✅ Created .env template - EDIT WITH YOUR CREDENTIALS"
else
echo "✅ .env already exists"
The completion message tells the user to edit .env with credentials but provides no warning about securing the file. In context, this promotes unsafe operational handling of sensitive brokerage secrets and increases the likelihood of accidental exposure.
IBEAM_PAGE_LOAD_TIMEOUT=60
EOF
sed -i "s|\${TRADING_DIR}|$TRADING_DIR|g" .env
echo "✅ Created .env template - EDIT WITH YOUR CREDENTIALS"
else
echo "✅ .env already exists"
fi
This line acknowledges continued use of an existing .env, which may already contain sensitive credentials, but does not verify permissions or security posture. In isolation it is not credential theft, yet it contributes to insecure secret lifecycle management in a high-value financial context.
sed -i "s|\${TRADING_DIR}|$TRADING_DIR|g" .env
echo "✅ Created .env template - EDIT WITH YOUR CREDENTIALS"
else
echo "✅ .env already exists"
fi
# Create start script
source .env executes the contents of the .env file as shell code rather than merely parsing key-value pairs. If the file is modified maliciously or accidentally contains shell metacharacters/commands, running authenticate.sh can lead to arbitrary command execution in addition to exposing credentials.
#!/bin/bash
cd "$(dirname "$0")"
source venv/bin/activate
source .env
# Start Xvfb if not running
if ! pgrep -x Xvfb > /dev/null; then
The final instructions direct the user to place IBKR credentials into .env, again normalizing insecure plaintext storage. While this line alone does not expose secrets, it operationalizes an unsafe pattern around high-value financial credentials.
echo "✅ Setup complete!"
echo ""
echo "Next steps:"
echo "1. Edit .env with your IBKR credentials"
echo "2. Run: ./start-gateway.sh"
echo "3. Wait 20 seconds"
echo "4. Run: ./authenticate.sh"
This code can place trades and then automatically confirm broker warning prompts without any human approval, which removes an important safety barrier before capital is committed. In a trading automation skill, this is especially dangerous because strategy bugs, bad symbol resolution, manipulated inputs, or unexpected broker warnings could immediately result in unintended live orders being executed.
The skill instructs users to perform shell commands, access environment variables, and make network requests, but it does not declare any tool scope or permissions boundary. In an agent setting, this increases the chance that an agent could overreach into sensitive execution, networking, or secret-handling operations without explicit user awareness or platform enforcement.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
# Java (for Client Portal Gateway)
sudo apt-get install -y openjdk-17-jre-headless
# Chrome + ChromeDriver (for IBeam)
sudo apt-get install -y chromium-browser chromium-chromedriver
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
curl -sk https://localhost:5000/v1/api/iserver/auth/status
Authenticated response includes "authenticated": true.
The skill provides a ready-to-run live order placement example against an IBKR account without a prominent warning that it can execute real trades and affect real funds. In trading automation context, omission of that warning materially raises the risk of accidental financial loss if a user or agent tests commands against a live account.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
def keepalive():
try:
r = requests.post("https://localhost:5000/v1/api/tickle", verify=False, timeout=10)
status = requests.get("https://localhost:5000/v1/api/iserver/auth/status", verify=False, timeout=10)
return status.json().get("authenticated", False)
except:
Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.
def keepalive():
try:
r = requests.post("https://localhost:5000/v1/api/tickle", verify=False, timeout=10)
status = requests.get("https://localhost:5000/v1/api/iserver/auth/status", verify=False, timeout=10)
return status.json().get("authenticated", False)
except:
The keepalive script disables TLS certificate verification with verify=False, which permits man-in-the-middle interception or spoofing of the local HTTPS gateway. In this skill's context, a spoofed gateway could manipulate auth-state responses or interact with sensitive trading session traffic, making insecure transport especially concerning.
def keepalive():
try:
r = requests.post("https://localhost:5000/v1/api/tickle", verify=False, timeout=10)
status = requests.get("https://localhost:5000/v1/api/iserver/auth/status", verify=False, timeout=10)
return status.json().get("authenticated", False)
except:
Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.
def keepalive():
try:
r = requests.post("https://localhost:5000/v1/api/tickle", verify=False, timeout=10)
status = requests.get("https://localhost:5000/v1/api/iserver/auth/status", verify=False, timeout=10)
return status.json().get("authenticated", False)
except:
return False
The authentication-status request also sets verify=False, extending the same TLS bypass to a sensitive session-check path. This undermines the integrity of security-relevant state and can cause agents or users to trust forged responses about whether a trading session is authenticated.
def keepalive():
try:
r = requests.post("https://localhost:5000/v1/api/tickle", verify=False, timeout=10)
status = requests.get("https://localhost:5000/v1/api/iserver/auth/status", verify=False, timeout=10)
return status.json().get("authenticated", False)
except:
return False
The documentation explicitly recommends disabling TLS certificate verification with verify=False or curl -k, which removes server identity validation and enables man-in-the-middle interception or spoofing. Because this skill handles brokerage authentication and account/trading traffic, intercepted sessions or modified responses could expose credentials, portfolio data, or lead to unauthorized trading actions.
Using verify=False is an unsafe default because it normalizes insecure transport behavior in example usage. In the context of brokerage automation with authentication and order placement, this materially raises the risk of traffic interception, API spoofing, and tampering with sensitive financial operations.
Base URL: `https://localhost:5000`
All requests use HTTPS with self-signed certs (use `verify=False` or `-k` with curl).
## Authentication
No suspicious patterns detected.