Back to skill

Security audit

科研工作区 (research-ops)

Security checks for vulnerabilities and agentic risk

Overview

This research-workspace skill mostly matches its stated project-organization purpose, but it also ships a sensitive credential vault with keyring access and optional command hooks that are not clearly scoped in the main skill instructions.

Install only if you are comfortable with this skill including a general-purpose credential vault. Before using creds.py, review where it stores the master key, avoid adding hooks.json unless you fully trust every command in it, and do not store sensitive credentials unless this behavior is explicitly intended for your workflow.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (59)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

声明描述的是科研项目工作区组织方法与相关脚本,关注项目目录、索引登记、跨工具映射和跨机同步纪律;而代码与这些功能没有实质关系。该代码的核心用途是管理加密凭据,并且还能在更新凭据后触发外部命令,这属于未声明且与所述科研项目工作区方法论明显不同的能力。两者的资源对象、主要用途和触发操作都不一致,因此应判定为明显不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is about cross-project research workspace organization rules and scripts involving local files, Zotero, Obsidian, Feishu, project indexing, sync procedures, and chat/buffer export workflows. The supplied code does not implement any of those behaviors. Instead, it implements a generic encrypted credential vault for storing secrets, including key management via environment variables, OS keyring, and local files. This is a materially different primary purpose and introduces undeclared sensitive-capability behavior around credential handling. Therefore the description does not accurately represent the code chunk.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file introduces a reusable credential vault CLI inside a skill whose declared purpose is research workspace methodology, not secret management. This mismatch expands the skill's privilege and behavior surface unexpectedly, increasing the chance that users or agents invoke secret-handling capabilities they did not anticipate or review.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation advertises automatic post-secret-update hooks, including syncing rotated credentials to external systems, despite the skill being framed as a research workspace utility. Embedding secret-propagation automation in this context is dangerous because it normalizes hidden side effects and creates a path for credentials to be copied to additional machines or services without strong controls.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

After set, the code matches the key against patterns in hooks.json and executes arbitrary command arrays via subprocess.run. This creates a direct arbitrary-code-execution mechanism tied to secret updates, which is especially sensitive because the commands run from the skill root and may access newly stored credentials or exfiltrate them.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file implements a general-purpose secret vault that is materially outside the declared scope of a research-ops skill focused on project organization. In an agent-skill context, adding hidden credential storage and retrieval expands capability to manage sensitive secrets without a clear user-justified need, increasing the risk of unauthorized secret persistence and later abuse by other skill logic.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

The documented design explicitly includes OS keyring, environment variables, and a local master-key file as credential sources, confirming that the skill has built-in credential-access and secret-management capability. In this skill context, that capability is unjustified and broadens the attack surface for secret discovery and persistence.

Content

Scanner excerpt · creds/vault.py (reported line 10)May include surrounding context.

python
- 主密钥来源(按优先级):
    1. 环境变量 OPENCODE_SKILL_MASTER_KEY     ← 跨机同步:各设备填同一个值(首选)
    2. 兼容旧环境变量 CAMPUS_MASTER_KEY / AIGW_MASTER_KEY / YUANBAO_MASTER_KEY
    3. OS keyring (service=opencode-skill, account=__master_key)
    4. 密钥文件 <skill>/runtime/vault/master.key (0600)
- 密文随 skill 文件夹同步到各设备;换机只需 export 同一个主密钥
- Scrypt 派生 Fernet key,每个保险箱文件独立 salt

Credential Access

High
Category
Privilege Escalation
Confidence
82% confidence
Finding

Defining keyring-related constants is part of enabling credential retrieval/storage through the host keyring. While a constant alone is not harmful, here it is used by active secret-access logic, so it contributes to an unnecessary credential-management capability in an unrelated skill.

Content

Scanner excerpt · creds/vault.py (reported line 36)May include surrounding context.

python
MASTER_KEY_ENV = "OPENCODE_SKILL_MASTER_KEY"
LEGACY_MASTER_KEY_ENVS = ("CAMPUS_MASTER_KEY", "AIGW_MASTER_KEY", "YUANBAO_MASTER_KEY")
KEYRING_SERVICE = "opencode-skill"
KEYRING_ACCOUNT = "__master_key"

SKILL_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

Credential Access

High
Category
Privilege Escalation
Confidence
82% confidence
Finding

