Back to skill

Security audit

IBKR Trading

Security checks for vulnerabilities and agentic risk

Overview

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.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (4)

T09 · Insecure Skill Coding Practices

Error
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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/setup.sh:66
Finding

Plaintext brokerage credential file is created without enforced restrictive permissions

Content
View full analysis
.env << 'EOF' # IBKR Credentials - EDIT THESE IBEAM_ACCOUNT=your_username IBEAM_PASSWORD='your_password' # Paths (auto-configured) IBEAM_GATEWAY_DIR=${TRADING_DIR}/clientportal IBEAM_CHROME_DRIVER_PATH=/usr/bin/chromedriver # 2FA Settings IBEAM_TWO_FA_SELECT_TARGET="IB Key" 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" fi ``` The generated authentication script then loads and exports the secret: ```bash cat > authenticate.sh << 'EOF' #!/bin/bash cd "$(dirname "$0")" source venv/bin/activate source .env # Start Xvfb if not running if ! pgrep -x Xvfb > /dev/null; then Xvfb :99 -screen 0 1024x768x24 & sleep 2 fi export DISPLAY=:99 export IBEAM_ACCOUNT export IBEAM_PASSWORD export IBEAM_GATEWAY_DIR export IBEAM_CHROME_DRIVER_PATH export IBEAM_TWO_FA_SELECT_TARGET export IBEAM_OAUTH_TIMEOUT export IBEAM_PAGE_LOAD_TIMEOUT ``` ### Technical Analysis The setup script creates `.env` using the caller's existing `umask` and never applies an explicit restrictive mode such as `0600`. Once the placeholder is replaced, this file contains a plaintext IBKR username and password. On systems with a permissive umask, the file may be readable by other local users or service accounts. The password is also exported into the environment of the IBeam authentication process. Environment inheritance is necessary for the selected IBeam integration, but it increases secret exposure to child processes and potentially to proce ...[truncated 1349 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/setup.sh:43
Finding

Unpinned Python dependencies and an unchecked gateway archive are installed

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/trading_bot.py:125
Finding

Trading bot automatically accepts all order confirmation requests

Content
View full analysis
dict: """ Place an order. Args: conid: Contract ID side: "BUY" or "SELL" quantity: Number of shares order_type: "MKT", "LMT", "STP", etc. limit_price: Price for limit orders """ order = { "conid": conid, "orderType": order_type, "side": side, "quantity": quantity, "tif": "DAY" } if limit_price and order_type == "LMT": order["price"] = limit_price # Place order result = self._post(f"/v1/api/iserver/account/{self.account_id}/orders", { "orders": [order] }) # Handle confirmation if needed if isinstance(result, list) and len(result) > 0: if result[0].get("messageIds"): # Confirm the order confirm = self._post(f"/v1/api/iserver/reply/{result[0]['id']}", { "confirmed": True }) return confirm return result ``` ### Technical Analysis The IBKR API can return an order confirmation request containing warning or informational messages. The code treats the mere presence of `messageIds` as sufficient authorization to send `{"confirmed": true}`. It does not inspect the warning identifiers or text, compare the returned order with the submitted order, require user approval, or apply limits for symbol, quantity, price, notional value, account, or order type. This removes a safety boundary intended to warn about potentially consequential transactions. The issue is particularly significant because `place_order` is designed for use by customizable automated strategies. A strategy error, unexpected ...[truncated 1208 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (38)

