Back to skill

Security audit

project-assistant

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent project-analysis assistant, but it has risky file-access and credential-handling behavior that should be reviewed before installation.

Install only if you are comfortable with a project assistant that writes .claude state, scans project configuration and environment files, and stores Feishu tokens in a local JSON file. Avoid using it on untrusted repositories or projects containing secrets until path containment, secret redaction, and opt-in secret scanning are fixed.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/qa_doc_manager.py:348
Finding

Arbitrary File Read Through the Q&A Document Retrieval Command

Content
View full analysis
Optional[str]: """Read Q&A document content.""" full_path = os.path.join(project_dir, ".claude", doc_path) if os.path.exists(full_path): try: with open(full_path, 'r', encoding='utf-8') as f: return f.read() except: pass return None ``` The function is directly reachable through the command-line interface: ```python elif command == "get": if len(sys.argv) < 4: print("Usage: qa_doc_manager.py get ") sys.exit(1) content = get_qa_doc_content(project_dir, sys.argv[3]) if content: print(content) else: print(json.dumps({"error": "Document does not exist"})) ``` ### Technical Analysis The `doc_path` argument comes directly from `sys.argv[3]` and is passed to `os.path.join()` without validation or canonical containment checking. An attacker can use either of the following path behaviors: 1. A path containing `../` components can escape the intended `/.claude` directory. 2. On supported platforms, an absolute `doc_path` causes `os.path.join()` to discard the preceding project path components. The code only verifies that the resulting path exists. It does not verify that the canonical path remains within the intended Q&A document directory. It then prints the complete file contents to standard output. ### Attack Path 1. An attacker or untrusted instruction causes the agent to invoke the Q&A `get` command with a crafted path. 2. The attacker supplies an absolute path or a traversal path, for example: ```bash python3 scripts/qa_doc_manager.py /target/project get /etc/passwd ``` or: ```bash python ...[truncated 995 chars]
Remediation
View remediation
Optional[str]: qa_root = ( Path(project_dir).resolve() / ".claude" / "docs" / "qa" ).resolve() supplied = Path(doc_path) if supplied.is_absolute(): return None candidate = (Path(project_dir).resolve() / ".claude" / supplied).resolve() try: candidate.relative_to(qa_root) except ValueError: return None if not candidate.is_file() or candidate.is_symlink(): return None return candidate.read_text(encoding="utf-8") ``` ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/qa_doc_manager.py:371
Finding

Arbitrary File Deletion Through a Poisoned Q&amp;A Index Entry

Content
View full analysis
Dict[str, Any]: """Load the index.""" index_path = get_index_path(project_dir) if os.path.exists(index_path): try: with open(index_path, 'r', encoding='utf-8') as f: return json.load(f) except: pass return DEFAULT_INDEX.copy() ``` The index-controlled path is later used for deletion: ```python def delete_qa_doc(project_dir: str, entry_id: str) -> Dict[str, Any]: """Delete a Q&A document.""" index = load_index(project_dir) for i, entry in enumerate(index["entries"]): if entry["id"] == entry_id: doc_path = os.path.join(project_dir, ".claude", entry["doc_path"]) if os.path.exists(doc_path): os.remove(doc_path) index["entries"].pop(i) save_index(project_dir, index) return {"success": True, "message": "Deleted"} return {"success": False, "error": "Not found"} ``` ### Technical Analysis The code treats `.claude/index/qa_index.json` as trusted state even though it may be present in an untrusted project or modified by another local process. The `doc_path` field is passed to `os.path.join()` and then to `os.remove()` without canonicalization or containment validation. A malicious index can specify: - An absolute path, which can replace the intended project prefix - A relative path containing `../`, which can escape the `.claude` directory - A path traversing a symlink to a location outside the project The deletion operation is destructive and executes with the full filesystem privileges of the agent process. ### Attack Path ...[truncated 1245 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/config_manager.py:96
Finding

Feishu Access Tokens Are Stored and Returned in Plaintext

