Back to skill

Security audit

Discord Project Manager

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent with its Discord project-management purpose, but it handles sensitive OpenClaw/Discord credentials in ways that could expose tokens or alter central agent configuration.

Install only if you trust this skill with your OpenClaw configuration and Discord bot authority. Before use, back up ~/.openclaw/openclaw.json, avoid running diagnostic commands that print raw config, restrict the bot to the minimum Discord permissions and guilds needed, and review/fix the config-file permission preservation and token redaction issues.

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

Error
Location
lib/config.py:80
Finding
OpenClaw Configuration Permissions Are Not Preserved During Atomic Replacement## Vulnerability Details **File Location**: `lib/config.py:80-104` **Vulnerability Type**: `T09: Insecure Skill Coding Practices` **Risk Level**: High ### Vulnerable Code ```python def _write_config_locked(self, config: Dict) -> str: """Write config with file locking and backup. Args: config: Config dict to write Returns: Backup file path """ backup_path = f"{self.CONFIG_PATH}.bak-{int(time.time())}" shutil.copy(self.CONFIG_PATH, backup_path) lock_fd = open(self.LOCK_PATH, 'w') try: fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB) # Write to temp file then rename (atomic) tmp_path = f"{self.CONFIG_PATH}.tmp" with open(tmp_path, 'w') as f: json.dump(config, f, indent=2, ensure_ascii=False) os.replace(tmp_path, self.CONFIG_PATH) finally: fcntl.flock(lock_fd, fcntl.LOCK_UN) lock_fd.close() return backup_path ``` ### Technical Analysis The temporary configuration file is created with Python's default `open(..., 'w')` behavior. Its permissions are consequently determined by the process umask instead of inheriting the restrictive permissions of the original `~/.openclaw/openclaw.json`. For example, under a common `022` umask, the temporary file may be created with mode `0644`. The subsequent `os.replace()` operation replaces the original configuration inode with this newly created file, so a configuration previously protected with mode `0600` can become readable by other local users. The OpenClaw configuration contains Discord bot tokens and may contain additional account credentials. This write path is reached by direct permission-removal operations and by the fallback configuration-patching path. The lock also does not address the permission issue because it only coordinates cooperating writers; it does not control the ...[truncated 1477 chars]
Remediation
## Remediation Suggestions - Preserve the original configuration's owner, group, and mode when replacing it. - Create the temporary file explicitly with mode `0600`, rather than relying on the current umask. For example, use `os.open()` with `O_WRONLY | O_CREAT | O_EXCL` and mode `0o600`, then wrap the descriptor with `os.fdopen()`. - Use a uniquely named temporary file in the same directory, such as one created through `tempfile.mkstemp(dir=config_directory)`. - Call `os.fchmod(fd, 0o600)` defensively before writing sensitive data. - Flush and call `os.fsync()` on the temporary file before replacement, then fsync the parent directory after `os.replace()`. - Acquire the lock before reading, copying, or modifying the configuration so the entire read-modify-write transaction is protected. - Verify after replacement that the resulting file has the expected owner and restrictive mode. Abort or correct the mode if it does not. - Apply equally restrictive permissions to the lock file and all timestamped backup files.

T09 · Insecure Skill Coding Practices

