Back to skill

Security audit

Casino Bot Builder

Security checks for vulnerabilities and agentic risk

Overview

This skill is openly for gambling bot automation, but its templates can let public chat or social users trigger real betting with shared credentials and weak safeguards.

Review before installing. Treat this as live financial automation: add allowlists for users, chats, guilds, channels, and roles; require confirmations for betting and autoplay; set hard wager, daily loss, round, and rate limits; default to dry-run where possible; never print or commit API keys; rotate any key exposed in logs; and pin dependencies before deployment.

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
references/telegram-bot.md:147
Finding
Unauthenticated Telegram Users Can Spend the Shared Casino Balance<![CDATA[ ## Vulnerability Details **File Location**: `references/telegram-bot.md`, lines 147–168 and 187–194 **Vulnerability Type**: Missing authorization, transaction limits, and rate limiting **Risk Level**: High ### Vulnerable Code ```python async def cmd_autoplay(update: Update, context: ContextTypes.DEFAULT_TYPE): if len(context.args) < 3: await update.message.reply_text("Usage: /autoplay <game> <amount> <rounds>") return game, amount, rounds = context.args[0], float(context.args[1]), int(context.args[2]) await update.message.reply_text(f"🤖 Auto-playing {rounds} rounds of {game} at {amount} each...") wins, losses, total_payout = 0, 0, 0 for i in range(rounds): kwargs = {"choice": "heads"} if game == "coinflip" else {"target": 50, "over": True} result = place_bet(game, amount, **kwargs) if result.get("won"): wins += 1 total_payout += result.get("payout", 0) else: losses += 1 await update.message.reply_text( f"🏁 Auto-play complete!\n" f"Rounds: {rounds} | Wins: {wins} | Losses: {losses}\n" f"Total wagered: {amount * rounds} | Total payout: {total_payout}\n" f"Net: {total_payout - (amount * rounds)}" ) ``` ```python app.add_handler(CommandHandler("coinflip", cmd_coinflip)) app.add_handler(CommandHandler("dice", cmd_dice)) app.add_handler(CommandHandler("bet", cmd_bet)) app.add_handler(CommandHandler("balance", cmd_balance)) app.add_handler(CommandHandler("history", cmd_history)) app.add_handler(CommandHandler("autoplay", cmd_autoplay)) app.add_handler(CallbackQueryHandler(button_callback)) ``` ### Technical Analysis All Telegram users who can interact with the bot are allowed to invoke commands that submit authenticated casino transactions. The bot uses one process-wide `AGENT_CASINO_API_KEY`, so user-issued commands operate against the operator's shared casino account rather than an independently authenticated ...[truncated 1415 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Deny betting commands by default and configure an explicit allowlist of authorized Telegram user and chat IDs. - Perform authorization checks inside every state-changing command and callback handler. - Assign each user a separately authenticated and funded account instead of sharing an operator-level API key. - Enforce server-side limits on individual wager amounts, rounds per request, wagers per time interval, daily loss, and total exposure. - Require explicit confirmation before initiating autoplay or high-value transactions. - Add per-user and global rate limiting, concurrency controls, and a circuit breaker. - Validate that amounts are finite, positive, and within configured bounds. - Restrict the game parameter to an explicit allowlist. - Record the requesting Telegram user ID in a tamper-resistant audit log. - Provide an operator-accessible emergency stop that immediately disables all betting. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
references/discord-bot.md:75
Finding
Discord Betting Commands Lack the Advertised Role-Based Access Control<![CDATA[ ## Vulnerability Details **File Location**: `references/discord-bot.md`, lines 75–90 and 135–147 **Vulnerability Type**: Missing role, user, guild, and transaction authorization **Risk Level**: High ### Vulnerable Code ```javascript client.on('interactionCreate', async interaction => { if (!interaction.isChatInputCommand()) return; try { if (interaction.commandName === 'coinflip') { const amount = interaction.options.getNumber('amount'); const result = await placeBet('coinflip', amount, { choice: 'heads' }); const embed = new EmbedBuilder() .setTitle(result.won ? '✅ You Won!' : '❌ You Lost') .setColor(result.won ? 0x00ff00 : 0xff0000) .addFields( { name: 'Bet', value: `${amount}`, inline: true }, { name: 'Payout', value: `${result.payout || 0}`, inline: true }, { name: 'Bet ID', value: result.bet_id || 'N/A', inline: true } ) ``` ```javascript else if (interaction.commandName === 'autoplay') { const game = interaction.options.getString('game'); const amount = interaction.options.getNumber('amount'); const rounds = interaction.options.getInteger('rounds'); await interaction.deferReply(); let wins = 0, totalPayout = 0; const opts = game === 'coinflip' ? { choice: 'heads' } : { target: 50, over: true }; for (let i = 0; i < Math.min(rounds, 50); i++) { const result = await placeBet(game, amount, opts); if (result.won) { wins++; totalPayout += result.payout || 0; } } ``` ### Technical Analysis The Skill documentation advertises role-based access control, but the Discord template performs no validation of `interaction.member` roles or permissions. It also does not restrict commands to approved guilds, channels, or users. Every accepted interaction uses the same casino API client configured with the operator's `AGENT_CASINO_API_KEY`. The 50-iteration limit only restricts one autoplay request; it does not cap the wager amount, aggregate exposu ...[truncated 1103 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Check `interaction.guildId`, `interaction.channelId`, `interaction.user.id`, and `interaction.member` roles before every sensitive operation. - Configure an explicit allowlist of authorized guilds, channels, roles, and operators. - Deny use in direct messages unless explicitly required. - Set Discord command default member permissions so betting commands are unavailable to ordinary members. - Bind wagers to separately authenticated user accounts rather than an operator-wide API key. - Cap amount, rounds, cumulative daily exposure, and maximum loss on the server side. - Rate-limit commands per user, guild, and bot instance, including concurrent invocations. - Require confirmation for autoplay and high-value wagers. - Recalculate results using the number of rounds actually executed rather than the untrusted requested value. - Maintain an immutable audit trail containing the requesting Discord user and guild. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
references/twitter-bot.md:83
Finding
Public Twitter Mentions Can Trigger Unauthorized Financial Transactions<![CDATA[ ## Vulnerability Details **File Location**: `references/twitter-bot.md`, lines 83–109 **Vulnerability Type**: Unauthenticated public input mapped directly to privileged transactions **Risk Level**: High ### Vulnerable Code ```python def reply_betting(): """Monitor mentions and place bets from replies.""" since_id = None while True: mentions = twitter.mentions_timeline(since_id=since_id, count=20) for mention in mentions: since_id = mention.id text = mention.text.lower() # Parse: @bot coinflip 100 parts = text.split() if len(parts) >= 3: game = parts[-2] if parts[-2] in ["coinflip", "dice"] else "coinflip" try: amount = float(parts[-1]) except ValueError: amount = 100 kwargs = {"choice": "heads"} if game == "coinflip" else {"target": 50, "over": True} result = place_bet(game, amount, **kwargs) reply = ( f"@{mention.user.screen_name} {'✅ WON' if result.get('won') else '❌ LOST'} " f"| {game} {amount} → {result.get('payout', 0)}" ) twitter.update_status(reply, in_reply_to_status_id=mention.id) time.sleep(30) ``` ### Technical Analysis The reply-monitoring mode interprets arbitrary public mentions as instructions to place bets. It does not authenticate the sender, verify account ownership, require prior enrollment, request confirmation, or impose wager and frequency limits. The resulting wager is submitted with the process-wide casino API key. Therefore, any Twitter user capable of mentioning the bot can trigger a privileged financial operation against the operator's balance. A public social-media identity is not an adequate authorization mechanism for access to shared funds. The parser also accepts arbitrary floating-point values without checking that ...[truncated 881 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Do not map public mentions directly to financial transactions. - Use mentions only to return informational instructions or a link to an authenticated application. - If reply-based betting is required, require prior account linking and cryptographic or out-of-band confirmation. - Maintain an explicit allowlist of permitted Twitter account IDs; do not authorize based only on mutable screen names. - Enforce positive, finite, server-bounded amounts and reject malformed values. - Add per-account, global, and rolling-window rate limits. - Establish daily spend and loss limits and an automatic shutdown threshold. - Require an operator confirmation for high-value transactions and autoplay behavior. - Isolate each user's funds and credentials instead of using one shared operator key. - Log the originating tweet ID, immutable user ID, amount, and authorization decision. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/setup-bot.sh:14
Finding
Setup Script Prints the Registration Response Containing API Credentials<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup-bot.sh`, lines 14–18 **Vulnerability Type**: Sensitive credential disclosure through terminal and build logs **Risk Level**: High ### Vulnerable Code ```bash RESPONSE=$(curl -s -X POST https://agent.rollhub.com/api/v1/register \ -H "Content-Type: application/json" \ -d "{\"name\": \"$BOT_NAME\", \"ref\": \"ref_27fcab61\"}") echo "Registration response: $RESPONSE" echo "" ``` ### Technical Analysis The project documentation states that the registration endpoint returns an `agent_id` and `api_key`. The setup script prints the complete response without redacting sensitive fields. Terminal output is frequently retained in CI/CD logs, deployment consoles, shell recordings, support transcripts, remote-session logs, or screenshots. Anyone who can read such output may recover the bearer credential. Because the API key authorizes casino operations, treating the entire response as ordinary diagnostic output violates secret-handling principles and least exposure. ### Attack Path 1. An operator executes `scripts/setup-bot.sh` in a terminal, deployment pipeline, or hosted build environment. 2. The script registers an agent and receives a response containing the API key. 3. `echo` writes the complete response to standard output. 4. The terminal or automation system stores the output in a log. 5. A user with log-reading access copies the API key. 6. The user sends authenticated requests directly to the casino API, including wagering requests. ### Impact Assessment An attacker with access to captured output may obtain the same API privileges as the registered bot. Depending on server-side authorization, this can expose balance and betting history and permit unauthorized wagering of all funds available to the agent. The disclosure persists for as long as the key remains valid and the logs remain accessible. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Never print the complete registration response. - Parse only non-sensitive fields for display and redact secrets, for example by showing only the agent ID and a confirmation that a key was created. - Write credentials directly to a dedicated secret manager or permission-restricted file without passing them through logs. - Set generated credential files to mode `0600` and ensure their parent directory is private. - Disable command tracing around secret-processing operations. - Document that API keys must not be committed, pasted into support tickets, or included in screenshots. - Rotate any key that may already have appeared in logs. - Configure CI/CD systems to mask known credential patterns and restrict log access and retention. - Add appropriate `curl` failure handling so malformed or failed responses are not mistaken for valid registration data. ]]>

T08 · Insecure Dependencies

Warning
Location
references/telegram-bot.md:6
Finding
Third-Party Dependencies Are Installed Without Version or Integrity Pinning<![CDATA[ ## Vulnerability Details **File Location**: `references/telegram-bot.md`, line 6; `references/discord-bot.md`, lines 6–7; `references/twitter-bot.md`, line 6; `scripts/setup-bot.sh`, lines 29, 39, and 52 **Vulnerability Type**: Unpinned and integrity-unverified software dependencies **Risk Level**: Medium ### Vulnerable Code ```bash pip install python-telegram-bot requests ``` ```bash npm init -y npm install discord.js axios ``` ```bash pip install tweepy requests ``` The setup script repeats the same installation guidance: ```bash echo "4. pip install python-telegram-bot requests" ``` ```bash echo "4. npm install discord.js axios" ``` ```bash echo "4. pip install tweepy requests" ``` ### Technical Analysis The installation instructions resolve mutable package versions at installation time. The project provides no exact version pins, Python package hashes, committed npm lockfile, or documented integrity-verification process. These dependencies run inside processes that hold Telegram, Discord, Twitter, and casino API credentials. A compromised upstream release, unsafe future version, or dependency-resolution change could therefore execute with access to all of those secrets and the bot's network privileges. No evidence was found that the named packages are themselves malicious. The vulnerability is the absence of reproducible, reviewed, integrity-checked dependency resolution. ### Attack Path 1. A user follows the documented installation command at a later date. 2. The package manager resolves the newest available direct and transitive dependency versions. 3. An upstream package or newly resolved transitive dependency is compromised, or an incompatible release introduces exploitable behavior. 4. Installation hooks or imported package code executes in the bot environment. 5. The affected component gains access to environment variables containing platform tokens and the casino API key. 6. Credentials, bot actions, or wagering requests may be ...[truncated 344 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Pin every direct dependency to an exact reviewed version. - Generate and commit a lockfile for the JavaScript implementation. - Use a fully pinned Python requirements file with hashes and install it using `pip --require-hashes`. - Review and pin transitive dependencies through reproducible lock-generation tooling. - Run dependency vulnerability and provenance checks in CI before deployment. - Use automated update tooling that opens reviewed pull requests rather than silently installing latest releases. - Install dependencies in an isolated virtual environment or container using an unprivileged account. - Minimize environment-variable exposure and provide each bot process only the credentials it requires. - Rebuild and test from clean environments to verify that installations are deterministic. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (17)

Missing User Warnings

High
Confidence
95% confidence
Finding
The skill instructs users to register with an external service and to save an issued api_key, but it gives no warning about secret handling, storage, logging, or transmission to third parties. Because these credentials can authorize betting actions and account access, poor handling could lead to account compromise or unauthorized financial transactions.

Ae1

High
Category
analysis-evasion
Content
Full template: [references/discord-bot.md](references/discord-bot.md)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Missing User Warnings

High
Confidence
97% confidence
Finding
The betting and autoplay sections normalize automated wagering without prominently warning that repeated API calls can spend real funds through irreversible transactions. In this skill's context, broad bot automation plus autoplay materially increases financial risk because a misconfiguration, prompt misunderstanding, or loop can rapidly place many bets.

Missing User Warnings

High
Confidence
98% confidence
Finding
The template presents itself as a Twitter bot that places bets and tweets results, but it does not clearly warn that the code can place real wagers automatically and repeatedly, including in response to social-media mentions. Because the skill's purpose is autonomous gambling automation, omission of this warning materially increases the chance of unintended financial loss, abuse by third parties, and deployment by users who do not realize the bot is live-trading real funds.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill includes shell commands and network interactions with an external gambling API but does not declare any tool restrictions or allowed tool scope. In an agent environment, that ambiguity can let the skill be invoked with broader-than-necessary capabilities, increasing the chance of unintended external requests or command execution.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The description is packed with broad bot-automation and deployment keywords, which can cause the skill to activate for loosely related user requests. Over-broad routing is risky here because the skill drives external wagering automation and account registration, so accidental invocation could push users toward sensitive financial actions.

External Transmission

Medium
Category
Data Exfiltration
Content
Every bot must first register on Agent Casino:

```bash
curl -X POST https://agent.rollhub.com/api/v1/register \
  -H "Content-Type: application/json" \
  -d '{"name": "my-bot", "ref": "ref_27fcab61"}'
```
Confidence
88% confidence
Finding
The skill explicitly directs transmission of registration data to an external domain via curl. While external communication is expected for API integration, it is still a security-relevant behavior because it sends user-controlled identifiers off-platform and initiates an account-registration flow tied to credential issuance.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The keyword block contains many generic activation-style phrases like bot deployment, notifications, slash commands, and automation without limiting context. That makes invocation scope ambiguous and increases the likelihood of the skill being selected for unrelated automation tasks despite containing sensitive betting and API instructions.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The /autoplay command enables repeated wagering in a loop with no user warning, cooldown, budget cap, loss limit, or explicit confirmation despite involving real-money or crypto gambling behavior. In this skill's context, the bot is specifically designed to automate casino betting, which increases the likelihood of financial harm, accidental rapid losses, and unsafe use by operators or end users.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The template instructs users to configure real API credentials and a Telegram bot that can place wagers, but it does not prominently warn that commands trigger live betting and data transmission to a third-party gambling API. In this skill context, that omission is more dangerous because the bot is explicitly designed for autonomous gambling, increasing the chance of unintended financial loss or unsafe deployment by unsuspecting users.

External Transmission

Medium
Category
Data Exfiltration
Content
# --- Registration (run once) ---
def register_agent(name: str) -> dict:
    resp = requests.post(f"{API_BASE}/register", json={"name": name, "ref": "ref_27fcab61"})
    return resp.json()

# --- API Helpers ---
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# --- Registration (run once) ---
def register_agent(name: str) -> dict:
    resp = requests.post(f"{API_BASE}/register", json={"name": name, "ref": "ref_27fcab61"})
    return resp.json()

# --- API Helpers ---
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# --- API Helpers ---
def place_bet(game: str, amount: float, **kwargs) -> dict:
    payload = {"game": game, "amount": amount, **kwargs}
    resp = requests.post(f"{API_BASE}/bet", headers=HEADERS, json=payload)
    return resp.json()

def get_balance() -> dict:
Confidence
92% confidence
Finding
This function sends authenticated betting requests to a remote gambling API using a bearer token, with user-supplied parameters converted directly into live wager actions and no safeguards such as confirmations, spend limits, sandboxing, or strong input validation. In the context of an autonomous casino bot, this materially increases the risk of unauthorized or accidental financial transactions if the bot is misused, exposed, or operated by untrained users.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The file instructs users to supply Twitter and casino API credentials but provides no guidance on secure storage, least-privilege use, rotation, or the consequences of exposing betting activity and account access. In this context, mishandled tokens could let an attacker post from the victim's Twitter account, read or abuse casino account functionality, and facilitate unauthorized gambling operations.

External Transmission

Medium
Category
Data Exfiltration
Content
return requests.post(f"{API_BASE}/register", json={"name": "twitter-casino-bot", "ref": "ref_27fcab61"}).json()

def place_bet(game, amount, **kwargs):
    return requests.post(f"{API_BASE}/bet", headers=HEADERS, json={"game": game, "amount": amount, **kwargs}).json()

def get_balance():
    return requests.get(f"{API_BASE}/balance", headers=HEADERS).json()
Confidence
92% confidence
Finding
The place_bet() function sends authenticated betting instructions to an external gambling API, causing real financial actions based on local code paths and untrusted social-media input. In this skill context, external transmission is more dangerous than usual because the outbound request is not just data sharing—it can spend funds automatically, repeatedly, and without safeguards such as authorization checks, rate limits, or spending caps.

External Transmission

Medium
Category
Data Exfiltration
Content
# Register agent
read -p "Bot name: " BOT_NAME
echo "Registering agent..."
RESPONSE=$(curl -s -X POST https://agent.rollhub.com/api/v1/register \
  -H "Content-Type: application/json" \
  -d "{\"name\": \"$BOT_NAME\", \"ref\": \"ref_27fcab61\"}")
echo "Registration response: $RESPONSE"
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Low
Confidence
89% confidence
Finding
This shell script performs an outbound HTTP POST to a third-party endpoint containing user-supplied data, but the user is not clearly warned before transmission about what data is being sent or that registration occurs over the network. While the script prints "Registering agent...", that is only a status message and does not disclose the privacy-impacting action in a meaningful way.