This constant identifies the account used for host keyring access, supporting persistent retrieval of master secrets. In the surrounding implementation, it is part of a real credential-access pathway that is out of scope for the skill and increases the risk of secret handling abuse.

Content

Scanner excerpt · creds/vault.py (reported line 37)May include surrounding context.

python
MASTER_KEY_ENV = "OPENCODE_SKILL_MASTER_KEY"
LEGACY_MASTER_KEY_ENVS = ("CAMPUS_MASTER_KEY", "AIGW_MASTER_KEY", "YUANBAO_MASTER_KEY")
KEYRING_SERVICE = "opencode-skill"
KEYRING_ACCOUNT = "__master_key"

SKILL_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
RUNTIME_DIR = os.path.join(SKILL_ROOT, "runtime")

Credential Access

High
Category
Privilege Escalation
Confidence
80% confidence
Finding

The presence of keyring cache state supports repeated host keyring probing and use, which is part of the broader secret-access behavior implemented by the module. On its own this is minor, but in context it underpins unnecessary credential operations in a non-credential skill.

Content

Scanner excerpt · creds/vault.py (reported line 44)May include surrounding context.

python
VAULT_FILE = os.path.join(RUNTIME_DIR, "credentials.enc")
KEY_FILE = os.path.join(RUNTIME_DIR, "vault", "master.key")

_KEYRING_CACHE = None


class VaultLocked(Exception):

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

The _keyring_ok function actively tests host keyring usability, which is a form of credential-store interaction. In an agent setting, probing and using host secret stores without a manifest-declared need is risky because it expands the skill's ability to access or persist sensitive material.

Content

Scanner excerpt · creds/vault.py (reported line 53)May include surrounding context.

python
# ==================== 主密钥来源 ====================

def _keyring_ok():
    global _KEYRING_CACHE
    if _KEYRING_CACHE is not None:
        return _KEYRING_CACHE

Credential Access

High
Category
Privilege Escalation
Confidence
78% confidence
Finding

This line is part of the keyring capability check and contributes to the active use of the host credential store. The risk is contextual rather than line-specific: the skill is implementing secret-store access outside its declared purpose.

Content

Scanner excerpt · creds/vault.py (reported line 54)May include surrounding context.

python
# ==================== 主密钥来源 ====================

def _keyring_ok():
    global _KEYRING_CACHE
    if _KEYRING_CACHE is not None:
        return _KEYRING_CACHE
    try:

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Importing the keyring module enables direct interaction with the host credential store. In this file, that import is not incidental—it is used for secret probing, retrieval, and storage, which is overly sensitive functionality for the declared skill scope.

Content

Scanner excerpt · creds/vault.py (reported line 55)May include surrounding context.

python
def _keyring_ok():
    global _KEYRING_CACHE
    if _KEYRING_CACHE is not None:
        return _KEYRING_CACHE
    try:
        import keyring

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

Writing a probe value into the host keyring demonstrates active modification of the credential store, not merely passive checking. This is dangerous because it performs credential-store operations without clear user awareness and establishes the capability needed to store real secrets later.

Content

Scanner excerpt · creds/vault.py (reported line 56)May include surrounding context.

python
def _keyring_ok():
    global _KEYRING_CACHE
    if _KEYRING_CACHE is not None:
        return _KEYRING_CACHE
    try:
        import keyring
        keyring.set_password(KEYRING_SERVICE, "_probe", "1")

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Reading back the probe value confirms operational access to the host keyring. Although used for testing, it still exercises secret-store read capability that is unnecessary for a research-ops methodology skill.

Content

Scanner excerpt · creds/vault.py (reported line 58)May include surrounding context.

python
if _KEYRING_CACHE is not None:
        return _KEYRING_CACHE
    try:
        import keyring
        keyring.set_password(KEYRING_SERVICE, "_probe", "1")
        ok = keyring.get_password(KEYRING_SERVICE, "_probe") == "1"
        try:

Credential Access

High
Category
Privilege Escalation
Confidence
88% confidence
Finding

This finding overlaps the same keyring deletion operation and is substantively the same risk: the skill manipulates the host credential store without a justified need. The concern is capability scope expansion rather than line-level exploit complexity.

Content

Scanner excerpt · creds/vault.py (reported line 59)May include surrounding context.

