Back to skill

Security audit

Knowledge Base Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent local knowledge-base tool, but its file handling can escape its intended folders and delete or overwrite user-writable files.

Review this skill before installing. Use it only in a contained workspace or sandbox, avoid sensitive screenshots unless redacted, and do not run delete or export commands with untrusted business names, filenames, or output paths. The publisher should add strict path validation, confirmation for destructive actions, safer export behavior, and clearer privacy/retention documentation before broad use.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
knowledge-base/kb-manager.py:34
Finding

Business Name Path Traversal Enables Filesystem Escape and Recursive Directory Deletion

Content
View full analysis

Vulnerability Details

File Location: knowledge-base/kb-manager.py:34-36, knowledge-base/kb-manager.py:41-47, and knowledge-base/kb-manager.py:114-121
Vulnerability Type: Path traversal leading to unauthorized filesystem access and recursive deletion
Risk Level: High

Vulnerable Code

python
def get_business_dir(business_name: str) -> str:
    """获取业务数据库目录"""
    return os.path.join(KB_ROOT, business_name)
python
def ensure_business(business_name: str) -> Dict[str, Any]:
    """确保业务存在,不存在则创建"""
    businesses = load_businesses()
    
    if business_name not in businesses["businesses"]:
        # 创建新业务
        business_dir = get_business_dir(business_name)
        os.makedirs(business_dir, exist_ok=True)
python
def delete_business(business_name: str) -> Dict[str, Any]:
    """删除业务"""
    businesses = load_businesses()
    
    if business_name not in businesses["businesses"]:
        return {"status": "not_found", "message": f"业务「{business_name}」不存在"}
    
    business_dir = get_business_dir(business_name)
    
    # 删除目录
    import shutil
    if os.path.exists(business_dir):
        shutil.rmtree(business_dir)

Technical Analysis

business_name is taken from command-line or Agent-controlled input and passed directly to os.path.join() without validation or canonical-path containment checks.

This does not guarantee that the resulting path remains under KB_ROOT:

  • A value containing ../ can traverse to a parent directory.
  • An absolute path causes os.path.join() to discard KB_ROOT.
  • The resulting uncontrolled path is used for directory creation, database reads and writes, enumeration, and recursive deletion.

Although delete_business() first checks whether the supplied name exists in businesses.json, an attacker may create a malicious business entry through ensure_business() and subsequently delete it. A preexist ...[truncated 1455 chars]

Remediation
View remediation

Remediation Suggestions

  • Validate business names using a conservative allowlist, such as letters, numbers, underscores, and hyphens.

  • Reject absolute paths, path separators, empty names, . components, and .. components.

  • Resolve the target and root directories before every filesystem operation and enforce containment:

    python
    from pathlib import Path
    
    KB_ROOT_PATH = Path(__file__).resolve().parent
    
    def get_business_dir(business_name: str) -> Path:
        if not business_name or Path(business_name).name != business_name:
            raise ValueError("Invalid business name")
    
        target = (KB_ROOT_PATH / business_name).resolve()
        if target.parent != KB_ROOT_PATH:
            raise ValueError("Business path escapes KB root")
        return target
    
  • Do not trust path-related values loaded from businesses.json; validate them again before use.

  • Require explicit confirmation or a separate authorization control for recursive deletion.

  • Refuse to recursively delete symbolic links or paths that are not direct children of KB_ROOT.

  • Consider replacing recursive deletion with a restricted quarantine or soft-delete mechanism.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
knowledge-base/image-manager.py:17
Finding

Attachment Path Traversal Enables Arbitrary File Deletion and External Writes

Content
View full analysis

Vulnerability Details

File Location: knowledge-base/image-manager.py:17-20, knowledge-base/image-manager.py:122-125, and knowledge-base/image-manager.py:173-180
Vulnerability Type: Path traversal in attachment management
Risk Level: High

Vulnerable Code

