Back to skill

Security audit

CDISC Library API Skill

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate CDISC API helper, but it needs review because its credential loading can pick up and send an unrelated API key from a shared local file.

Install only if you are comfortable with it contacting the CDISC API and caching responses locally. Prefer setting CDISC_API_KEY through your environment or a secret manager, avoid putting keys in a shared or committed TOOLS.md, and run exports from a directory where accidental overwrites are not harmful.

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
cdisc_client.py:58
Finding
Overbroad Credential Discovery Can Disclose an Unrelated API Key<![CDATA[ ## Vulnerability Details **File Location**: `cdisc_client.py:58-79`, with credential transmission at `cdisc_client.py:47-52` and `cdisc_client.py:153` **Vulnerability Type**: Overbroad credential selection and unintended secret disclosure **Risk Level**: High ### Vulnerable Code ```python def _load_api_key(self) -> Optional[str]: """从环境变量或 TOOLS.md 加载 API Key""" # 优先环境变量 if os.getenv("CDISC_API_KEY"): return os.getenv("CDISC_API_KEY") # 尝试从 TOOLS.md 读取 tools_path = Path(__file__).parent.parent.parent / "TOOLS.md" if tools_path.exists(): content = tools_path.read_text(encoding="utf-8") for line in content.split("\n"): # 支持格式:**API Key**: `xxx` 或 - API Key: xxx if "API Key" in line and "`" in line: # 提取反引号中的内容 import re match = re.search(r'`([a-zA-Z0-9]{32,})`', line) if match: return match.group(1) elif "API Key" in line and ":" in line: key = line.split(":", 1)[1].strip().strip("`'\"") if key and len(key) >= 32: return key return None ``` The selected value is installed as the API credential and transmitted to CDISC: ```python self.headers = { "api-key": self.api_key, "Accept": "application/json" } self.session = requests.Session() self.session.headers.update(self.headers) ``` ```python response = self.session.get(url, params=params, timeout=30) ``` ### Technical Analysis The fallback parser scans a shared `TOOLS.md` file and accepts the first line that merely contains the generic text `API Key`. It does not verify that the line belongs to a dedicated `CDISC API` section and does not reject ambiguous or duplicate credential entries. Consequently, a key belonging to another service can be selected if it appears before the intended CDISC credential and satisfies the minimum length or regular-expression requi ...[truncated 1666 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer the dedicated `CDISC_API_KEY` environment variable or a CDISC-specific configuration file. 2. If `TOOLS.md` support is retained, parse only an exact `## CDISC API` section and an exact `API Key` field within that section. 3. Reject missing, duplicate, or ambiguous CDISC credential entries instead of selecting the first generic match. 4. Resolve the documented configuration path explicitly and verify that the implementation and documentation reference the same file. 5. Avoid scanning unrelated configuration sections for secrets. 6. Add tests covering multiple API keys, duplicate CDISC sections, malformed entries, and configuration-path resolution. 7. Document the external destination to which the credential will be sent and prioritize the environment variable over shared plaintext configuration. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
commands/export.py:19
Finding
Unsanitized Export Identifiers Permit Unsafe File Placement and Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `commands/export.py:19-37` and `commands/export.py:58-80` **Vulnerability Type**: Unsafe file path construction and predictable file overwrite **Risk Level**: Medium ### Vulnerable Code ```python def export_json(data, filename): """导出为 JSON""" output_path = Path(filename) with open(output_path, "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) return output_path def export_csv(rows, filename, fieldnames=None): """导出为 CSV""" if not rows: return None output_path = Path(filename) if not fieldnames: fieldnames = list(rows[0].keys()) with open(output_path, "w", encoding="utf-8-sig", newline="") as f: writer = csv.DictWriter(f, fieldnames=fieldnames, extrasaction="ignore") writer.writeheader() writer.writerows(rows) return output_path ``` ```python export_type = sys.argv[1].lower() resource_id = sys.argv[2] version = sys.argv[3] if len(sys.argv) > 3 and not sys.argv[3].startswith("--") else None output_format = "json" # 解析格式参数 for arg in sys.argv: if arg.startswith("--format="): output_format = arg.split("=")[1].lower() try: client = CDISCClient() except ValueError as e: print(f"❌ 错误:{e}") return try: data = None rows = [] filename = f"cdisc_{export_type}_{resource_id}" if version: filename += f"_{version}" ``` ### Technical Analysis The export destination is derived from command-line values without validating `resource_id` or `version` against the documented identifier formats. The resulting string is passed directly to `Path` and opened in write mode. Path separators and traversal components in these values can affect destination resolution when corresponding intermediate paths exist. In addition, generated names are predictable and the code follows existing symbolic links. Opening the destination with mode `"w"` silently truncate ...[truncated 1782 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate `resource_id` and `version` with strict allowlists matching the documented CDISC identifier formats. 2. Reject `/`, `\`, `..`, null bytes, control characters, and platform-specific path separators in filename components. 3. Write all exports beneath a dedicated directory selected by the application or explicitly supplied by the user. 4. Resolve both the export directory and candidate destination, then verify that the destination remains inside the approved directory. 5. Refuse to follow symbolic links. Where supported, use secure open flags such as `O_NOFOLLOW`. 6. Use exclusive creation by default, or require explicit overwrite confirmation before replacing an existing file. 7. Generate temporary output securely and atomically rename it after successful serialization. 8. Normalize the requested format through a fixed allowlist before adding the extension. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
Findings (33)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The documented purpose is a read-oriented API query skill, but the behavior includes local cache inspection, cache clearing, directory deletion/recreation, and file output. This mismatch can mislead users and reviewers into authorizing a skill they believe is query-only, when it actually performs state-changing filesystem operations that can delete or overwrite local data.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The README instructs users to place an API key into a repository-adjacent markdown file, but gives no guidance about secret handling, access control, or avoiding commits. This creates a realistic risk of credential exposure through source control, file sharing, screenshots, backups, or accidental disclosure, especially because the instructions normalize storing the key in plaintext.

External Transmission

Medium
Category
Data Exfiltration
Content
- **API Key**: `你的 API Key`
```

获取 Key: https://api.developer.library.cdisc.org/profile

### 2. 测试连接
Confidence
50% 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 Key**: `你的 API Key`
```

获取 Key: https://api.developer.library.cdisc.org/profile

### 2. 测试连接
Confidence
50% 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 Key**: `你的 API Key`
```

获取 Key: https://api.developer.library.cdisc.org/profile

### 2. 测试连接
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill advertises capabilities that imply network, environment-variable, and filesystem use, but it does not declare any explicit tool scope or permissions boundary. This increases the chance that an agent runtime grants broader access than users expect, especially since the skill also documents cache, export, and batch features that touch local files and credentials.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
SQP-3 applies to all file types and covers language/locale policy violations. The user-facing instructions, command explanations, and operational notes are presented entirely in Chinese, and the file does not indicate that this locale restriction is optional, user-selected, or required for a region-specific compliance reason.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill instructs users to place an API key in TOOLS.md or an environment variable without warning about secret handling, storage exposure, or accidental logging. In agent ecosystems, credentials placed in config files can be leaked through repository commits, debugging output, or overly broad file access by other tools.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This Python file contains its docstrings and visible runtime messages entirely in Chinese, including installation guidance and API key error instructions. The file does not offer an alternative language or any opt-in mechanism, which is a natural-language locale policy issue under the language-choice rule.

External Transmission

Medium
Category
Data Exfiltration
Content
class CDISCClient:
    """CDISC Library API 客户端"""
    
    BASE_URL = "https://api.library.cdisc.org/api"
    CACHE_DIR = Path(__file__).parent / ".cache"
    CACHE_TTL = timedelta(hours=1)
    RATE_LIMIT_DELAY = 0.1  # 100ms
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The client reads an API key from a repository-local TOOLS.md file by traversing parent directories, which is broader file access than necessary for a network API wrapper. This can unintentionally ingest secrets from unrelated local files, normalize insecure secret storage in documentation, and expose credentials to other components or logs if the file is mishandled.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This Python file presents its CLI description, usage text, examples, status output, and error messages entirely in Chinese. The stated policy flags language/locale constraints when a skill forces a specific language without offering the user a choice or documenting a justified regional restriction.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This code file contains natural-language strings that present the skill exclusively in Chinese, starting with the top-level command description. The policy requires flagging language or locale constraints when the skill forces a specific language without user opt-in or a documented justification.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The docstring and usage/help text are entirely in Chinese, which imposes a specific language on users. Under the stated policy, locale or language constraints should offer user opt-in or be clearly documented as region-specific; this file does neither.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This Python file emits its usage/help text entirely in Chinese, including the command description and error/help messages. Under the policy for natural-language violations, forcing a specific language without user opt-in is a locale-policy issue unless the restriction is clearly documented and justified.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The docstring and all user-facing messages are written only in Chinese, including usage instructions and errors. This imposes a specific language on all users without opt-in or any documented reason that the skill is intentionally region-specific, which matches the language/locale policy violation criteria.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The command description and all user-facing output strings are fixed in Chinese, which imposes a specific language on users without opt-in or alternative locale support. This is a natural-language policy concern because the skill does not document that it is intentionally Chinese-only or provide a language selection mechanism.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The module docstring states the skill purpose in Chinese, and the user-facing messages throughout the file are also hard-coded in Chinese. This creates a language/locale constraint without any user opt-in or justification, which matches the policy-violation category for forced language behavior.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The command description is written in Chinese, and the rest of the script emits only Chinese usage, error, and success messages. This imposes a specific language on users without opt-in or any indication that the skill is intentionally limited to a Chinese-speaking context.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This code's user-facing natural-language strings and usage description are entirely in Chinese, which effectively imposes a specific language on users. The file does not indicate that language selection is optional or that the skill is region-specific, so it conflicts with the language/locale choice policy.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The docstring, error messages, headings, descriptions, and usage hints are all hard-coded in Chinese. For a general-purpose CLI skill, this imposes a specific language on users without opt-in, which matches the language/locale policy violation criteria.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This Python file contains user-facing help and status messages exclusively in Chinese, including the command description and runtime output. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is clearly documented and justified.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The docstring and all CLI usage and error messages are presented in Chinese, which imposes a specific language on users. There is no indication that the skill is region-specific or that users can opt into another language, so this appears to violate the language/locale policy.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
This code file contains natural-language descriptions and user-facing messages exclusively in Chinese, including the module docstring and printed CLI output. Under the policy, forcing a specific language without user opt-in is a locale/language policy violation unless the constraint is clearly documented and justified.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The command description, usage text, and all user-facing messages are written only in Chinese, which imposes a specific language on users without opt-in. The policy explicitly calls out language or locale restrictions as violations unless the skill offers a choice or clearly documents a justified locale-specific scope.

Static analysis

No suspicious patterns detected.