python
return _KEYRING_CACHE
    try:
        import keyring
        keyring.set_password(KEYRING_SERVICE, "_probe", "1")
        ok = keyring.get_password(KEYRING_SERVICE, "_probe") == "1"
        try:
            keyring.delete_password(KEYRING_SERVICE, "_probe")

Credential Access

High
Category
Privilege Escalation
Confidence
88% confidence
Finding

This finding overlaps the same keyring deletion operation and is substantively the same risk: the skill manipulates the host credential store without a justified need. The concern is capability scope expansion rather than line-level exploit complexity.

Content

Scanner excerpt · creds/vault.py (reported line 59)May include surrounding context.

python
return _KEYRING_CACHE
    try:
        import keyring
        keyring.set_password(KEYRING_SERVICE, "_probe", "1")
        ok = keyring.get_password(KEYRING_SERVICE, "_probe") == "1"
        try:
            keyring.delete_password(KEYRING_SERVICE, "_probe")

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

This duplicate finding again reflects hidden error suppression around keyring cleanup, which can obscure persistent changes to the credential store. In a skill not meant to manage secrets, such hidden behavior is unnecessary and risky.

Content

Scanner excerpt · creds/vault.py (reported line 60)May include surrounding context.

python
try:
        import keyring
        keyring.set_password(KEYRING_SERVICE, "_probe", "1")
        ok = keyring.get_password(KEYRING_SERVICE, "_probe") == "1"
        try:
            keyring.delete_password(KEYRING_SERVICE, "_probe")
        except Exception:

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

This duplicate finding again reflects hidden error suppression around keyring cleanup, which can obscure persistent changes to the credential store. In a skill not meant to manage secrets, such hidden behavior is unnecessary and risky.

Content

Scanner excerpt · creds/vault.py (reported line 60)May include surrounding context.

python
try:
        import keyring
        keyring.set_password(KEYRING_SERVICE, "_probe", "1")
        ok = keyring.get_password(KEYRING_SERVICE, "_probe") == "1"
        try:
            keyring.delete_password(KEYRING_SERVICE, "_probe")
        except Exception:

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · creds/vault.py (reported line 62)May include surrounding context.

python
keyring.set_password(KEYRING_SERVICE, "_probe", "1")
        ok = keyring.get_password(KEYRING_SERVICE, "_probe") == "1"
        try:
            keyring.delete_password(KEYRING_SERVICE, "_probe")
        except Exception:
            pass
        _KEYRING_CACHE = ok

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · creds/vault.py (reported line 87)May include surrounding context.

python
keyring.set_password(KEYRING_SERVICE, "_probe", "1")
        ok = keyring.get_password(KEYRING_SERVICE, "_probe") == "1"
        try:
            keyring.delete_password(KEYRING_SERVICE, "_probe")
        except Exception:
            pass
        _KEYRING_CACHE = ok

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · creds/vault.py (reported line 118)May include surrounding context.

python
keyring.set_password(KEYRING_SERVICE, "_probe", "1")
        ok = keyring.get_password(KEYRING_SERVICE, "_probe") == "1"
        try:
            keyring.delete_password(KEYRING_SERVICE, "_probe")
        except Exception:
            pass
        _KEYRING_CACHE = ok

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · creds/vault.py (reported line 119)May include surrounding context.

python
keyring.set_password(KEYRING_SERVICE, "_probe", "1")
        ok = keyring.get_password(KEYRING_SERVICE, "_probe") == "1"
        try:
            keyring.delete_password(KEYRING_SERVICE, "_probe")
        except Exception:
            pass
        _KEYRING_CACHE = ok

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · creds/vault.py (reported line 137)May include surrounding context.

python
keyring.set_password(KEYRING_SERVICE, "_probe", "1")
        ok = keyring.get_password(KEYRING_SERVICE, "_probe") == "1"
        try:
            keyring.delete_password(KEYRING_SERVICE, "_probe")
        except Exception:
            pass
        _KEYRING_CACHE = ok

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · creds/vault.py (reported line 138)May include surrounding context.

python
keyring.set_password(KEYRING_SERVICE, "_probe", "1")
        ok = keyring.get_password(KEYRING_SERVICE, "_probe") == "1"
        try:
            keyring.delete_password(KEYRING_SERVICE, "_probe")
        except Exception:
            pass
        _KEYRING_CACHE = ok

Static analysis

No suspicious patterns detected.