python
def ensure_attachments_dir(business_name: str) -> str:
    """确保业务附件目录存在"""
    dir_path = os.path.join(ATTACHMENTS_ROOT, business_name)
    os.makedirs(dir_path, exist_ok=True)
    return dir_path
python
def get_image_info(business_name: str, filename: str) -> Optional[Dict[str, Any]]:
    """获取图片信息"""
    image_path = os.path.join(ATTACHMENTS_ROOT, business_name, filename)
    if not os.path.exists(image_path):
        return None
python
def delete_image(business_name: str, filename: str) -> Dict[str, Any]:
    """删除图片"""
    image_path = os.path.join(ATTACHMENTS_ROOT, business_name, filename)
    if not os.path.exists(image_path):
        return {"status": "not_found", "message": "图片不存在"}
    
    try:
        os.remove(image_path)
        return {"status": "deleted", "message": "已删除图片", "filename": filename}
    except Exception as e:
        return {"status": "error", "message": f"删除失败:{str(e)}"}

Technical Analysis

Both business_name and filename can originate from command-line or Agent-controlled input. They are concatenated with ATTACHMENTS_ROOT without normalization, validation, or a check that the resolved path remains inside the attachment directory.

A traversal sequence in either parameter can escape the intended directory. An absolute business_name can also override ATTACHMENTS_ROOT. The unsafe path is used by:

  • ensure_attachments_dir() to create directories.
  • save_image() indirectly to copy files into those directories.
  • get_image_info() to inspect external files.
  • delete_image() to delete files.

