Back to skill

Security audit

Neko Futures Trader

Security checks for vulnerabilities and agentic risk

Overview

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.

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 (5)

T09 Β· Insecure Skill Coding Practices

Error
Location
dashboard_api.py:102
Finding

Unauthenticated Dashboard Exposes Private Account Data and Workspace Files

Content
View full analysis
Remediation
View remediation

T08 Β· Insecure Dependencies

Error
Location
README.md:203
Finding

Unsafe Dependency Instructions Create Package-Substitution and Mutable Supply-Chain Risk

Content
View full analysis
Remediation
View remediation

T09 Β· Insecure Skill Coding Practices

Error
Location
price-monitor.py:270
Finding

Duplicated Position-Management Logic Can Over-Close or Reverse Leveraged Positions

Content
View full analysis
0 else 0 if profit_pct >= tp3 and remaining_pct > 0: close_amt = abs(position_amt) close_side = 'SELL' if side == 'LONG' else 'BUY' result = close_position(symbol, close_side, close_amt) ``` The first execution block begins with: ```python original_amt = abs(amt) # Store original amount for Multi-TP calculation check_multi_tp(symbol, side, entry, current, amt, original_amt) ``` The multi-TP, trailing-TP, stop-loss, and take-profit logic is then repeated later in the same loop: ```python original_amt = abs(amt) # Store original amount for Multi-TP calculation check_multi_tp(symbol, side, entry, current, amt, original_amt) ``` Orders are submitted without a reduce-only constraint: ```python 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() ``` ### Technical Analysis The same multi-TP, trailing, stop-loss, and take-profit execution logic appears twice in one position-processing iteration. A successful first order does not consistently terminate processing or refresh the current Binance position before the duplicate block executes. In addition, ...[truncated 1604 chars]
Remediation
View remediation

T09 Β· Insecure Skill Coding Practices

Error
Location
price-monitor.py:374
Finding

Missing Cached SL/TP State Disables Position Monitoring