Tainted flow: 'BASE_URL' from os.getenv (line 18, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

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.

Content

Scanner excerpt · scripts/keepalive.py (reported line 28)May include surrounding context.

python
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

Tainted flow: 'BASE_URL' from os.getenv (line 18, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
97% confidence
Finding

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.

Content

Scanner excerpt · scripts/keepalive.py (reported line 41)May include surrounding context.

python
def tickle():
    """Send keepalive ping."""
    try:
        r = requests.post(
            f"{BASE_URL}/v1/api/tickle",
            verify=False,
            timeout=10

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

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.

Content

Scanner excerpt · SKILL.md (reported line 77)May include surrounding context.

md
# 3. Run IBeam authentication
cd ~/trading
source venv/bin/activate
source .env
export DISPLAY=:99
Xvfb :99 -screen 0 1024x768x24 &
python -m ibeam --authenticate

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

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.

Content

Scanner excerpt · references/api-endpoints.md (reported line 217)May include surrounding context.

Cancel Order

text
DELETE /v1/api/iserver/account/{accountId}/order/{orderId}

Modify Order

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

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.

Content

Scanner excerpt · scripts/setup.sh (reported line 66)May include surrounding context.

sh
echo "✅ Python venv already exists"
fi

# Create .env template if not exists
if [ ! -f ".env" ]; then
    echo ""
    echo "📝 Creating .env template..."

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

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.

Content

Scanner excerpt · scripts/setup.sh (reported line 67)May include surrounding context.

sh
fi

# Create .env template if not exists
if [ ! -f ".env" ]; then
    echo ""
    echo "📝 Creating .env template..."
    cat > .env << 'EOF'

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

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.

Content

Scanner excerpt · scripts/setup.sh (reported line 69)May include surrounding context.

sh
# 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

Credential Access

High
Category
Privilege Escalation
Confidence
98% confidence
Finding

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.

Content

Scanner excerpt · scripts/setup.sh (reported line 70)May include surrounding context.

sh
if [ ! -f ".env" ]; then
    echo ""
    echo "📝 Creating .env template..."
    cat > .env << 'EOF'
# IBKR Credentials - EDIT THESE
IBEAM_ACCOUNT=your_username
IBEAM_PASSWORD='your_password'

Credential Access

High
Category
Privilege Escalation
Confidence
92% confidence
Finding

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.

Content

Scanner excerpt · scripts/setup.sh (reported line 84)May include surrounding context.

sh
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"

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

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.

Content

Scanner excerpt · scripts/setup.sh (reported line 85)May include surrounding context.

sh
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

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

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.

Content

Scanner excerpt · scripts/setup.sh (reported line 87)May include surrounding context.

sh
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

Credential Access

High
Category
Privilege Escalation
Confidence
98% confidence
Finding

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.

Content

Scanner excerpt · scripts/setup.sh (reported line 108)May include surrounding context.

sh
#!/bin/bash
cd "$(dirname "$0")"
source venv/bin/activate
source .env

# Start Xvfb if not running
if ! pgrep -x Xvfb > /dev/null; then

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

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.

Content

Scanner excerpt · scripts/setup.sh (reported line 135)May include surrounding context.

sh
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"

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 30)May include surrounding context.

bash
# 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

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 88)May include surrounding context.

Check Auth Status

bash
curl -sk https://localhost:5000/v1/api/iserver/auth/status

Authenticated response includes "authenticated": true.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

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.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 154)May include surrounding context.

md
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:

Internal Network Request

Medium
Category
Server-Side Request Forgery
Confidence
70% confidence
Finding

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.

Content

Scanner excerpt · SKILL.md (reported line 154)May include surrounding context.

md
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:

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
97% confidence
Finding

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.

Content

Scanner excerpt · SKILL.md (reported line 154)May include surrounding context.

md
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:

Internal Network Request

Medium
Category
Server-Side Request Forgery
Confidence
70% confidence
Finding

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.

Content

Scanner excerpt · SKILL.md (reported line 155)May include surrounding context.

md
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

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
97% confidence
Finding

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.

Content

Scanner excerpt · SKILL.md (reported line 155)May include surrounding context.

md
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

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

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.

Content

No source excerpt is available for this finding.

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
99% confidence
Finding

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.

Content

Scanner excerpt · references/api-endpoints.md (reported line 5)May include surrounding context.

md
Base URL: `https://localhost:5000`

All requests use HTTPS with self-signed certs (use `verify=False` or `-k` with curl).

## Authentication

Static analysis

No suspicious patterns detected.