Back to skill

Security audit

SwanLab Reader

Security checks for vulnerabilities and agentic risk

Overview

This skill is a SwanLab data reader whose credential use and local key storage are disclosed, with a local secret-handling weakness users should understand.

Install only if you are comfortable granting the skill access to SwanLab data available to your API key. Prefer setting the key via a protected environment or manually securing ~/.config/swanlab/key, and avoid typing secrets directly into commands that may be saved in shell history.

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

T09 · Insecure Skill Coding Practices

Warning
Location
swanlab_reader.py:61
Finding

SwanLab API Key Exposed Through Process Arguments and Insecure Plaintext Storage

Content
View full analysis

Vulnerability Details

File Location: swanlab_reader.py:61-64, swanlab_reader.py:352-357, and SKILL.md:17-20
Vulnerability Type: API credential exposure through command-line arguments and insufficient file permission enforcement
Risk Level: Medium

Vulnerable Code

python
def save_api_key(key):
    os.makedirs(CONFIG_DIR, exist_ok=True)
    with open(CONFIG_KEY_FILE, "w") as f:
        f.write(key)
python
if action == "set-key":
    if len(sys.argv) < 3:
        print("用法: swanlab set-key <key>")
        sys.exit(1)
    save_api_key(sys.argv[2])
    print("Key 已保存到 ~/.config/swanlab/key")
    sys.exit(0)

The documented invocation also instructs users to place the secret directly in a command-line argument:

bash
uv run python skills/swanlab-reader/swanlab_reader.py set-key <your-key>

Technical Analysis

The set-key command obtains the SwanLab API key from sys.argv[2]. Command-line arguments may be recorded in shell history and can be exposed through process-inspection facilities while the command is running. This unnecessarily expands the number of local components that may observe the credential.

The key is subsequently written in plaintext to ~/.config/swanlab/key. Plaintext storage is consistent with the declared credential mechanism, but the implementation does not explicitly enforce owner-only permissions. Both the configuration directory and key file inherit permissions from the process umask. Under an insufficiently restrictive umask, other local accounts or processes may be able to read the key.

The code does not contain evidence of deliberate credential exfiltration. Network requests attach the key as a Bearer token only to the fixed HTTPS origin https://swanlab.cn, which is necessary for the Skill's declared private-project access. The vulnerability instead arises from avoidable local exposure before the key is used.

Attack Path

  1. A user follows the documented command ...[truncated 1402 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove secrets from command-line arguments

    • Prompt interactively with getpass.getpass() so the key is not echoed or placed in process arguments.
    • Alternatively, accept the key through protected standard input or a dedicated secret manager.
    • Retain environment-variable support only where users understand that environment values may be visible to child processes or diagnostic tooling.
  2. Enforce owner-only filesystem permissions

    • Create ~/.config/swanlab with mode 0700.
    • Create the key file atomically with mode 0600, rather than relying on the user's umask.
    • Verify and correct permissions on existing directories and key files before reading them.
    • Reject symbolic-link targets or use safe open flags to prevent writing through an attacker-controlled link.
  3. Use atomic credential writes

    • Write to an owner-only temporary file in the same directory, flush it, and atomically replace the destination.
    • Ensure failures cannot leave a partially written or unexpectedly permissioned credential file.
  4. Update the documentation

    • Replace set-key <your-key> with an interactive set-key workflow.
    • Warn users not to place API keys in shell history, scripts, logs, or copied terminal output.
    • Recommend revoking and rotating any key suspected of exposure.

A hardened interface could use set-key without a secret argument, collect the key through getpass.getpass("SwanLab API key: "), create the configuration directory with 0700, and save the credential to an atomically created 0600 file.

Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared purpose says the skill reads SwanLab experiment data from a provided run URL, but the documented behavior is broader: it can persist API keys locally, enumerate project runs, compare multiple runs, and use authenticated access. This mismatch is dangerous because users and policy systems may grant trust to a seemingly narrow read-only skill while it actually expands data access scope and performs local state changes.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill declares capabilities that involve reading environment variables, writing a local credential file, and making network requests, but it does not declare any tool scope or permission boundaries. This is dangerous because an agent runtime or reviewer may authorize the skill based on incomplete metadata, leading to unintended access to secrets, filesystem locations, or external services.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest description and all user-facing instructions are written in Chinese, which effectively imposes a specific language on users. There is no indication that the skill supports language choice, user opt-in, or that the Chinese-only constraint is required for a region-specific purpose.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This Python skill includes natural-language command descriptions in Chinese in the module docstring, and the rest of the CLI messages continue that pattern. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is explicitly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The code emits Chinese-only runtime messages such as parse errors and usage text, and similar strings appear throughout the CLI. Because the skill does not offer a language choice or justify a Chinese-only scope, this creates an organizational language/locale policy issue.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest describes a read-oriented skill used when a user sends a SwanLab run URL, which implies fetching and presenting experiment data. However, the CLI includes a credential-management path that writes an API key into ~/.config/swanlab/key, which goes beyond reading experiment data and introduces local state mutation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The stated purpose is to read SwanLab experiment data when given a run URL. Accessing SWANLAB_KEY/SWANLAB_API_KEY and ~/.config/swanlab/key may be practical for authentication, but this credential-discovery behavior is not reflected in the manifest's narrowly phrased description and expands the skill's access to local sensitive sources.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.