Content
View full analysis
configured % try: trail_thresh = MIN_PROFIT_TRAILING_TP if 'MIN_PROFIT_TRAILING_TP' in dir() else 3.0 except: trail_thresh = 3.0 new_trailing_tp = should_activate_trailing_tp(entry, current, tp_price, side, trail_percent=trail_thresh) ``` ### Technical Analysis `sl_price` and `tp_price` are assigned only when the local JSON cache contains both expected fields. If a live Binance position was opened manually, the cache was deleted or corrupted, or a previous write failed, these variables remain uninitialized. The code nevertheless passes `tp_price` to `should_activate_trailing_tp` and later uses both variables in SL/TP comparisons. Python raises `UnboundLocalError`. The broad outer exception catches the error, prints it, and delays until the next loop, so the same unmanaged position can fail repeatedly. The documented ATR fallback occurs later and is not reached before the first use. ### Attack Path 1. A Binance futures position exists without a matching complete entry in `.positions_sl_tp.json`. 2. The monitor reads an empty or incomplete `pos_data` object. 3. It skips initialization of `sl_price` and `tp_price`. 4. The trailing-TP call references `tp_price`, raising ...[truncated 551 chars]
Remediation
View remediation

T09 Β· Insecure Skill Coding Practices

Warning
Location
SKILL.md:71
Finding

Setup Instructions Print Credential File Contents

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (119)

Tainted flow: 'sig' from os.environ (line 31, credential/environment) β†’ requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· dashboard_api.py (reported line 32)May include surrounding context.

python
"""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
    )

Tainted flow: 'sig2' from os.environ (line 60, credential/environment) β†’ requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· dashboard_api.py (reported line 61)May include surrounding context.

python
# 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 'agent_skill_credential_exfiltration_webhook': AI agent skill credential harvesting followed by webhook or external exfiltration [agent_skills]

Critical
Category
YARA Match
Confidence
85% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt Β· delisting_monitor.py (reported line 24)May include surrounding context.

python
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()

Tainted flow: 'token' from os.environ.get (line 121, credential/environment) β†’ requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· delisting_monitor.py (reported line 134)May include surrounding context.

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

Tainted flow: 'API_KEY' from os.environ (line 23, credential/environment) β†’ requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· position_command.py (reported line 37)May include surrounding context.

python
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]

Tainted flow: 'API_KEY' from os.environ (line 23, credential/environment) β†’ requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· position_command.py (reported line 42)May include surrounding context.

python
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 'agent_skill_credential_exfiltration_webhook': AI agent skill credential harvesting followed by webhook or external exfiltration [agent_skills]

Critical
Category
YARA Match
Confidence
85% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt Β· price-monitor.py (reported line 35)May include surrounding context.

python
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

Tainted flow: 'headers' from os.environ.get (line 123, credential/environment) β†’ requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· price-monitor.py (reported line 114)May include surrounding context.

python
params = f'symbol={symbol}&side={close_side}&type=STOP_MARKET&stopPrice={new_sl}&workingType=CONTRACT_PRICE&closePosition=true&timestamp={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:

Tainted flow: 'headers' from os.environ.get (line 123, credential/environment) β†’ requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· price-monitor.py (reported line 128)May include surrounding context.

python
params = f'symbol={symbol}&side={close_side}&type=STOP_MARKET&stopPrice={new_sl}&workingType=CONTRACT_PRICE&closePosition=true&timestamp={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:

Tainted flow: 'API_KEY' from os.environ.get (line 54, credential/environment) β†’ requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· price-monitor.py (reported line 137)May include surrounding context.

python
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]

Tainted flow: 'API_KEY' from os.environ.get (line 54, credential/environment) β†’ requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· price-monitor.py (reported line 144)May include surrounding context.

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

Tainted flow: 'API_KEY' from os.environ.get (line 54, credential/environment) β†’ requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· price-monitor.py (reported line 193)May include surrounding context.

python
def close_position(symbol, side, quantity):
    ts = int(time.time() * 1000)
    params = f'symbol={symbol}&side={side}&type=MARKET&quantity={quantity}&timestamp={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()

Tainted flow: 'TELEGRAM_BOT_TOKEN' from os.environ.get (line 56, credential/environment) β†’ requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· price-monitor.py (reported line 267)May include surrounding context.

python
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):

Tainted flow: 'API_KEY' from os.environ.get (line 54, credential/environment) β†’ requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· price-monitor.py (reported line 635)May include surrounding context.

python
for i in range(max_retries):
                        time.sleep(1)
                        check_params = f'orderId={order_id}&symbol={symbol}&timestamp={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 'agent_skill_credential_exfiltration_webhook': AI agent skill credential harvesting followed by webhook or external exfiltration [agent_skills]

Critical
Category
YARA Match
Confidence
85% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt Β· scanner-v8.py (reported line 37)May include surrounding context.

python
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

Tainted flow: 'url' from os.environ.get (line 459, credential/environment) β†’ requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· scanner-v8.py (reported line 97)May include surrounding context.

python
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):

Tainted flow: 'url' from os.environ.get (line 459, credential/environment) β†’ requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· scanner-v8.py (reported line 104)May include surrounding context.

python
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 ===

Tainted flow: 'API_KEY' from os.environ.get (line 79, credential/environment) β†’ requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· scanner-v8.py (reported line 113)May include surrounding context.

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

Tainted flow: 'API_KEY' from os.environ.get (line 79, credential/environment) β†’ requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· scanner-v8.py (reported line 125)May include surrounding context.

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

Tainted flow: 'url' from os.environ.get (line 459, credential/environment) β†’ requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· scanner-v8.py (reported line 170)May include surrounding context.

python
"""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:

Tainted flow: 'url' from os.environ.get (line 459, credential/environment) β†’ requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· scanner-v8.py (reported line 180)May include surrounding context.

python
"""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:

Tainted flow: 'url' from os.environ.get (line 459, credential/environment) β†’ requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· scanner-v8.py (reported line 208)May include surrounding context.

python
"""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:

Tainted flow: 'url' from os.environ.get (line 459, credential/environment) β†’ requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· scanner-v8.py (reported line 229)May include surrounding context.

python
"""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:

Tainted flow: 'url' from os.environ.get (line 459, credential/environment) β†’ requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· scanner-v8.py (reported line 239)May include surrounding context.

python
"""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:

Tainted flow: 'url' from os.environ.get (line 459, credential/environment) β†’ requests.get (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt Β· scanner-v8.py (reported line 247)May include surrounding context.

python
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):