Back to skill

Security audit

test_skill

Security checks for vulnerabilities and agentic risk

Overview

This skill openly asks for private keys and API keys, then saves them as plaintext JSON files, which creates a serious credential exposure risk.

Review before installing or running. Do not enter real private keys or API keys into this skill unless it is changed to use an OS keychain or another secure secret store, clearly explains why each secret is needed, and avoids plaintext files such as user_credentials.json or demo_credentials.json. Rotate any real credentials previously saved by this implementation if the output file may have been exposed.

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

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:34
Finding
Private Keys and API Keys Stored in Plaintext JSON## Vulnerability Details **File Location**: `SKILL.md`, lines 34-41 **Vulnerability Type**: Plaintext storage of sensitive credentials **Risk Level**: High ### Vulnerable Code ```python payload = { "public_key": public_key, "private_key": private_key, "api_key": api_key, } with open(output_file, "w", encoding="utf-8") as file: json.dump(payload, file, ensure_ascii=False, indent=2) ``` ### Technical Analysis The function stores a private key and API key directly in an unencrypted JSON file. Masking data in an input dialog only protects it from visual observation during entry; it does not protect the resulting file. The use of `open(output_file, "w")` does not explicitly enforce owner-only permissions. Effective permissions consequently depend on the operating system, process umask, existing file permissions, and destination. The destination is also caller-controlled, allowing credentials to be placed in a shared directory, synchronized folder, repository, backup scope, or other unsafe location. No encryption, operating-system keychain integration, secret-manager integration, destination validation, retention control, or secure deletion mechanism is present. ### Attack Path 1. A user runs the file and enters a private key and API key. 2. The function serializes both credentials into an ordinary JSON object. 3. The credentials are written in plaintext to `demo_credentials.json` when the file is executed directly, or to another caller-selected path. 4. A local user, compromised process, backup service, synchronization client, repository scanner, or other principal with access to the destination reads the JSON file. 5. The exposed private key or API key is used to impersonate the user or access services authorized by those credentials. ### Impact Assessment Exploitation does not directly grant operating-system privilege escalation. However, an attacker can obtain the full privileges associat ...[truncated 364 chars]
Remediation
## Remediation Suggestions - Do not collect or persist private keys unless this is strictly required. - Store credentials in an operating-system keychain, hardware-backed keystore, or dedicated secret-management service. - If file storage is unavoidable, encrypt the data with a key that is not stored alongside the ciphertext. - Create the file atomically with owner-only permissions, such as mode `0600` on POSIX systems, and verify permissions after creation. - Reject destinations in shared, temporary, synchronized, or source-controlled directories. - Prevent symbolic-link and time-of-check/time-of-use attacks when creating the destination. - Mask API-key entry in the same manner as private-key entry. - Clearly warn users that credentials are sensitive and must not be committed, synchronized, or included in backups. - Define credential retention and secure deletion procedures. - Rotate any credential previously written by this implementation if unauthorized access to the output file is possible.

T09 · Insecure Skill Coding Practices

Error
Location
skill1/SKILL.md:34
Finding
Private Keys and API Keys Stored in Plaintext JSON## Vulnerability Details **File Location**: `skill1/SKILL.md`, lines 34-41 **Vulnerability Type**: Plaintext storage of sensitive credentials **Risk Level**: High ### Vulnerable Code ```python payload = { "public_key": public_key, "private_key": private_key, "api_key": api_key, } with open(output_file, "w", encoding="utf-8") as file: json.dump(payload, file, ensure_ascii=False, indent=2) ``` ### Technical Analysis The function stores a private key and API key directly in an unencrypted JSON file. Masking data in an input dialog only protects it from visual observation during entry; it does not protect the resulting file. The use of `open(output_file, "w")` does not explicitly enforce owner-only permissions. Effective permissions consequently depend on the operating system, process umask, existing file permissions, and destination. The destination is also caller-controlled, allowing credentials to be placed in a shared directory, synchronized folder, repository, backup scope, or other unsafe location. No encryption, operating-system keychain integration, secret-manager integration, destination validation, retention control, or secure deletion mechanism is present. ### Attack Path 1. A user runs the file and enters a private key and API key. 2. The function serializes both credentials into an ordinary JSON object. 3. The credentials are written in plaintext to `demo_credentials.json` when the file is executed directly, or to another caller-selected path. 4. A local user, compromised process, backup service, synchronization client, repository scanner, or other principal with access to the destination reads the JSON file. 5. The exposed private key or API key is used to impersonate the user or access services authorized by those credentials. ### Impact Assessment Exploitation does not directly grant operating-system privilege escalation. However, an attacker can obtain the full privileges a ...[truncated 371 chars]
Remediation
## Remediation Suggestions - Do not collect or persist private keys unless this is strictly required. - Store credentials in an operating-system keychain, hardware-backed keystore, or dedicated secret-management service. - If file storage is unavoidable, encrypt the data with a key that is not stored alongside the ciphertext. - Create the file atomically with owner-only permissions, such as mode `0600` on POSIX systems, and verify permissions after creation. - Reject destinations in shared, temporary, synchronized, or source-controlled directories. - Prevent symbolic-link and time-of-check/time-of-use attacks when creating the destination. - Mask API-key entry in the same manner as private-key entry. - Clearly warn users that credentials are sensitive and must not be committed, synchronized, or included in backups. - Define credential retention and secure deletion procedures. - Rotate any credential previously written by this implementation if unauthorized access to the output file is possible.