Warning
Location
lib/config.py:290
Finding
Diagnostic Commands Print Discord Bot Tokens in Plaintext## Vulnerability Details **File Location**: `lib/config.py:290-297` **Vulnerability Type**: `T09: Insecure Skill Coding Practices` **Risk Level**: Medium ### Vulnerable Code ```python if command == 'get': result = config.get() print(json.dumps(result, indent=2, ensure_ascii=False)) elif command == 'accounts': accounts = config.get_discord_accounts() print(json.dumps(accounts, indent=2, ensure_ascii=False)) ``` ### Technical Analysis The `get` command serializes and prints the complete OpenClaw configuration. The `accounts` command prints the complete Discord account structures. Based on the token-loading implementation elsewhere in the project, these structures can contain credentials under fields such as: ```text channels.discord.accounts.*.token channels.discord.token ``` Neither command performs recursive redaction or limits its output to non-sensitive metadata. Consequently, Discord bot tokens are written directly to standard output. Standard output is frequently captured by terminal logging, CI/CD systems, orchestration services, support bundles, agent transcripts, or shell redirection. This behavior also conflicts with the statement in `SKILL.md` that the bot token is never logged. ### Attack Path 1. A user, support operator, automation task, or agent invokes `lib/config.py get` or `lib/config.py accounts`. 2. The command loads the full configuration or Discord account configuration. 3. The unredacted JSON, including any Discord token fields, is printed to standard output. 4. Output is retained in a terminal transcript, CI log, monitoring system, redirected file, or agent conversation record. 5. A person or service with access to that retained output obtains the bot token. 6. The token is used to authenticate directly to Discord as the configured bot. ### Impact Assessment Exposure grants the observer the effective Discord identity and privileges of the affected bot unt ...[truncated 482 chars]
Remediation
## Remediation Suggestions - Do not print the complete configuration or complete account objects by default. - Implement recursive redaction before serialization. At minimum, redact keys such as `token`, `secret`, `password`, `apiKey`, `authorization`, and private-key fields. - Replace sensitive values with a constant marker such as `[REDACTED]`; do not reveal prefixes or suffixes unless operationally necessary. - Make diagnostic output an explicit allowlist of safe fields, such as account identifiers, guild identifiers, and channel identifiers. - If raw output is absolutely required for a narrowly defined administrative workflow, require an explicit high-friction option, display a warning, write only to a securely created `0600` file, and avoid stdout. - Add automated tests containing synthetic token fields at multiple nesting levels and verify that no credential value appears in command output. - Update the documentation so its token-handling guarantees accurately reflect the implemented behavior. - Rotate any bot token that may already have been captured in logs or transcripts.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill claims collaboration management features but appears to perform agent-registry file management and read ~/.openclaw/openclaw.json without accurately reflecting that behavior. In this context, undeclared access to a central OpenClaw configuration file is especially dangerous because it may expose account mappings, tokens, and channel permissions, and any writes can alter agent communication policy across the environment.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill claims collaboration management features but appears to perform agent-registry file management and read ~/.openclaw/openclaw.json without accurately reflecting that behavior. In this context, undeclared access to a central OpenClaw configuration file is especially dangerous because it may expose account mappings, tokens, and channel permissions, and any writes can alter agent communication policy across the environment.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill claims collaboration management features but appears to perform agent-registry file management and read ~/.openclaw/openclaw.json without accurately reflecting that behavior. In this context, undeclared access to a central OpenClaw configuration file is especially dangerous because it may expose account mappings, tokens, and channel permissions, and any writes can alter agent communication policy across the environment.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill claims collaboration management features but appears to perform agent-registry file management and read ~/.openclaw/openclaw.json without accurately reflecting that behavior. In this context, undeclared access to a central OpenClaw configuration file is especially dangerous because it may expose account mappings, tokens, and channel permissions, and any writes can alter agent communication policy across the environment.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill claims collaboration management features but appears to perform agent-registry file management and read ~/.openclaw/openclaw.json without accurately reflecting that behavior. In this context, undeclared access to a central OpenClaw configuration file is especially dangerous because it may expose account mappings, tokens, and channel permissions, and any writes can alter agent communication policy across the environment.

Context-Inappropriate Capability

High
Confidence
96% confidence
Finding
Host process discovery and signaling capability is unjustified by the declared skill purpose and materially increases risk. In the context of an agent skill, such capability can be repurposed for denial of service, interference with other workloads, or persistence-related runtime manipulation if the skill is invoked by a compromised agent or prompt flow.

Context Leakage

High
Category
Data Exfiltration
Content
forum_id, name, message
        )
        
        # Extract thread ID from response
        thread_id = thread_result.get('payload', {}).get('thread', {}).get('id')
        if not thread_id:
            raise ValueError(f"Failed to create thread: no thread id in response. Got: {thread_result}")
Confidence
91% confidence
Finding
The code raises an exception that includes the full raw `thread_result` object when the expected thread ID is missing. If that API response contains sensitive metadata, tokens, internal identifiers, or unexpected message content, it may be exposed through logs, CLI output, or upstream error handling. In a Discord project-management skill that coordinates multiple agents and permissions, leaking raw integration responses increases the chance of cross-context data disclosure.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill exposes capabilities for file read/write, shell/process control, and network access, but does not declare an explicit tool scope such as allowed tools. That weakens reviewability and enforcement, because consumers may trust the markdown description while the skill can modify local config, restart services, and interact with Discord over the network.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The documentation claims all config changes go through `openclaw config.patch`, but the implementation also directly edits config files and may restart the gateway. This mismatch is security-relevant because reviewers and operators may underestimate the skill's actual privileges and side effects, leading to unsafe deployment decisions.

