Back to skill

Security audit

Discord Hub Builder

Security checks for vulnerabilities and agentic risk

Overview

The skill is purpose-aligned for building a Discord hub, but it needs Review because it can make persistent server changes with a bot token while overstating permission setup and handling the token unsafely.

Install only if you are comfortable giving the script a Discord bot token with server-management permissions. Use a test or empty guild first, verify the guild ID, avoid passing the token on the command line, rotate the token if it has been exposed in shell history or logs, and manually verify channel permissions before putting sensitive agent outputs or personal content in the server.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/build_hub.py:167
Finding
Discord Bot Token Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/build_hub.py:167-170`; documented invocation in `SKILL.md:38-48` **Vulnerability Type**: Credential exposure through process arguments and shell history **Risk Level**: Medium ### Vulnerable Code ```python parser.add_argument("--token", required=True, help="Discord bot token") parser.add_argument("--guild", required=True, help="Guild (server) ID") parser.add_argument("--dry-run", action="store_true", help="Preview without creating") args = parser.parse_args() build_hub(args.token, args.guild, args.dry_run) ``` The documented commands reinforce this unsafe credential-handling method: ```bash python3 scripts/build_hub.py --token BOT_TOKEN --guild GUILD_ID --dry-run ``` ```bash python3 scripts/build_hub.py --token BOT_TOKEN --guild GUILD_ID ``` ### Technical Analysis The Skill requires users to provide a Discord bot token as a command-line argument. Command-line arguments are not an appropriate channel for long-lived credentials because they may be exposed through: - Shell command history. - Process inspection interfaces and monitoring tools. - Terminal session capture. - CI/CD job logs or command tracing. - Diagnostic and endpoint-management software that records process arguments. The token is an administrative credential used with permissions including channel management, role management, message sending, and message pinning. Although the token is sent only to Discord's hardcoded official HTTPS API, its local handling creates an avoidable disclosure risk. ### Attack Path 1. A user follows `SKILL.md` and invokes the script with `--token BOT_TOKEN`. 2. The complete command is retained in shell history, captured by logging, or temporarily visible through process inspection. 3. An attacker with access to that local information obtains the bot token. 4. The attacker sends authenticated requests to the Discord REST API as the bot. 5. The attacker exercises whichever permissions have been assigne ...[truncated 658 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `--token` command-line argument. 2. Read the token from a protected environment variable or operating-system secret store. 3. Alternatively, request it using `getpass.getpass()` so it is not echoed or retained in shell history. 4. Ensure CI/CD systems inject the credential through masked secret variables rather than command text. 5. Avoid printing, logging, or including the token in exception messages. 6. Update `SKILL.md` to show a safe invocation pattern, for example: ```python import os import getpass token = os.environ.get("DISCORD_BOT_TOKEN") if not token: token = getpass.getpass("Discord bot token: ") ``` ```bash export DISCORD_BOT_TOKEN='...' python3 scripts/build_hub.py --guild GUILD_ID --dry-run ``` 7. Advise users who have already supplied the token on the command line to clear relevant history and logs and rotate the token through the Discord developer portal. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/build_hub.py:48
Finding
Dry-Run Mode Performs an Undisclosed Authenticated Network Request<![CDATA[ ## Vulnerability Details **File Location**: `scripts/build_hub.py:48-62`; dry-run instructions in `SKILL.md:38-42` **Vulnerability Type**: Unexpected credential transmission during purported preview mode **Risk Level**: Low ### Vulnerable Code ```python existing_roles = api("GET", f"/guilds/{guild_id}/roles", token) or [] existing_names = {r["name"]: r["id"] for r in existing_roles} for name, opts in roles.items(): if name in existing_names: role_ids[name] = existing_names[name] print(f" ✓ {name} (exists)") elif not dry_run: r = api("POST", f"/guilds/{guild_id}/roles", token, {"name": name, **opts}) if r: role_ids[name] = r["id"] print(f" + {name} created (id={r['id']})") else: print(f" [dry] Would create role: {name}") ``` The `api()` function adds the credential to every request: ```python headers={ "Authorization": f"Bot {token}", "Content-Type": "application/json", "User-Agent": "OpenClaw-Discord-Hub-Builder/1.0", }, ``` ### Technical Analysis The role-list request executes before the code checks `dry_run`. Consequently, the mandatory dry-run command is not an offline preview: it sends an authenticated request to Discord and reads live guild role metadata. The request is directed only to the hardcoded official endpoint `https://discord.com/api/v10`, and reading existing roles supports the role-deduplication preview. There is no evidence of token exfiltration to an unrelated host. Nevertheless, the implementation violates the conventional expectation that a dry run avoids external effects and unnecessarily requires credential transmission when a purely static structure preview would be sufficient. The primary risk is unexpected credential use and exposure through local proxies, enterprise TLS inspection, or request instrumentation. This is lower risk than sending the token to an untrusted endpoint because HTTPS and a hardcoded official Discord host ar ...[truncated 1197 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make dry-run mode fully offline by checking `dry_run` before the role-list API request. 2. Generate a static preview from `STRUCTURE` and the role definitions without requiring a bot token. 3. Require `--token` only for live execution if dry-run no longer accesses Discord. 4. If existing-resource discovery is intentionally retained, rename the mode to `--authenticated-preview` or clearly state that it performs read-only Discord API requests. 5. Obtain explicit user consent before making the authenticated request. 6. Consider separate modes: - `--dry-run`: entirely offline static preview. - `--inspect`: authenticated read-only inspection of the target guild. - Default live mode: authenticated server modification. 7. Continue using the hardcoded HTTPS Discord endpoint and ensure redirects cannot cause the `Authorization` header to be forwarded to an unrelated host. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The skill claims it builds a complete Discord server including permissions, but the documented behavior admits that channel-specific permissions and access controls are not actually implemented. This mismatch can cause users to deploy channels they believe are owner-only or read-only when they are not, leading to unintended exposure or misuse of operational channels.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill explicitly performs networked actions against the Discord REST API and requires a bot token, but it declares no tool scope or allowed-tools restrictions. Missing scope declarations weaken policy enforcement and reviewability, making it easier for an agent runtime to invoke network-capable behavior without clear authorization boundaries.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This code performs outbound HTTP requests authenticated with a Discord bot token and sends guild structure data to Discord's API. While the script's purpose is to build a Discord server, the file itself provides no inline warning, confirmation, or comment reminding users that credentials and server metadata will be transmitted to an external service.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The skill claims to set up a Discord command center with roles, permissions, and owner-only/restricted areas, but it never creates permission overwrites or assigns roles to enforce those controls. As a result, channels labeled as owner-only or read-only are created with default server permissions, which can expose sensitive agent outputs or allow unauthorized users to post in supposedly restricted channels.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The script performs bulk creation of roles, categories, channels, messages, and pins immediately when run without a confirmation gate. In a high-privilege Discord administration context, a mistyped guild ID, accidental execution, or misuse by another operator can rapidly alter a production server in ways that are disruptive and difficult to clean up.

Intent-Code Divergence

Medium
Confidence
99% confidence
Finding
Channel metadata such as readonly_humans, owner_only_send, and topics like 'Owner only' imply access restrictions, but these flags are only descriptive and are never enforced in API calls. This creates a dangerous mismatch between operator expectations and actual Discord ACLs, increasing the chance of sensitive content being visible or writable by unintended members.

Excessive Permissions

Low
Category
Privilege Escalation
Content
Before running, confirm the user has:

1. **A Discord bot** — created at https://discord.com/developers/applications
2. **Bot permissions:** `Manage Channels`, `Manage Roles`, `Send Messages`, `Manage Messages` (for pinning)
3. **Bot invited to the server** — use OAuth2 URL with `bot` scope + above permissions
4. **Guild ID** — right-click server name → Copy Server ID (Developer Mode must be on)
5. **Bot token** — from the Bot tab in developer portal
Confidence
80% confidence
Finding
Skill requests more permissions than appear necessary for its stated functionality. Review if elevated access is justified.

Static analysis

No suspicious patterns detected.