T09 · Insecure Skill Coding Practices
- Location
mtf_momentum.py:256- Finding
API Credential Can Be Redirected to an Arbitrary Network Endpoint
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a real trading automation skill with disclosed dry-run/live modes, but its market scope, credential handling, and dependency controls need careful review before installation.
Install only after confirming this is meant to trade SOL 5-minute markets through Simmer, not BTC directly on Polymarket. Use a minimally scoped API key, do not set SIMMER_API_URL unless you fully trust the destination, pin and review simmer-sdk, keep dry-run mode until tested, and enable cron/live trading only with explicit risk limits.
mtf_momentum.py:256API Credential Can Be Redirected to an Arbitrary Network Endpoint
clawhub.json:8Security-Critical Third-Party Dependency Is Installed Without Version or Integrity Pinning
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
url = f"{BINANCE_KLINE_URL}?symbol={symbol}&interval={interval}&limit={limit}"
try:
req = Request(url, headers={"User-Agent": "SimmerMTFMomentum/1.0"})
data = json.loads(urlopen(req, timeout=10).read())
return data
except Exception as e:
print(f" Binance kline fetch failed: {e}")
The request target is built from SIMMER_API_URL, which is environment-controlled, and the code attaches the SIMMER_API_KEY as a Bearer token header before calling urlopen. If an attacker can influence the environment or deployment configuration, they can redirect this request to an attacker-controlled host and capture the API key, making this a real credential exfiltration risk.
f"{SIMMER_API_URL}/api/sdk/fast-markets?asset={ASSET}&window=5m&limit=10",
headers={"Authorization": f"Bearer {api_key}"},
)
data = json.loads(urlopen(req, timeout=10).read())
return data.get("markets", [])
except Exception as e:
print(f" Failed to fetch fast markets: {e}")
The documentation describes one strategy and market context, but the detected behavior references different assets, different platform resources, and additional portfolio/status operations not clearly disclosed in the declared purpose. In a trading skill, this ambiguity is dangerous because users may grant trust or permissions based on a false understanding of what accounts, markets, and operations the skill will actually touch.
The documentation describes one strategy and market context, but the detected behavior references different assets, different platform resources, and additional portfolio/status operations not clearly disclosed in the declared purpose. In a trading skill, this ambiguity is dangerous because users may grant trust or permissions based on a false understanding of what accounts, markets, and operations the skill will actually touch.
The manifest description frames the skill as targeting Polymarket BTC 5-minute fast markets, but the implementation hard-codes ASSET = "SOL" and BINANCE_SYMBOL = "SOLUSDT". This is a direct semantic mismatch in the traded instrument, not an implementation detail.
The script is hard-coded to SOL and a Simmer trade source even though the skill metadata describes Polymarket BTC 5-minute markets. This mismatch can cause operators to review the wrong asset and venue status, leading to incorrect trading decisions, missed risk exposure, and false assurance about strategy state.
The skill documents behavior that depends on environment variables and external network access, but it does not declare any explicit tool scope or permissions. In an agent ecosystem, missing scope declarations reduce transparency and can cause users or orchestrators to approve a skill without understanding that it can access secrets and communicate externally, which is especially risky for a trading bot handling API keys and live actions.
The manifest and body text conflict on the traded asset and market source, undermining the integrity of the documentation. In a finance-related skill, inconsistent asset/source labeling can cause an operator to deploy the strategy under false assumptions, making accidental misuse materially more likely.
The example output shows a BTC market trade even though the skill is presented as a SOL strategy, which can train users to expect the wrong runtime behavior. Examples are often treated as operational truth, so this contradiction increases the chance of executing against an unintended market and suffering financial mistakes.
The skill advertises a --live mode for executing trades but does not prominently warn that real funds can be used and lost. In trading automation, insufficient risk disclosure can lead users to trigger irreversible financial actions without informed consent, especially when setup instructions and command examples make live execution seem routine.
The description claims trading for Polymarket fast markets, but the code is implemented against api.simmer.markets and SimmerClient, including market discovery and trade execution through Simmer-specific interfaces. That may still be related infrastructure, but as written the manifest does not accurately describe the actual trading venue/integration used by the code.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
SLIPPAGE_MAX_PCT = 0.15
SIMMER_API_URL = os.environ.get("SIMMER_API_URL", "https://api.simmer.markets")
BINANCE_KLINE_URL = "https://api.binance.com/api/v3/klines"
# ---------------------------------------------------------------------------
# SimmerClient singleton
The docstring claims this status tool 'Shows active positions and recent signals,' but the implementation only calls get_portfolio() and get_positions() and reports balances, positions, PnL, and win rate. There is no retrieval or display of any signal history, so the documentation overstates what the script does.
The top-level documentation states the skill 'Reads 1m/3m/5m Binance SOL/USDT returns', which implies direct multi-timeframe inputs. In reality, the code fetches only 1-minute klines and computes 3-minute and 5-minute returns synthetically from that single stream.
No suspicious patterns detected.