Back to skill

Security audit

Self Skill Evolver

Security checks for vulnerabilities and agentic risk

Overview

This looks like a legitimate local skill-analysis tool, but it needs review because it can inspect broader local paths and stores/deletes telemetry with weak safeguards.

Install only if you are comfortable with a local tool that scans skill source files and keeps a SQLite telemetry database in your home directory. Use it on trusted skill names and paths, avoid passing sensitive context or raw errors into monitoring, and treat HTML report output as unsafe if skill names or recommendations may contain untrusted text.

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

Warning
Location
skill_evolver/analyzer.py:58
Finding

Unrestricted Skill Path Allows Analysis Outside the Configured Skill Directory

Content
View full analysis
SkillAnalysisResult: """ 分析单个技能 """ skill_path = self.skills_dir / skill_name result = SkillAnalysisResult( skill_name=skill_name, skill_path=str(skill_path) ) ``` The resulting path is subsequently used for recursive file discovery: ```python def _analyze_python_code(self, result: SkillAnalysisResult, skill_path: Path): """分析 Python 代码文件""" python_files = list(skill_path.rglob("*.py")) ``` ### Technical Analysis The analyzer constructs the target path by directly joining the configured Skill directory with the caller-controlled `skill_name`. It does not reject: - Parent-directory components such as `..` - Absolute paths - Symbolic links that resolve outside the Skill root - Alternate paths that normalize outside the intended directory With `pathlib`, joining a base path with an absolute path discards the base path. Relative traversal components can similarly escape the configured directory after filesystem resolution. The escaped path is used to read `SKILL.md`, parse `package.json`, and recursively discover and parse every Python file beneath the target. Although the implementation does not print complete source contents, it can disclose directory existence, resolved paths, filenames, syntax errors, line numbers, and code-quality information about files outside the authorized Skill repository. Recursive traversal can also impose substantial CPU and memory costs when pointed at a large directory. ### Atta ...[truncated 1324 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
database/models.py:143
Finding

SQL Predicate Injection Through Unvalidated Day Values

Content
View full analysis
Dict[str, Any]: """获取技能使用统计""" with self._get_connection() as conn: cursor = conn.execute(""" SELECT COUNT(*) as total, SUM(CASE WHEN status = 'success' THEN 1 ELSE 0 END) as success, SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed, AVG(duration_ms) as avg_duration, MAX(duration_ms) as max_duration, MIN(duration_ms) as min_duration FROM skill_usage WHERE skill_name = ? AND timestamp >= datetime('now', '-{} days') """.format(days), (skill_name,)) ``` The same pattern is used in a destructive operation: ```python def clear_old_data(self, days: int = 90): """清理旧数据""" with self._get_connection() as conn: conn.execute(""" DELETE FROM skill_usage WHERE timestamp < datetime('now', '-{} days') """.format(days)) conn.execute(""" DELETE FROM feedback WHERE timestamp < datetime('now', '-{} days') """.format(days)) conn.commit() ``` ### Technical Analysis The `days` value is interpolated directly into SQL before execution. Type annotations do not enforce runtime types in Python, so direct callers of these public methods can pass strings or objects whose string representation contains SQL syntax. The CLI reduces exposure because `argparse` parses `--days` as an integer. However, the database class is also a public Python API, and the methods do not independently enforce that `days` is an integer within a safe range. An attacker can close the `datetime()` expression and append a predicate such as `OR 1=1`, comm ...[truncated 1642 chars]
Remediation
View remediation
= datetime('now', ?) """, (skill_name, modifier), ) ``` 3. Apply the same parameterization to both deletion queries: ```python conn.execute( """ DELETE FROM skill_usage WHERE timestamp < datetime('now', ?) """, (modifier,), ) ``` 4. Consider requiring explicit confirmation for unusually broad retention deletion. 5. Return and display affected-row counts so unexpected deletion scope is visible. 6. Add regression tests using strings, booleans, negative values, extreme integers, quote characters, comment markers, and predicate-injection payloads. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
skill_evolver/reporter.py:296
Finding

Unescaped Report Fields Permit HTML and Script Injection

Content
View full analysis
str: """将报告转换为 HTML 格式""" if "error" in report: return f"

错误

分析 {report['skill_name']} 时出错: {report['error']}

" status_color = { "healthy": "#28a745", "warning": "#ffc107", "critical": "#dc3545" } html = f""" {report['skill_name']} 健康度报告 ``` The Skill name is inserted into the document body without escaping: ```python

{report['skill_name']} 健康度报告

生成时间: {report['generated_at']}