Description-Behavior Mismatch

Medium
Confidence
90% confidence
Finding
The helper includes broad gateway/process management logic in a skill described as Discord collaboration infrastructure. This scope expansion increases blast radius: a feature intended to manage channel permissions can also alter host configuration state and influence service lifecycle behavior.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
['pgrep', '-f', 'openclaw.*gateway'],
            ]
            for cmd in patterns:
                result = subprocess.run(
                    cmd, capture_output=True, text=True, timeout=5
                )
                if result.returncode == 0 and result.stdout.strip():
Confidence
93% confidence
Finding
Although this is not shell injection, the subprocess is used for host process discovery via `pgrep -f`, followed by signaling matching PIDs. Pattern-based process discovery and subsequent signaling can affect unintended processes and grants this skill capability to enumerate and control host processes beyond Discord channel management.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# Last resort: openclaw gateway restart
        try:
            result = subprocess.run(
                ['openclaw', 'gateway', 'restart'],
                capture_output=True, text=True, timeout=15
            )
Confidence
84% confidence
Finding
This code can invoke `openclaw gateway restart`, which gives the skill direct host-level process control outside its stated Discord project-management purpose. If an untrusted or over-privileged caller can trigger this path, they can cause service disruption or manipulate the agent runtime by restarting the gateway.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
"""
        patch_json = json.dumps(patch)
        
        result = subprocess.run(
            ['openclaw', 'config.patch', '--raw', patch_json, '--note', note],
            capture_output=True,
            text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The skill reads a Discord bot token from the local OpenClaw configuration without requiring explicit user consent at the point of use. Accessing local credentials expands the skill's privilege boundary and enables authenticated remote actions as the bot, which is more sensitive than a generic project-management helper needs unless clearly disclosed and scoped.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
Silently loading a Discord bot token from local configuration is a security-relevant side effect because it consumes stored credentials without notifying the user. In this skill context, that makes the agent capable of authenticated Discord operations under the user's environment, increasing the blast radius if the skill is invoked unexpectedly or abused.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
This function performs outbound authenticated API calls that create Discord channels, causing persistent remote side effects without any visible warning or confirmation mechanism. Because the skill is for project coordination, channel creation is contextually related, but automatic remote mutation still warrants disclosure and approval to prevent accidental or unauthorized changes.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
cmd.extend(['-m', message])
        
        try:
            result = subprocess.run(
                cmd,
                capture_output=True,
                text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill sends messages to Discord via an external CLI without warning the user that provided content will be transmitted off-host and posted remotely. In a multi-agent collaboration setting, this can leak sensitive prompts, internal data, or unintended content if invocation is implicit or manipulated.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
]
        
        try:
            result = subprocess.run(
                cmd,
                capture_output=True,
                text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Medium
Confidence
76% confidence
Finding
The create operation transmits guild and channel metadata to Discord via a REST API call. While the function name implies creation, the surrounding CLI help and docstrings do not explicitly warn users that invoking this command performs a live network action against Discord.

Missing User Warnings

Medium
Confidence
83% confidence
Finding
This code writes to the registry as a side effect of creating a forum channel, and similar save operations recur elsewhere in the file. Although there are status prints after the fact, there is no confirmation prompt or explicit warning that local configuration/registry data will be modified before the write occurs.

Context-Inappropriate Capability

Low
Confidence
75% confidence
Finding
The manifest presents the skill as Discord project-management infrastructure, but these methods invoke an external command-line tool via subprocess to create threads and send messages. Launching subprocesses is a broader host-execution capability that is not implied by the manifest's functional description and is sensitive from an intent-auditing perspective.

Context-Inappropriate Capability

Low
Confidence
82% confidence
Finding
The skill is described as Discord project collaboration infrastructure managing channels, threads, permissions, and mention mode. This file additionally reaches into a user-scoped OpenClaw config at ~/.openclaw/openclaw.json to derive settings, which is a local file access capability not implied by the manifest's Discord-management purpose.

Static analysis

No suspicious patterns detected.