File-extension filtering in `save_image() ...[truncated 1433 chars]

Remediation
View remediation

Remediation Suggestions

  • Apply the same strict business-name validation used by the knowledge-base manager.

  • Require filename to be a basename only:

    python
    if not filename or os.path.basename(filename) != filename:
        raise ValueError("Invalid attachment filename")
    
  • Resolve paths and verify they remain beneath ATTACHMENTS_ROOT before creation, inspection, copying, or deletion.

  • Prefer internally generated attachment identifiers rather than accepting caller-controlled filenames for deletion.

  • Reject symbolic-link targets and use file operations designed to reduce symlink race risks.

  • Verify that deletion targets are regular files and direct descendants of the expected business attachment directory.

  • Add regression tests covering absolute paths, ../, nested separators, symbolic links, and encoded or platform-specific path separators.

T09 · Insecure Skill Coding Practices

Warning
Location
knowledge-base/kb-manager.py:458
Finding

Unrestricted Export Path Permits Arbitrary Writable File Overwrite

Content
View full analysis

Vulnerability Details

File Location: knowledge-base/kb-manager.py:418-460 and knowledge-base/kb-manager.py:550-552
Vulnerability Type: Arbitrary file overwrite through an unrestricted export destination
Risk Level: Medium

Vulnerable Code

python
def export_markdown(business_name: str, output_path: str = None) -> str:
    """导出为 Markdown"""
    all_answered = []
    all_pending = []
    
    for page_file in get_db_files(business_name):
        page_db = load_db_from_file(business_name, page_file)
        all_answered.extend(page_db.get('answered', []))
        all_pending.extend(page_db.get('pending', []))
    
    md = [f"# {business_name} - 问答知识库", ""]
    md.append(f"_最后更新:{datetime.now().strftime('%Y-%m-%d %H:%M')}")
    md.append("")
    md.append(f"**已回答**: {len(all_answered)} | **待回答**: {len(all_pending)} | **页数**: {len(get_db_files(business_name))}")
    md.append("")
    
    if all_answered:
        md.append("## ✅ 已回答问题")
        md.append("")
        for i, qa in enumerate(all_answered, 1):
            md.append(f"### Q{i}. {qa['question']}")
            md.append("")
            md.append(f"**A**: {qa['answer']}")
            md.append("")
            tags = qa.get('tags', [])
            usage = qa.get('usage_count', 0)
            md.append(f"_标签_: {', '.join(tags) if tags else '无'} | _使用次数_: {usage}")
            md.append("")
            md.append("---")
            md.append("")
    
    if all_pending:
        md.append("## ⏳ 待回答问题")
        md.append("")
        for i, p in enumerate(all_pending, 1):
            md.append(f"{i}. **{p['question']}** (_{p['created'][:10]}_)")
        md.append("")
    
    content = "\n".join(md)
    
    if output_path:
        with open(output_path, "w", encoding="utf-8") as f:
            f.write(content)
    
    return content
python
elif cmd == "export" and len(sys.a
...[truncated 2033 chars]
Remediation
View remediation

Remediation Suggestions

  • Export only into a dedicated directory controlled by the application.
  • Accept a filename rather than a complete path and reject path separators and traversal components.
  • Resolve the destination and enforce containment beneath the export root.
  • Reject symbolic links and verify that each relevant parent directory is trusted.
  • Use exclusive creation mode ("x") by default to prevent unintentional replacement.
  • If overwrite support is required, require explicit confirmation and verify the exact canonical destination.
  • Generate temporary output in the same trusted directory and perform an atomic rename only after successful completion.

T08 · Insecure Dependencies

Note
Location
SKILL.md:427
Finding

Unpinned OCR Dependencies Create a Supply-Chain Integrity Risk

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:427
Vulnerability Type: Unpinned third-party dependency installation
Risk Level: Low

Vulnerable Code

bash
pip install pytesseract pillow

Technical Analysis

The installation instruction requests packages by name without version constraints, integrity hashes, a lock file, or an explicitly approved package index.

The package names are consistent with the Skill's declared OCR functionality, and no typosquatting was identified. Nevertheless, resolving mutable latest versions makes installation non-reproducible and exposes users to compromised releases, account takeover at the package repository, or unexpected future behavior.

Python packages may execute build or installation logic and are subsequently imported by image-manager.py, giving compromised dependency code the privileges of the installing or invoking user.

Attack Path

  1. A user follows the dependency installation command in SKILL.md.
  2. pip resolves the current package versions from its configured package index.
  3. A compromised, malicious, or unexpectedly changed release is downloaded because no version or hash is enforced.
  4. Package build or installation code executes, or malicious code executes when the OCR modules are imported.
  5. The dependency receives the privileges and data access of the Python process.

Impact Assessment

Impact depends on the behavior of a compromised dependency and the privileges used for installation or execution. Potential consequences include:

  • Arbitrary code execution as the installing user.
  • Access to local knowledge-base and attachment data.
  • Modification or deletion of user-accessible files.
  • Credential or environment-variable exposure.
  • Broader system compromise if installation is performed with elevated privileges.

No evidence was found that the currently named packages are malicious; this finding concerns the absenc ...[truncated 55 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin reviewed dependency versions in a requirements file.
  • Generate and verify cryptographic hashes, for example through a hash-locked requirements workflow.
  • Use an approved package index or internal mirror.
  • Install dependencies in an isolated virtual environment rather than globally.
  • Avoid elevated installation privileges.
  • Establish a dependency update and vulnerability-review process.
  • Document compatible versions of the Tesseract binary and language data where applicable.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The documented behavior materially overstates what the skill actually implements, claiming database management, auto pagination, and intelligent search that are reportedly absent. This can cause users or orchestrators to trust the skill with sensitive workflows under false assumptions, leading to misuse, accidental data exposure, or reliance on nonexistent safeguards.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The business name is used directly in filesystem path construction via os.path.join(KB_ROOT, business_name) with no normalization or containment checks. An attacker can supply values like '../..' or absolute paths, causing ensure_business and delete_business to create or recursively delete directories outside the knowledge-base root, which is far beyond the stated purpose of managing business-specific KB data.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill declares executable capabilities involving file read/write and shell access but does not define any tool scope or permission boundaries. In a skill that manages local files, attachments, OCR, and shell-based helpers, this omission increases the risk of overbroad access, unintended file operations, and unsafe command execution paths.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill prominently promotes image attachment and OCR extraction but does not clearly warn that uploaded images and extracted text are stored and may contain sensitive data. Because screenshots often include credentials, PII, internal URLs, or error details, silent retention materially increases privacy and data-leak risk.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases include very broad terms such as '知识库', 'knowledge base', and 'KB', which are likely to appear in normal conversation. Overbroad activation can cause the skill to engage unexpectedly and start interpreting ordinary user text as commands, increasing the chance of unintended file, OCR, or data-management actions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The documented delete command enables irreversible business deletion without any warning, safeguard, or confirmation requirement. In a knowledge-base tool with persistent local storage, accidental or induced deletion could cause permanent loss of records and attachments.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest describes a knowledge-base skill with image attachment and OCR support, which justifies image storage and text extraction. However, spawning a system process with subprocess introduces general local command-execution capability, which is materially different from ordinary file handling and is not explicitly declared in the stated purpose.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · knowledge-base/image-manager.py (reported line 88)May include surrounding context.

python
if tesseract_cmd:
            try:
                output_base = image_path + "_ocr"
                subprocess.run([
                    tesseract_cmd,
                    image_path,
                    output_base,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The delete_image function removes files from disk with os.remove and the CLI exposes this via the delete command, but there is no confirmation prompt or explicit warning that the operation is destructive. Because this is an irreversible file-deletion action, the skill should disclose that behavior before executing it.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script automatically performs OCR on a user-supplied image and gives no warning that image contents may be extracted and processed as text. In a knowledge-base context, screenshots often contain credentials, PII, internal URLs, or tickets, so silent OCR increases the chance of unintended sensitive-data ingestion.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The attachment object stores both the original image path and extracted OCR text in the knowledge base, which can persist sensitive local filesystem details and image-derived secrets beyond the user's expectation. In a multi-business knowledge base, this broadens exposure because indexed OCR text may become searchable by other workflows or users.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Business deletion is destructive and immediately calls shutil.rmtree on the derived directory with no confirmation, dry-run, or safety interlock. In this file, that weakness is amplified by the path traversal issue in business_name handling, making accidental or malicious data loss more likely and more severe.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

export_markdown accepts an arbitrary output_path and writes content to it without restriction. This enables overwriting or planting files anywhere the process has access, which exceeds normal KB export scope and could damage data or be chained into more serious attacks depending on runtime permissions.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The natural-language command descriptions are loosely defined and do not establish strict parsing boundaries between conversational text and operational commands. This ambiguity can lead to accidental command execution or incorrect interpretation of user intent, though the risk is lower than explicit broad trigger phrases.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The configuration hard-codes OCR language to chi_sim+eng, which imposes a specific language/locale behavior. The document does not indicate that users can choose another language package or that the restriction is required for a region-specific deployment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The module description and OCR implementation are written for Chinese usage and the OCR language is hard-coded to chi_sim+eng, without offering the user a language choice. This can violate language/locale policy when a skill imposes a specific locale by default rather than making it configurable or clearly region-scoped.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

All user-visible help text, usage strings, and status messages are written only in Chinese, which imposes a specific language on users without any opt-in or alternative. The policy calls for flagging language constraints unless the skill offers a choice or clearly documents a justified locale restriction.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The inline documentation says kb-image.sh add <业务名> <问题> <答案> <图片路径>, which is four arguments after add, but the code checks if [ $# -lt 7 ] before proceeding. This means the documented invocation would be rejected, so the documented intent actively conflicts with runtime behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The module docstring and all CLI user-facing messages are written only in Chinese, which effectively imposes a single language on users without any opt-in or alternative. The stated policy flags language or locale constraints when the skill does not offer a choice or clearly justify the restriction.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

export_markdown writes generated content to an output path supplied by the caller, but the code provides no warning in the function or command help that running export will create or overwrite a file at the specified location. Since file writes are safety-relevant under this rule, some disclosure is expected when the operation may affect user files.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.