Content
View full analysis
bool: """Save the configuration file.""" config_path = get_config_path(base_dir) try: config["updated_at"] = datetime.now().isoformat() if not config.get("created_at"): config["created_at"] = config["updated_at"] with open(config_path, 'w', encoding='utf-8') as f: json.dump(config, f, indent=2, ensure_ascii=False) return True except IOError as e: print(f"[Error] Failed to save configuration: {e}", file=sys.stderr) return False ``` Individual values are returned without redaction: ```python def get_value(base_dir: str, key: str) -> Dict[str, Any]: """Get an individual configuration value.""" config = load_config(base_dir) keys = key.split('.') value = config for k in keys: if isinstance(value, dict) and k in value: value = value[k] else: return {"success": False, "key": key, "error": f"Configuration does not exist: {key}"} return {"success": True, "key": key, "value": value} ``` All custom configuration is also returned by the display operation: ```python def show_all(base_dir: str) -> Dict[str, Any]: """Display all configuration.""" config = load_config(base_dir) result = {"config": {}} for key in ["workdir", "project_name", "build_command", "run_command", "test_command"]: result["config"][key] = config.get(key) if config.get("preferences") ...[truncated 2249 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/analyzers/env_scanner.py:125
Finding

Default Secret Reconnaissance Scans Sensitive Project Files Without Explicit Opt-In

Content
View full analysis
Dict[str, Any]: """Execute the scan.""" logger.info(f"Starting environment-variable scan: {self.project_dir}") self._scan_env_files() self._scan_source_files() if self.scan_secrets: self._scan_for_secrets() return self._generate_report() ``` Environment files are read and parsed: ```python def _scan_env_files(self) -> None: """Scan environment files.""" for pattern in self.ENV_FILE_PATTERNS: for env_file in self.project_dir.glob(pattern): self._parse_env_file(env_file) self.env_files.append(str(env_file.relative_to(self.project_dir))) def _parse_env_file(self, file_path: Path) -> None: """Parse an environment file.""" try: with open(file_path, 'r', encoding='utf-8', errors='ignore') as f: lines = f.readlines() rel_path = str(file_path.relative_to(self.project_dir)) for line_num, line in enumerate(lines, 1): line = line.strip() if not line or line.startswith('#'): continue match = re.match(r'^([A-Z_][A-Z0-9_]*)\s*=\s*(.*)$', line) if match: name = match.group(1) value = match.group(2).strip().strip('"').strip("'") ...[truncated 3396 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (138)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The manifest presents the skill as '智能分析' and project Q&A, but the documented workflow for historical Q&A search/create suggests a more constrained retrieval and persistence mechanism than the headline implies. Overstating capability is dangerous because it can lead users to trust incomplete or low-fidelity answers as if they were broad, current, and deeply reasoned project analysis.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The manifest presents the skill as '智能分析' and project Q&A, but the documented workflow for historical Q&A search/create suggests a more constrained retrieval and persistence mechanism than the headline implies. Overstating capability is dangerous because it can lead users to trust incomplete or low-fidelity answers as if they were broad, current, and deeply reasoned project analysis.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The manifest presents the skill as '智能分析' and project Q&A, but the documented workflow for historical Q&A search/create suggests a more constrained retrieval and persistence mechanism than the headline implies. Overstating capability is dangerous because it can lead users to trust incomplete or low-fidelity answers as if they were broad, current, and deeply reasoned project analysis.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The manifest presents the skill as '智能分析' and project Q&A, but the documented workflow for historical Q&A search/create suggests a more constrained retrieval and persistence mechanism than the headline implies. Overstating capability is dangerous because it can lead users to trust incomplete or low-fidelity answers as if they were broad, current, and deeply reasoned project analysis.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The manifest presents the skill as '智能分析' and project Q&A, but the documented workflow for historical Q&A search/create suggests a more constrained retrieval and persistence mechanism than the headline implies. Overstating capability is dangerous because it can lead users to trust incomplete or low-fidelity answers as if they were broad, current, and deeply reasoned project analysis.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The manifest presents the skill as '智能分析' and project Q&A, but the documented workflow for historical Q&A search/create suggests a more constrained retrieval and persistence mechanism than the headline implies. Overstating capability is dangerous because it can lead users to trust incomplete or low-fidelity answers as if they were broad, current, and deeply reasoned project analysis.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The manifest presents the skill as '智能分析' and project Q&A, but the documented workflow for historical Q&A search/create suggests a more constrained retrieval and persistence mechanism than the headline implies. Overstating capability is dangerous because it can lead users to trust incomplete or low-fidelity answers as if they were broad, current, and deeply reasoned project analysis.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The manifest presents the skill as '智能分析' and project Q&A, but the documented workflow for historical Q&A search/create suggests a more constrained retrieval and persistence mechanism than the headline implies. Overstating capability is dangerous because it can lead users to trust incomplete or low-fidelity answers as if they were broad, current, and deeply reasoned project analysis.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The manifest presents the skill as '智能分析' and project Q&A, but the documented workflow for historical Q&A search/create suggests a more constrained retrieval and persistence mechanism than the headline implies. Overstating capability is dangerous because it can lead users to trust incomplete or low-fidelity answers as if they were broad, current, and deeply reasoned project analysis.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The manifest presents the skill as '智能分析' and project Q&A, but the documented workflow for historical Q&A search/create suggests a more constrained retrieval and persistence mechanism than the headline implies. Overstating capability is dangerous because it can lead users to trust incomplete or low-fidelity answers as if they were broad, current, and deeply reasoned project analysis.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The manifest presents the skill as '智能分析' and project Q&A, but the documented workflow for historical Q&A search/create suggests a more constrained retrieval and persistence mechanism than the headline implies. Overstating capability is dangerous because it can lead users to trust incomplete or low-fidelity answers as if they were broad, current, and deeply reasoned project analysis.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The manifest presents the skill as '智能分析' and project Q&A, but the documented workflow for historical Q&A search/create suggests a more constrained retrieval and persistence mechanism than the headline implies. Overstating capability is dangerous because it can lead users to trust incomplete or low-fidelity answers as if they were broad, current, and deeply reasoned project analysis.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The manifest presents the skill as '智能分析' and project Q&A, but the documented workflow for historical Q&A search/create suggests a more constrained retrieval and persistence mechanism than the headline implies. Overstating capability is dangerous because it can lead users to trust incomplete or low-fidelity answers as if they were broad, current, and deeply reasoned project analysis.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The manifest presents the skill as '智能分析' and project Q&A, but the documented workflow for historical Q&A search/create suggests a more constrained retrieval and persistence mechanism than the headline implies. Overstating capability is dangerous because it can lead users to trust incomplete or low-fidelity answers as if they were broad, current, and deeply reasoned project analysis.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

Feishu integration is presented as a normal feature but lacks any privacy warning that project-derived content, metadata, or recommendations may leave the local environment or be prepared for external sharing. In a project-analysis skill, this is especially risky because analyzed files, Git history, and synthesized documentation can contain proprietary code, secrets, or internal architecture details.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

This line begins a set of patterns explicitly targeting .env files, which commonly store API keys, passwords, and tokens. In the context of a non-security-oriented assistant skill, adding logic to discover and parse these files creates credential-access capability that can expose sensitive configuration data.

Content

Scanner excerpt · scripts/analyzers/env_scanner.py (reported line 75)May include surrounding context.

python
'smtp_password', 'mail_password',
    ]

    # .env 文件模式
    ENV_FILE_PATTERNS = [
        '.env',
        '.env.local',

Credential Access

High
Category
Privilege Escalation
Confidence
90% confidence
Finding

Including '.env' as a direct scan target enables the tool to inspect a file type that often contains plaintext credentials. That creates a real credential-access surface, especially risky because the skill's declared purpose does not require reading secrets.

Content

Scanner excerpt · scripts/analyzers/env_scanner.py (reported line 77)May include surrounding context.

python
# .env 文件模式
    ENV_FILE_PATTERNS = [
        '.env',
        '.env.local',
        '.env.development',
        '.env.production',

Credential Access

High
Category
Privilege Escalation
Confidence
89% confidence
Finding

Targeting '.env.local' extends the same credential-access behavior to a common local override file that frequently contains developer-specific secrets. This increases the likelihood of exposing private credentials during ordinary assistant operations.

Content

Scanner excerpt · scripts/analyzers/env_scanner.py (reported line 78)May include surrounding context.

python
# .env 文件模式
    ENV_FILE_PATTERNS = [
        '.env',
        '.env.local',
        '.env.development',
        '.env.production',
        '.env.test',

Credential Access

High
Category
Privilege Escalation
Confidence
89% confidence
Finding

Scanning '.env.development' gives the skill access to development secrets such as test database credentials and API tokens. Even non-production secrets can enable lateral movement, source-code service access, or pivoting into higher-value environments.

Content

Scanner excerpt · scripts/analyzers/env_scanner.py (reported line 79)May include surrounding context.

python
ENV_FILE_PATTERNS = [
        '.env',
        '.env.local',
        '.env.development',
        '.env.production',
        '.env.test',
        '.env.staging',

Credential Access

High
Category
Privilege Escalation
Confidence
89% confidence
Finding

Including '.env.production' is particularly sensitive because production environment files may contain live credentials. In a skill not declared as a security scanner, this creates disproportionate risk of unauthorized access to operational secrets.

Content

Scanner excerpt · scripts/analyzers/env_scanner.py (reported line 80)May include surrounding context.

python
'.env',
        '.env.local',
        '.env.development',
        '.env.production',
        '.env.test',
        '.env.staging',
        '.env.*',

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

The '*.env' config-file pattern broadens discovery of environment files across the repository, increasing the chance of reading sensitive configuration material. The danger is amplified by the mismatch between capability and stated skill purpose.

Content

Scanner excerpt · scripts/analyzers/env_scanner.py (reported line 88)May include surrounding context.

python
# 配置文件模式
    CONFIG_FILE_PATTERNS = [
        '*.env',
        'config.*',
        'settings.*',
        '*.config.*',

Credential Access

High
Category
Privilege Escalation
Confidence
92% confidence
Finding

This function actively scans for .env files and passes them for parsing, which is direct credential-access behavior. Because environment files commonly contain plaintext secrets, this materially increases confidentiality risk if the skill is invoked in routine workflows.

Content

Scanner excerpt · scripts/analyzers/env_scanner.py (reported line 145)May include surrounding context.

python
return self._generate_report()

    def _scan_env_files(self) -> None:
        """扫描 .env 文件"""
        for pattern in self.ENV_FILE_PATTERNS:
            for env_file in self.project_dir.glob(pattern):
                self._parse_env_file(env_file)

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

Parsing .env files means the code reads lines that may contain secrets and stores associated metadata, masking only some values later. Reading sensitive files at all is credential-access capability, and partial redaction does not remove the underlying exposure risk.

Content

Scanner excerpt · scripts/analyzers/env_scanner.py (reported line 152)May include surrounding context.

python
self.env_files.append(str(env_file.relative_to(self.project_dir)))

    def _parse_env_file(self, file_path: Path) -> None:
        """解析 .env 文件"""
        try:
            with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
                lines = f.readlines()

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

This line includes '.env' in the set of file types scanned for sensitive values, meaning the scanner inspects secret-bearing files directly for credentials and tokens. In a general project-assistant skill, that is an unnecessary and risky credential-discovery capability.

Content

Scanner excerpt · scripts/analyzers/env_scanner.py (reported line 231)May include surrounding context.

python
for f in files:
                ext = Path(f).suffix.lower()
                if ext in {'.py', '.js', '.ts', '.jsx', '.tsx', '.java', '.go', '.json', '.yaml', '.yml', '.env'}:
                    file_path = Path(root) / f
                    self._find_secrets_in_file(file_path)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · scripts/analyzers/env_scanner.py (reported line 307)May include surrounding context.

python
"""生成安全建议"""
        recommendations = []

        # 检查是否有 .env 文件
        if self.env_files:
            recommendations.append("确保 .env 文件已添加到 .gitignore")

Static analysis

No suspicious patterns detected.