T09 Β· Insecure Skill Coding Practices
- Location
dashboard_api.py:102- Finding
Unauthenticated Dashboard Exposes Private Account Data and Workspace Files
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a real automated Binance futures trading skill, but it has serious review-worthy risks around public dashboard exposure, secret handling, and automatic leveraged order execution.
Review before installing. Use only test or tightly scoped, IP-restricted Binance keys, do not expose the dashboard to a public network, remove any instruction that prints .env contents, and fix the order-management and dependency issues before using real funds. Rotate Binance and Telegram credentials if this code or dashboard has already run on an exposed host.
dashboard_api.py:102Unauthenticated Dashboard Exposes Private Account Data and Workspace Files
README.md:203Unsafe Dependency Instructions Create Package-Substitution and Mutable Supply-Chain Risk
price-monitor.py:270Duplicated Position-Management Logic Can Over-Close or Reverse Leveraged Positions
price-monitor.py:374Missing Cached SL/TP State Disables Position Monitoring
SKILL.md:71Setup Instructions Print Credential File Contents
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
"""Use fapi/v2/positionRisk β has entryPrice, markPrice, unRealizedProfit."""
ts = int(time.time() * 1000)
sig = hmac.new(SECRET.encode(), f'timestamp={ts}'.encode(), hashlib.sha256).hexdigest()
r = requests.get(
f'https://fapi.binance.com/fapi/v2/positionRisk?timestamp={ts}&signature={sig}',
headers={'X-MBX-APIKEY': API_KEY}, timeout=8
)
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
# Balance from account snapshot
sig2 = hmac.new(SECRET.encode(), f'timestamp={ts}'.encode(), hashlib.sha256).hexdigest()
r2 = requests.get(
f'https://fapi.binance.com/fapi/v3/account?timestamp={ts}&signature={sig2}',
headers={'X-MBX-APIKEY': API_KEY}, timeout=8
)
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).
s
from datetime import datetime, timedelta
from typing import Set, List, Dict
# Load env
script_dir = os.path.dirname(os.path.abspath(__file__))
env_file = os.path.join(script_dir, '.env')
if os.path.exists(env_file):
with open(env_file) as f:
for line in f:
line = line.strip()
if line and '=' in line:
k, v = line.split('=', 1)
os.environ[k] = v
API_KEY = os.environ.get('BINANCE_API_KEY', '')
BLOCKLIST_FILE = os.path.join(script_dir, '.delist_blocklist.json')
# Keywords that indicate delisting
DELIST_KEYWORDS = [
'delist', 'removal', 'will be removed', 'will no longer',
'εζ’δΊ€ζ', 'δΈζΆ', 'delisted', 'termination',
'terminate', 'εζ’εηΊ¦', 'εηΊ¦ε°ζ'
]
def load_blocklist() -> Set[str]:
"""Load blocked tokens from file"""
try:
with open(BLOCKLIST_FILE, 'r') as f:
data = json.load(f)
return set(data.get('tokens', []))
except:
return set()
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
msg += "\n_Automatically added to blocklist_"
try:
requests.post(f'https://api.telegram.org/bot{token}/sendMessage',
data={'chat_id': channel, 'text': msg, 'parse_mode': 'Markdown'},
timeout=10)
except:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
sig = get_sig(params)
# Get account info
r = requests.get(f'https://fapi.binance.com/fapi/v2/positionRisk?{params}&signature={sig}',
headers={'X-MBX-APIKEY': API_KEY}, timeout=15)
positions = [p for p in r.json() if float(p.get('positionAmt', 0)) != 0]
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
positions = [p for p in r.json() if float(p.get('positionAmt', 0)) != 0]
# Get account balance
r2 = requests.get(f'https://fapi.binance.com/fapi/v3/account?{params}&signature={sig}',
headers={'X-MBX-APIKEY': API_KEY}, timeout=15)
acc = r2.json()
balance = float(acc.get('totalMarginBalance', 0))
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).
onfig import *
except ImportError:
pass # Use defaults
# === LOAD FROM ENV FILE ===
script_dir = os.path.dirname(os.path.abspath(__file__))
env_file = os.path.join(script_dir, '.env')
if os.path.exists(env_file):
with open(env_file) as f:
for line in f:
line = line.strip()
if line and '=' in line:
k, v = line.split('=', 1)
os.environ[k] = v
# === LOAD CONFIG ===
sys.path.insert(0, script_dir)
try:
from config import *
except ImportError:
pass
env_file = os.path.join(script_dir, '.env')
if env_file and os.path.exists(env_file):
with open(env_file) as f:
for line in f:
line = line.strip()
if line and not line.startswith('#') and '=' in line:
key, value = line.split('=', 1)
os.environ[key] = value
API_KEY = os.environ.get('BINANCE_API_KEY', '')
SECRET = os.environ.get('BINANCE_SECRET', '')
TELEGRAM_BOT_TOKEN = os.environ.get('TELEGRAM_B
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
params = f'symbol={symbol}&side={close_side}&type=STOP_MARKET&stopPrice={new_sl}&workingType=CONTRACT_PRICE&closePosition=true×tamp={ts}'
sig = get_sig(params)
try:
r = requests.post(f'https://fapi.binance.com/fapi/v1/order?{params}&signature={sig}',
headers=headers, timeout=15)
return r.json()
except:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
params = f'symbol={symbol}&side={close_side}&type=STOP_MARKET&stopPrice={new_sl}&workingType=CONTRACT_PRICE&closePosition=true×tamp={ts}'
sig = get_sig(params)
try:
r = requests.post(f'https://fapi.binance.com/fapi/v1/order?{params}&signature={sig}',
headers=headers, timeout=15)
return r.json()
except:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
def get_positions():
ts = int(time.time() * 1000)
params = f'timestamp={ts}'
r = requests.get(f'https://fapi.binance.com/fapi/v2/positionRisk?{params}&signature={get_sig(params)}',
headers={'X-MBX-APIKEY': API_KEY}, timeout=15)
return [p for p in r.json() if float(p.get('positionAmt', 0)) != 0]
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
def get_price(symbol):
ts = int(time.time() * 1000)
params = f'timestamp={ts}'
r = requests.get(f'https://fapi.binance.com/fapi/v2/positionRisk?symbol={symbol}&{params}&signature={get_sig(params)}',
headers={'X-MBX-APIKEY': API_KEY}, timeout=15)
data = r.json()
if isinstance(data, list) and len(data) > 0:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
def close_position(symbol, side, quantity):
ts = int(time.time() * 1000)
params = f'symbol={symbol}&side={side}&type=MARKET&quantity={quantity}×tamp={ts}'
r = requests.post(f'https://fapi.binance.com/fapi/v1/order?{params}&signature={get_sig(params)}',
headers={'X-MBX-APIKEY': API_KEY}, timeout=15)
return r.json()
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
def send_telegram(msg):
if TELEGRAM_BOT_TOKEN and TELEGRAM_CHANNEL:
requests.post(f'https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage',
data={'chat_id': TELEGRAM_CHANNEL, 'text': msg, 'parse_mode': 'Markdown'})
def check_multi_tp(symbol, side, entry, current, position_amt, original_amt):
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
for i in range(max_retries):
time.sleep(1)
check_params = f'orderId={order_id}&symbol={symbol}×tamp={int(time.time() * 1000)}'
check_r = requests.get(f'https://fapi.binance.com/fapi/v1/order?{check_params}&signature={get_sig(check_params)}',
headers={'X-MBX-APIKEY': API_KEY}, timeout=15)
order_data = check_r.json()
status = order_data.get('status', '')
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).
oad from the same directory as the script
script_dir = os.path.dirname(os.path.abspath(__file__))
env_file = os.path.join(script_dir, '.env')
if env_file and os.path.exists(env_file):
with open(env_file) as f:
for line in f:
line = line.strip()
if line and not line.startswith('#') and '=' in line:
key, value = line.split('=', 1)
os.environ[key] = value
# === LOAD CONFIG FROM config.py ===
try:
from config import *
except ImportError:
pass
# Load delisting blocklist
try:
from delisting_monitor import is_token_blocked, get_blocklist, check_binance_delist_announcements
DELISTING_CHECK = True
except ImportError:
DELISTING_CHECK = False
# Default ATR multipliers if not loaded from config
try:
ATR_MULTIPLIER_SL_HIGH
except NameError:
ATR_MULTIPLIER_SL_HIGH = 2.0
try:
ATR_MULTIPLIER_TP_HIGH
except NameError:
ATR_MULTIPLIER_TP_HIGH = 4.0
try:
ATR_MULTIPLIER_SL_NORMAL
except NameError
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
params['timestamp'] = int(time.time() * 1000)
params['signature'] = get_signature('&'.join(f'{k}={v}' for k, v in params.items()))
headers = {'X-MBX-APIKEY': API_KEY}
r = requests.get(url, params=params, headers=headers, timeout=15)
return r.json()
def binance_post(url, params):
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
params['timestamp'] = int(time.time() * 1000)
params['signature'] = get_signature('&'.join(f'{k}={v}' for k, v in params.items()))
headers = {'X-MBX-APIKEY': API_KEY}
r = requests.post(url, data=params, headers=headers, timeout=15)
return r.json()
# === GET DATA ===
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
ts = int(time.time() * 1000)
params = "timestamp={}".format(ts)
sig = get_signature(params)
r = requests.get("https://fapi.binance.com/fapi/v3/account?{}&signature={}".format(params, sig),
headers={"X-MBX-APIKEY": API_KEY}, timeout=15)
if r:
try:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
ts = int(time.time() * 1000)
params = "timestamp={}".format(ts)
sig = get_signature(params)
r = requests.get("https://fapi.binance.com/fapi/v3/account?{}&signature={}".format(params, sig),
headers={"X-MBX-APIKEY": API_KEY}, timeout=15)
if r:
try:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
"""Get current Open Interest for a symbol"""
try:
url = f'https://fapi.binance.com/fapi/v1/openInterest?symbol={symbol}'
r = requests.get(url, timeout=10)
data = r.json()
return float(data.get('openInterest', 0))
except:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
"""Get current Open Interest for a symbol"""
try:
url = f'https://fapi.binance.com/fapi/v1/openInterest?symbol={symbol}'
r = requests.get(url, timeout=10)
data = r.json()
return float(data.get('openInterest', 0))
except:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
"""Get current Open Interest for a symbol"""
try:
url = f'https://fapi.binance.com/fapi/v1/openInterest?symbol={symbol}'
r = requests.get(url, timeout=10)
data = r.json()
return float(data.get('openInterest', 0))
except:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
"""Get current Open Interest for a symbol"""
try:
url = f'https://fapi.binance.com/fapi/v1/openInterest?symbol={symbol}'
r = requests.get(url, timeout=10)
data = r.json()
return float(data.get('openInterest', 0))
except:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
"""Get current Open Interest for a symbol"""
try:
url = f'https://fapi.binance.com/fapi/v1/openInterest?symbol={symbol}'
r = requests.get(url, timeout=10)
data = r.json()
return float(data.get('openInterest', 0))
except:
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
def get_klines(symbol, interval='1h', limit=100):
url = f'https://fapi.binance.com/fapi/v1/klines?symbol={symbol}&interval={interval}&limit={limit}'
r = requests.get(url, timeout=15)
return r.json()
def place_order_with_sl_tp(symbol, side, quantity, sl_price, tp_price):