``` Recommendation values are also appended as raw HTML: ```python for rec in report['recommendations']: html += f"
  • {rec}
  • \n" ``` ### Technical Analysis The HTML renderer builds a document through direct string interpolation. It does not perform context-sensitive HTML escaping on dynamic fields such as: - `skill_name` - `error` - `generated_at` - `status` - Recommendation entries - Other report values if a caller supplies a custom report dictionary A Skill name is accepted from CLI/API input and persisted in several database workflows. A malicious name containing closing tags and script or event-handler markup can therefore break out of the intended text context. When a generated report is opened in a browser, injected markup is interpreted as active HTML rather than displayed as text. Browser restrictions may limit access to unrelated local files when the report is opened using a `file:` URL, but script execution, report spoofing, navigation, and access to data available within the report's browser context remain possible. ### Attack Path 1. The attacker supplies a malicious Skill name through the CLI, API, or a ...[truncated 1264 chars]
    Remediation
    View remediation

    T08 · Insecure Dependencies

    Note
    Location
    requirements.txt:1
    Finding

    Unpinned and Unhashed Dependencies Create a Non-Reproducible Supply Chain

    Content
    View full analysis
    =6.0 # Git operations (optional) GitPython>=3.1.0 # Testing pytest>=7.0.0 # Code linting flake8>=6.0.0 ``` The documented installation process executes this dependency set: ```bash pip install -r requirements.txt ``` ### Technical Analysis All dependencies use lower-bound constraints without upper bounds, exact versions, or package hashes. Consequently, two installations performed at different times can resolve to different package versions. The same file also includes testing and linting packages that are not required for normal runtime behavior. This unnecessarily increases the number of packages and transitive dependencies installed in production environments. No malicious dependency or currently exploitable dependency version was identified from the reviewed files. The security weakness is the absence of reproducible dependency controls: a future compromised, malicious, or incompatible release satisfying the lower-bound constraint can be selected automatically during installation. ### Attack Path 1. A maintainer or user follows the documented installation command. 2. `pip` resolves the latest package versions satisfying the `>=` constraints. 3. A newly published or compromised direct or transitive dependency is selected. 4. Package build, installation, or import-time code runs with the privileges of the installing user or environment. 5. The compromised component can affect the Skill or installation environment. This path is conditional on compromise or malicious publication of an allowed dependency version; the audit did not establish that any currently listed package is malicious. ### Impact Assessment Impact depends on the privileges used for installation and the behavior of the selected package. ...[truncated 531 chars]
    Remediation
    View remediation
    Vulnerability Patterns
    • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
    • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
    • 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 (26)

    Tp4

    High
    Category
    MCP Tool Poisoning
    Confidence
    95% confidence
    Finding

    A second, more specific description-behavior mismatch indicates the skill may only provide limited logging/statistics while claiming code-quality scanning, health checks, and improvement generation. It also reportedly uses a database without declared permissions/resources, compounding the risk by obscuring stateful behavior and creating hidden data-handling expectations.

    Content

    No source excerpt is available for this finding.

    Tp4

    High
    Category
    MCP Tool Poisoning
    Confidence
    95% confidence
    Finding

    A second, more specific description-behavior mismatch indicates the skill may only provide limited logging/statistics while claiming code-quality scanning, health checks, and improvement generation. It also reportedly uses a database without declared permissions/resources, compounding the risk by obscuring stateful behavior and creating hidden data-handling expectations.

    Content

    No source excerpt is available for this finding.

    Undeclared Tool Scope

    Medium
    Category
    MCP Least Privilege
    Confidence
    88% confidence
    Finding

    The skill advertises commands and detected capabilities that imply file read/write behavior, but it does not declare any tool scope such as permissions or allowed-tools. This creates an authorization and transparency gap: consumers may grant or assume broader access than intended, and reviewers cannot verify whether filesystem access is constrained to safe paths or purposes.

    Content

    No source excerpt is available for this finding.

    Missing User Warnings

    Medium
    Category
    Not specified by scanner
    Confidence
    90% confidence
    Finding

    The documented clear --days 90 command suggests deletion of stored data, but the skill description provides no warning that the action may be destructive or irreversible. In an operational context, users could remove logs or audit history unintentionally, reducing forensic visibility and disrupting monitoring or reporting workflows.

    Content

    No source excerpt is available for this finding.

    Missing User Warnings

    Medium
    Category
    Not specified by scanner
    Confidence
    95% confidence
    Finding

    This code creates and uses a persistent local SQLite database under the user's home directory to store skill usage logs and user feedback, including comments, context, error messages, and optional user identifiers. Even though there is no direct code-execution risk here, undisclosed persistence of potentially sensitive telemetry can create privacy and compliance issues, especially because the skill is designed to monitor usage and health over time.

    Content

    No source excerpt is available for this finding.

    Natural-Language Policy Violations

    Medium
    Category
    Not specified by scanner
    Confidence
    95% confidence
    Finding

    This Python file's module docstring and user-facing descriptive strings are written exclusively in Chinese, and there is no indication that users can choose another language or that the skill is intentionally region-specific. Under the policy, forcing a specific language without opt-in is a natural-language locale violation.

    Content

    No source excerpt is available for this finding.

    Natural-Language Policy Violations

    Medium
    Category
    Not specified by scanner
    Confidence
    96% confidence
    Finding

    The module docstring and many user-visible CLI messages are written only in Chinese, and there is no option for users to select another language or indication that the tool is intentionally region-specific. This creates a language/locale policy concern because the skill appears to enforce a specific language without user opt-in.

    Content

    No source excerpt is available for this finding.

    Missing User Warnings

    Medium
    Category
    Not specified by scanner
    Confidence
    95% confidence
    Finding

    The clear subcommand invokes db.clear_old_data(args.days) immediately, with no confirmation prompt, dry-run mode, or secondary safeguard. In a CLI that manages stored operational data, an accidental invocation or misuse can irreversibly delete records and reduce auditability, especially if run in automation or with an unexpectedly small/negative retention value depending on downstream validation.

    Content

    No source excerpt is available for this finding.

    Missing User Warnings

    Medium
    Category
    Not specified by scanner
    Confidence
    93% confidence
    Finding

    The monitor persists arbitrary caller-supplied context data directly to the database with no filtering, minimization, or sensitivity checks. In practice, context objects often contain prompts, inputs, identifiers, tokens, or other sensitive operational data, so this creates a privacy and data-retention risk if developers pass rich runtime state into the tracker.

    Content

    No source excerpt is available for this finding.

    Missing User Warnings

    Medium
    Category
    Not specified by scanner
    Confidence
    91% confidence
    Finding

    The failure path stores raw exception text via tracker.failed(str(e)), which can include secrets, file paths, SQL fragments, request contents, or internal implementation details. Retaining unsanitized exception messages in a database increases the risk of sensitive data exposure to operators, logs viewers, or attackers who later gain access to telemetry storage.

    Content

    No source excerpt is available for this finding.

    Natural-Language Policy Violations

    Medium
    Category
    Not specified by scanner
    Confidence
    91% confidence
    Finding

    The module docstrings, report labels, status text, and error messages are written entirely in Chinese, which implies the skill's generated reports are fixed to a specific language. Under the locale policy, forcing one language without user choice or documented justification is a natural-language policy violation.

    Content

    No source excerpt is available for this finding.

    Description-Behavior Mismatch

    Medium
    Category
    Not specified by scanner
    Confidence
    93% confidence
    Finding

    The module docstring says it is responsible for generating analysis and health reports, but generate_health_report also saves derived health-score data back into the database. That is a state-changing behavior beyond straightforward report generation and is not clearly reflected in the stated reporting-only purpose.

    Content

    No source excerpt is available for this finding.

    Natural-Language Policy Violations

    Low
    Category
    Not specified by scanner
    Confidence
    96% confidence
    Finding

    Module and class docstrings throughout the file are written in Chinese, which imposes a specific language on maintainers or users reading embedded instructions and comments. Under the policy, forcing a specific language without opt-in or justification is a natural-language policy concern.

    Content

    No source excerpt is available for this finding.

    Unpinned Dependencies

    Low
    Category
    Supply Chain
    Confidence
    97% confidence
    Finding

    The dependency is specified with a lower bound only, which permits installation of any newer release, including unexpected major versions or compromised upstream releases. This weakens reproducibility and makes it harder to verify whether a known-safe version of PyYAML is being used, especially important because YAML parsers have had prior security issues around unsafe parsing behavior.

    Content

    Scanner excerpt · requirements.txt (reported line 4)May include surrounding context.

    text
    # Skill Evolver Dependencies
    
    # YAML parsing
    PyYAML>=6.0
    
    # Git operations (optional)
    GitPython>=3.1.0
    

    Unverifiable Dependency: PyYAML has 8 known advisory(ies) (CVE-2019-20477 (Deserialization of Untrusted Data in PyYAML); CVE-2020-1747 (Improper Input Validation in PyYAML); CVE-2020-14343 (Improper Input Validation in PyYAML) +5 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

    Low
    Category
    Supply Chain
    Confidence
    95% confidence
    Finding

    PyYAML has known historical advisories, and because the manifest does not pin the package, it is impossible to verify whether the resolved version is affected. In a skill that may parse skill metadata or configuration, ambiguous PyYAML versioning is more concerning because insecure parser behavior can become exploitable when handling untrusted YAML content.

    Content

    No source excerpt is available for this finding.

    Unpinned Dependencies

    Low
    Category
    Supply Chain
    Confidence
    97% confidence
    Finding

    GitPython is unpinned, so builds may resolve to different versions over time, including versions with security regressions or newly introduced risky behavior. For a skill that evaluates and evolves other agent skills, git-related functionality can interact with repositories and local tooling, making dependency predictability more important than in a purely passive package.

    Content

    Scanner excerpt · requirements.txt (reported line 7)May include surrounding context.

    text
    PyYAML>=6.0
    
    # Git operations (optional)
    GitPython>=3.1.0
    
    # Testing
    pytest>=7.0.0
    

    Unverifiable Dependency: GitPython has 16 known advisory(ies) (CVE-2026-78676 (GitPython: Dormant multi-line git-config values are corrupted into live injected); CVE-2026-67325 (GitPython: Command Injection via git long-option prefix abbreviation bypass of C); CVE-2024-22190 (Untrusted search path under some conditions on Windows allows arbitrary code exe) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

    Low
    Category
    Supply Chain
    Confidence
    95% confidence
    Finding

    GitPython has multiple advisories, and the unpinned requirement prevents determining whether the installed version contains a known fix. Given this skill's stated role around analyzing and improving other skills, repository interaction is plausible, so uncertainty around a git library version increases exposure to dependency-related security issues.

    Content

    No source excerpt is available for this finding.

    Unpinned Dependencies

    Low
    Category
    Supply Chain
    Confidence
    92% confidence
    Finding

    pytest is also unpinned, which creates non-reproducible environments and can silently introduce vulnerable or incompatible releases into testing workflows. While primarily a development dependency, compromised or vulnerable test tooling can still affect CI systems or local developer environments.

    Content

    Scanner excerpt · requirements.txt (reported line 10)May include surrounding context.

    text
    GitPython>=3.1.0
    
    # Testing
    pytest>=7.0.0
    
    # Code linting
    flake8>=6.0.0
    

    Unverifiable Dependency: pytest has 2 known advisory(ies) (CVE-2025-71176 (pytest has vulnerable tmpdir handling); CVE-2025-71176 (pytest has vulnerable tmpdir handling)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

    Low
    Category
    Supply Chain
    Confidence
    87% confidence
    Finding

    pytest has known advisories, and without a fixed version there is no reliable way to determine whether the environment is vulnerable. Although this is a testing dependency rather than core runtime logic, vulnerable test tooling can still impact CI pipelines, temporary file handling, or developer workstations.

    Content

    No source excerpt is available for this finding.

    Unpinned Dependencies

    Low
    Category
    Supply Chain
    Confidence
    90% confidence
    Finding

    flake8 is unpinned, which allows arbitrary newer versions to be installed and may expose CI or developer systems to vulnerable or malicious upstream releases. The main risk is supply-chain instability and reduced reproducibility rather than direct runtime exploitation of the deployed skill.

    Content

    Scanner excerpt · requirements.txt (reported line 13)May include surrounding context.

    text
    pytest>=7.0.0
    
    # Code linting
    flake8>=6.0.0
    

    Natural-Language Policy Violations

    Low
    Category
    Not specified by scanner
    Confidence
    91% confidence
    Finding

    The natural-language text in the module docstring is presented only in Chinese and does not indicate any user language or locale choice. Under the policy rule, forcing a specific language without opt-in can be a locale/language policy violation even in code comments or docstrings.

    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 docstrings and inline documentation are exclusively in Chinese, with no indication that the language is configurable or intentionally limited to a Chinese-language environment. Per the policy, forcing a specific language without opt-in is a natural-language policy concern.

    Content

    No source excerpt is available for this finding.

    Intent-Code Divergence

    Low
    Category
    Not specified by scanner
    Confidence
    82% confidence
    Finding

    The generate_health_report docstring presents the method as producing and returning a health report, but the implementation also invokes _save_health_score and updates persistent state. This creates an intent mismatch between the documented behavior and the actual side effect.

    Content

    No source excerpt is available for this finding.

    Missing User Warnings

    Low
    Category
    Not specified by scanner
    Confidence
    80% confidence
    Finding

    This branch serializes the report and writes it to a user-specified file path, which is a safety-relevant file write. Although exporting is the function's purpose, there is no visible disclosure that directories may be created and files may be overwritten.

    Content

    No source excerpt is available for this finding.

    Missing User Warnings

    Low
    Category
    Not specified by scanner
    Confidence
    79% confidence
    Finding

    This branch writes Markdown output to output_path, which is a filesystem modification. The code does not include a confirmation prompt, user-visible logging, or an explicit warning that the chosen path will be created or overwritten.

    Content

    No source excerpt is available for this finding.