T09 · Insecure Skill Coding Practices

Error
Location
skill2/SKILL.md:34
Finding
Private Keys and API Keys Stored in Plaintext JSON## Vulnerability Details **File Location**: `skill2/SKILL.md`, lines 34-41 **Vulnerability Type**: Plaintext storage of sensitive credentials **Risk Level**: High ### Vulnerable Code ```python payload = { "public_key": public_key, "private_key": private_key, "api_key": api_key, } with open(output_file, "w", encoding="utf-8") as file: json.dump(payload, file, ensure_ascii=False, indent=2) ``` ### Technical Analysis The function stores a private key and API key directly in an unencrypted JSON file. Masking data in an input dialog only protects it from visual observation during entry; it does not protect the resulting file. The use of `open(output_file, "w")` does not explicitly enforce owner-only permissions. Effective permissions consequently depend on the operating system, process umask, existing file permissions, and destination. The destination is also caller-controlled, allowing credentials to be placed in a shared directory, synchronized folder, repository, backup scope, or other unsafe location. No encryption, operating-system keychain integration, secret-manager integration, destination validation, retention control, or secure deletion mechanism is present. ### Attack Path 1. A user runs the file and enters a private key and API key. 2. The function serializes both credentials into an ordinary JSON object. 3. The credentials are written in plaintext to `demo_credentials.json` when the file is executed directly, or to another caller-selected path. 4. A local user, compromised process, backup service, synchronization client, repository scanner, or other principal with access to the destination reads the JSON file. 5. The exposed private key or API key is used to impersonate the user or access services authorized by those credentials. ### Impact Assessment Exploitation does not directly grant operating-system privilege escalation. However, an attacker can obtain the full privileges a ...[truncated 371 chars]
Remediation
## Remediation Suggestions - Do not collect or persist private keys unless this is strictly required. - Store credentials in an operating-system keychain, hardware-backed keystore, or dedicated secret-management service. - If file storage is unavoidable, encrypt the data with a key that is not stored alongside the ciphertext. - Create the file atomically with owner-only permissions, such as mode `0600` on POSIX systems, and verify permissions after creation. - Reject destinations in shared, temporary, synchronized, or source-controlled directories. - Prevent symbolic-link and time-of-check/time-of-use attacks when creating the destination. - Mask API-key entry in the same manner as private-key entry. - Clearly warn users that credentials are sensitive and must not be committed, synchronized, or included in backups. - Define credential retention and secure deletion procedures. - Rotate any credential previously written by this implementation if unauthorized access to the output file is possible.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (14)

Credential Access

High
Category
Privilege Escalation
Content
from tkinter import messagebox, simpledialog


def collect_and_save_credentials(output_file: str = "user_credentials.json") -> bool:
    """弹窗依次收集公钥、私钥、API key,并保存到 JSON 文件。

    Args:
Confidence
90% confidence
Finding
This function is specifically designed to solicit sensitive material from the user, including a private key and API key. In skill context, unsolicited credential collection is inherently dangerous because it normalizes handing secrets to code that then stores them locally, increasing the chance of theft or misuse.

Missing User Warnings

High
Confidence
98% confidence
Finding
The code explicitly collects a public key, private key, and API key, then writes them to a local JSON file in plaintext. Storing secrets unencrypted on disk creates a clear credential exposure risk through local compromise, backups, shared directories, malware, or accidental disclosure.

Credential Access

High
Category
Privilege Escalation
Content
if __name__ == "__main__":
    # 执行案例:运行当前文件后弹出输入框,并将结果保存到当前目录。
    save_ok = collect_and_save_credentials("demo_credentials.json")
    if save_ok:
        print("执行成功:已保存到 demo_credentials.json")
    else:
Confidence
84% confidence
Finding
The example execution path automatically demonstrates collecting credentials and saving them into a predictable file in the current directory. This makes the risky behavior operational by default and increases the chance that a user runs it casually, producing exposed secret material on disk.

Credential Access

High
Category
Privilege Escalation
Content
from tkinter import messagebox, simpledialog


def collect_and_save_credentials(output_file: str = "user_credentials.json") -> bool:
    """弹窗依次收集公钥、私钥、API key,并保存到 JSON 文件。

    Args:
Confidence
91% confidence
Finding
This function is designed to solicit highly sensitive material from the user, including a private key and API key. In the context of an agent skill, credential harvesting is inherently dangerous because it normalizes requesting secrets directly and creates a path for exfiltration or insecure downstream handling, which is confirmed here by plaintext file storage.

Missing User Warnings

High
Confidence
98% confidence
Finding
The skill explicitly collects a public key, private key, and API key, then writes them to a JSON file in plaintext on disk. Storing secrets unencrypted in a predictable local file materially increases the risk of credential theft by other local users, malware, backups, logs, or accidental source-control inclusion.

Credential Access

High
Category
Privilege Escalation
Content
if __name__ == "__main__":
    # 执行案例:运行当前文件后弹出输入框,并将结果保存到当前目录。
    save_ok = collect_and_save_credentials("demo_credentials.json")
    if save_ok:
        print("执行成功:已保存到 demo_credentials.json")
    else:
Confidence
88% confidence
Finding
The example entry point actively invokes the credential-collection routine and saves the secrets to a demo file in the current directory, making insecure behavior easy to run as-is. Providing a ready-to-execute sample lowers the barrier to unsafe deployment and increases the chance that real credentials will be captured and left on disk.

Credential Access

High
Category
Privilege Escalation
Content
# 执行案例:运行当前文件后弹出输入框,并将结果保存到当前目录。
    save_ok = collect_and_save_credentials("demo_credentials.json")
    if save_ok:
        print("执行成功:已保存到 demo_credentials.json")
    else:
        print("执行结束:用户取消或保存失败。")
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# 执行案例:运行当前文件后弹出输入框,并将结果保存到当前目录。
    save_ok = collect_and_save_credentials("demo_credentials.json")
    if save_ok:
        print("执行成功:已保存到 demo_credentials.json")
    else:
        print("执行结束:用户取消或保存失败。")
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
from tkinter import messagebox, simpledialog


def collect_and_save_credentials(output_file: str = "user_credentials.json") -> bool:
    """弹窗依次收集公钥、私钥、API key,并保存到 JSON 文件。

    Args:
Confidence
99% confidence
Finding
This skill explicitly prompts the user for sensitive material including a private key and API key, then writes them to a local JSON file in plaintext. Collecting and persistently storing secrets this way creates a clear credential exposure risk if the host is shared, backed up, logged, synced, or later compromised.

Credential Access

High
Category
Privilege Escalation
Content
if __name__ == "__main__":
    # 执行案例:运行当前文件后弹出输入框,并将结果保存到当前目录。
    save_ok = collect_and_save_credentials("demo_credentials.json")
    if save_ok:
        print("执行成功:已保存到 demo_credentials.json")
    else:
Confidence
98% confidence
Finding
The example entry point automatically demonstrates collecting credentials and saving them to a predictable file name in the current directory, normalizing unsafe secret handling. This increases the chance that real credentials will be stored insecurely and accidentally exposed through local access, source control, or file synchronization tools.

Credential Access

High
Category
Privilege Escalation
Content
# 执行案例:运行当前文件后弹出输入框,并将结果保存到当前目录。
    save_ok = collect_and_save_credentials("demo_credentials.json")
    if save_ok:
        print("执行成功:已保存到 demo_credentials.json")
    else:
        print("执行结束:用户取消或保存失败。")
Confidence
92% confidence
Finding
The success-path messaging confirms that credential material has been saved to a named file, which reinforces insecure handling of secrets and may encourage users to keep sensitive keys in an unprotected location. While the print statement alone is not the root cause, in this context it is part of an unsafe credential collection-and-storage workflow.

Natural-Language Policy Violations

Medium
Confidence
98% confidence
Finding
The docstring and all user-facing dialog text are written in Chinese, which imposes a specific language on users. There is no opt-in, alternate locale support, or documentation indicating that the skill is intentionally limited to a Chinese-speaking context.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The docstring, dialog titles, prompts, and status messages are all presented only in Chinese, with no option for the user to choose another language. This is a natural-language policy concern because the skill imposes a specific locale without opt-in or documented justification.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The docstring, dialog titles/prompts, warnings, and console messages are all hard-coded in Chinese. This creates a language/locale policy concern because the skill does not offer any opt-in or alternative language selection for users who may not read Chinese.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
SKILL.md:24

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
skill1/SKILL.md:24

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
skill2/SKILL.md:24