Back to skill

Security audit

auto-wiki

Security checks for vulnerabilities and agentic risk

Overview

The skill is a disclosed local wiki builder, but it needs review because it persistently modifies wiki data and its generated reports can run unsafe browser JavaScript over private wiki content.

Install only if you are comfortable with a local persistent .wiki knowledge base that the agent can modify. Avoid generating or opening _report.html for sensitive wikis until report output is sanitized and the remote JavaScript dependency is removed or pinned with integrity controls. Use explicit commands for ingest/lint/deep-dive, review proposed writes, and keep network features and external validators disabled for confidential projects unless you approve the destination and data being sent.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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)

T09 · Insecure Skill Coding Practices

Error
Location
references/schema.py:526
Finding
Stored JavaScript Injection in Generated Wiki Reports<![CDATA[ ## Vulnerability Details **File Location**: `references/schema.py:526-687` **Vulnerability Type**: Stored HTML/JavaScript injection **Risk Level**: High ### Vulnerable Code ```javascript cardsEl.innerHTML = cc.map(c => `<div class="card"><div class="num">${c.num}</div><div class="label">${c.label}</div></div>`).join(''); ``` ```javascript ndBody.innerHTML = html; ``` ```javascript dtEl.innerHTML = `<table><thead><tr><th>Page</th><th>Field</th><th class="r">Value</th><th>Unit</th><th>Period</th><th>Conf.</th></tr></thead><tbody>` + DATA.data_rows.map(r => `<tr><td>${r.page}</td><td>${r.field}</td><td class="r"><b>${r.value}</b></td><td>${r.unit}</td><td>${r.period}</td><td><span class="badge badge-${r.confidence}">${r.confidence}</span></td></tr>` ).join('') + '</tbody></table>'; ``` ```python def generate_report(wiki_dir: Path) -> Path: """生成 wiki 可视化报告 HTML。返回输出文件路径。""" data = collect_report_data(wiki_dir) html = REPORT_HTML_TEMPLATE html = html.replace("{{WIKI_NAME}}", data["name"]) html = html.replace("{{WIKI_DESC}}", data.get("description", "")) html = html.replace("{{ONTOLOGY_TYPE}}", data.get("ontology_type", "")) html = html.replace("{{TOTAL_PAGES}}", str(data["total_pages"])) html = html.replace("{{JSON_DATA}}", json.dumps(data, ensure_ascii=False, default=str)) out_path = wiki_dir / "_report.html" out_path.write_text(html, encoding="utf-8") return out_path ``` ### Technical Analysis The report generator incorporates wiki-controlled metadata and page-derived values directly into an HTML document. Some values are inserted through string replacement, while the complete data model is embedded in an inline script using `json.dumps()`. JSON serialization alone is not sufficient for safe embedding inside an HTML `<script>` element. In particular, an attacker-controlled value containing `</script>` can terminate the original script element and inject new HTML or JavaScript. The generated c ...[truncated 1883 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not insert untrusted values into HTML using raw string replacement. 2. Construct report elements with DOM APIs and assign untrusted values using `textContent`, not `innerHTML`. 3. If limited markup is required, process it through a well-maintained HTML sanitizer with a restrictive allowlist. 4. Escape HTML placeholders using an appropriate HTML-escaping function. 5. Before embedding JSON in a script element, escape at least: - `<` as `\u003c` - `>` as `\u003e` - `&` as `\u0026` - U+2028 and U+2029 as Unicode escapes 6. Prefer placing serialized data in an inert `<script type="application/json">` element and parse its `textContent`. 7. Validate slugs, relation types, confidence values, and other identifier-like fields against strict allowlists. 8. Add a restrictive Content Security Policy. If inline scripts remain necessary, use a nonce or hash rather than allowing unrestricted inline execution. 9. Add regression tests using payloads containing: ```text </script><script>alert(1)</script> <img src=x onerror=alert(1)> ${maliciousValue} ``` ]]>

T03 · Remote Payload Retrieval and Execution

Warning
Location
references/schema.py:395
Finding
Generated Reports Retrieve and Execute Third-Party JavaScript<![CDATA[ ## Vulnerability Details **File Location**: `references/schema.py:395` **Vulnerability Type**: Remote code retrieval in generated HTML **Risk Level**: Medium ### Vulnerable Code ```html <script src="https://unpkg.com/vis-network@9.1.9/standalone/umd/vis-network.min.js"></script> ``` ### Technical Analysis Every generated report references JavaScript hosted by `unpkg.com`. When the report is opened, the browser retrieves and executes that remote payload in the same document context as the embedded wiki data. The package version is specified, which reduces ordinary version drift, but the asset is not protected by a Subresource Integrity hash. The report also lacks a restrictive Content Security Policy. As a result, security depends on the CDN, its delivery infrastructure, and the integrity of the hosted package artifact at viewing time. This behavior also conflicts with the Skill's passive-mode claim of zero network dependencies from a user-expectation perspective: compilation may remain local, but opening the generated report causes a network request and remote code execution. ### Attack Path 1. The user generates `_report.html`. 2. The report contains private wiki metadata and structured data in its inline `DATA` object. 3. The user opens the report while connected to the network. 4. The browser requests the script from `unpkg.com`. 5. If the CDN, package artifact, account, DNS path, or delivery infrastructure is compromised, altered JavaScript is returned. 6. The remote script executes in the report context and can access the embedded wiki report data. 7. The script can transmit that data or manipulate the report interface. ### Impact Assessment A compromised remote dependency could: - Read all information embedded in the generated report. - Exfiltrate wiki metadata and structured data. - Falsify graph nodes, data tables, confidence labels, or coverage warnings. - Load additional remote payloads. - Track users who open otherwise local rep ...[truncated 165 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Bundle a reviewed local copy of `vis-network` with the Skill and reference it using a relative path. 2. If CDN delivery is retained, add a verified Subresource Integrity hash and the appropriate `crossorigin` attribute: ```html <script src="https://unpkg.com/vis-network@9.1.9/standalone/umd/vis-network.min.js" integrity="sha384-REPLACE_WITH_VERIFIED_HASH" crossorigin="anonymous"></script> ``` 3. Add a restrictive Content Security Policy that only permits the exact required script source. 4. Clearly inform the user that opening the report causes a third-party network request. 5. Provide an explicit offline-report option and make it the default. 6. Verify and document the provenance and license of the bundled dependency. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
validators/fibo-mcp.md:12
Finding
External Ontology Validation Can Disclose Wiki-Derived Terms Without Explicit Per-Service Consent<![CDATA[ ## Vulnerability Details **File Location**: `validators/fibo-mcp.md:12-22`; related invocation behavior at `references/lint-protocol.md:151-160` **Vulnerability Type**: Unclear external data-disclosure boundary **Risk Level**: Low ### Vulnerable Configuration and Instructions ```markdown | Item | Value | |------|-------| | Endpoint | `https://mcp.ablemind.cc/fibomcp/mcp` | | Protocol | MCP Streamable HTTP (requires `Mcp-Session-Id`), HTTPS via Cloudflare | | Tools | Only `sparql` (no search) | | Data Scale | 627,712 triples (includes OWL-RL inference materialization) | ``` ```markdown Send `tools/call` request via MCP protocol, tool name = `sparql`, parameter is SPARQL query string. Need to `initialize` first to get `Mcp-Session-Id`, subsequent requests include that header. > **No user credentials needed**: `Mcp-Session-Id` is a standard session identifier for MCP Streamable HTTP transport (similar to HTTP Session), automatically obtained by the agent during `initialize`. No API key or secrets required from the user. The endpoint is a public read-only SPARQL query service. ``` Related automatic validator behavior: ```markdown If meta.yaml declares a `seed` and the corresponding seed file points to a `validator`, Coverage additionally runs validator checks: - Detection: Call validator (e.g., FIBO SPARQL) to query required relations (`someValuesFrom` constraints) for entity types, compare against relations built in wiki - Example: FIBO says PensionFund must have a Trustee relation, but the wiki entity page lacks this relation → Gap - Output: `{ gap_type: "validator_gap", page: "xxx", missing_relation: "hasTrustee", standard: "FIBO" }` - Degradation: If validator unreachable, silently skip and note in report "External validator unreachable, skipped" ``` ### Technical Analysis Validator queries are transmitted to the third-party endpoint `mcp.ablemind.cc`. Those queries can contain class names, property names, keywords, and other terms derived f ...[truncated 1832 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require explicit opt-in before the first request to each external validator. 2. Display: - The destination hostname. - The categories of wiki information being transmitted. - Whether the service may log requests. - The local-only fallback behavior. 3. Show or summarize the exact SPARQL query before transmission when confidential data may be involved. 4. Provide a persistent `external_validation: false` or `network_mode: local-only` configuration. 5. Redact internal entity identifiers and replace them with generic ontology terms whenever possible. 6. Do not silently initiate external validation solely because a seed references a validator. 7. Document the endpoint operator, privacy policy, retention policy, and trust assumptions. 8. Consider supporting a locally hosted FIBO dataset or validator for confidential wikis. ]]>

T08 · Insecure Dependencies

Note
Location
SKILL.md:36
Finding
Runtime Dependencies Are Incompletely Declared and Not Version-Locked<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:36-40`; undeclared import at `references/schema.py:18` **Vulnerability Type**: Unpinned and incomplete dependency specification **Risk Level**: Low ### Vulnerable Instructions and Code ```markdown | Dependency | Required? | Description | |------------|-----------|-------------| | **Python 3.8+** | ✅ Required | `schema.py` (frontmatter validation), `store.py` (SQLite data management), `build_index.py` (FTS5 indexing) are Python scripts. Uses only stdlib (`sqlite3`, `json`, `pathlib`) + `pydantic` | | **pydantic** | ✅ Required | Frontmatter validation in `schema.py`. `pip install pydantic` | ``` The executable validator additionally imports PyYAML: ```python import yaml from pydantic import BaseModel, Field, field_validator, model_validator ``` ### Technical Analysis The setup instructions recommend installing `pydantic` without a version constraint, lock file, or package hash. Package resolution therefore depends on the latest version available from the configured package index at installation time. The documentation also claims the Python components use the standard library plus Pydantic, but `schema.py` imports `yaml`, which is provided by PyYAML and is not part of the Python standard library. PyYAML is not declared in the dependency table or installation command. This causes two security and reliability problems: 1. Builds are not reproducible because mutable dependency versions are selected at installation time. 2. Users may respond to the missing `yaml` module by installing an incorrect or unreviewed package ad hoc. The code correctly uses `yaml.safe_load`, so this finding does not assert unsafe YAML object deserialization. ### Attack Path 1. A user follows the documented setup procedure. 2. `pip install pydantic` resolves a mutable current release from the user's configured package index. 3. Running `schema.py` fails because PyYAML is absent. 4. The user installs an additional pac ...[truncated 890 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Add an explicit dependency manifest containing both Pydantic and PyYAML. 2. Pin reviewed versions compatible with the implementation, especially because the code uses Pydantic v2 APIs such as `field_validator` and `model_validator`. 3. Provide a hash-locked requirements file, for example: ```text pydantic==REVIEWED_VERSION --hash=sha256:... PyYAML==REVIEWED_VERSION --hash=sha256:... ``` 4. Generate and maintain the lock file using a reproducible dependency-management tool. 5. Document the trusted package index and discourage installation from arbitrary extra indexes. 6. Test installation in a clean virtual environment as part of continuous integration. 7. Correct the runtime-dependency statement so it no longer claims that only the standard library and Pydantic are used. 8. Add automated dependency and vulnerability scanning for locked packages. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (25)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The code partially aligns with the declared 'lint' aspect of the skill because it validates wiki page frontmatter and checks wiki health-related issues. However, the declared purpose presents the skill primarily as a knowledge compiler/router with recall, ingest, query, lint, and deep-dive behaviors. This code chunk does not implement recall, ingest, query routing, or search-based gap filling. Instead, it focuses on schema validation and report generation. The biggest undeclared behavior is the generation of an interactive HTML visualization report and the extraction of graph/data analytics from both markdown files and a SQLite database. Accessing data.db is a materially different resource interaction than the description suggests, especially since declared runtime dependencies mention only stdlib, pydantic, and optional WebSearch/MCP validator, while the code also depends on YAML parsing and SQLite-backed wiki data analysis. So while this is related to wiki linting/support infrastructure, the description does not accurately represent this chunk's actual behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding
The supplied code is a low-level persistence component, not a full 'knowledge compiler' skill. It stores structured wiki metadata and numeric data points in SQLite, tracks history, and supports retrieval and summaries. It does not implement the declared user-facing modes (recall, ingest, query, lint, deep-dive), automatic routing based on trigger words, source compilation, gap analysis, search, or answer generation from accumulated knowledge. While persistent wiki storage is related to the broader declared system, this chunk’s actual behavior is materially narrower and different in purpose: it is a database backend rather than the described multi-mode knowledge-compilation skill.

Vague Triggers

High
Confidence
96% confidence
Finding
The ingest triggers include very common phrases like 'organize this,' 'study this,' 'research this,' and 'help me organize,' which can match ordinary conversation and cause unintended activation of a write-capable workflow. In this skill, accidental activation is more dangerous because ingest can create persistent files, update existing knowledge, and potentially invoke optional search behavior.

Vague Triggers

High
Confidence
94% confidence
Finding
The query and lint triggers overlap with normal conversation, especially phrases like 'check it' and 'check wiki,' making unintended mode switching plausible. Because lint performs broad scans and potential auto-fixes while query changes retrieval behavior, ambiguous activation can lead to unnecessary file access, unexpected modifications, or confusing policy changes in the session.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill explicitly directs the agent to scan, read, create, and modify files under `.wiki/` and to run local Python utilities, but it does not declare a formal tool scope such as allowed tools or permissions metadata. That weakens platform enforcement and increases the chance the skill is granted broader file access than intended, especially because it persists data across sessions and manipulates local storage.

Vague Triggers

Medium
Confidence
90% confidence
Finding
Deep-dive trigger phrases like 'fill gaps,' 'level up,' and 'comprehensive fill' are broad enough to be used casually, yet this mode can chain coverage analysis, search, and ingestion. Even though the spec includes a confirmation step before batch writes, overly broad activation still increases the risk of unintended external search, expanded file reads, and persistence operations.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The protocol explicitly authorizes automatic fixes, metadata updates, and log appends, but it does not require an explicit user confirmation boundary or a warning that user-authored content may be modified. In an agent skill, this can lead to unintended or over-broad writes to a persistent knowledge base, especially because lint is framed as a routine maintenance action and may be triggered automatically by user intent.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This document operationalizes systematic collection and synthesis of a person's writings, conversations, expression patterns, decisions, and external views into a persistent cognitive profile, but it does not include any privacy, consent, sensitive-data, or anti-targeting safeguards. Even when sourcing from public materials, aggregating and structuring these signals can create a far more invasive profile than any single source, enabling profiling, inference of sensitive traits, and downstream misuse.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
### Index Build Script

Agent auto-executes after ingest (if search.db exists):

```python
#!/usr/bin/env python3
Confidence
90% confidence
Finding
The document explicitly instructs the agent to 'auto-execute' an index rebuild script after ingest, creating an autonomous action that writes to disk and processes large sets of files without an explicit per-run user confirmation. Even though the shown script is local and uses parameterized SQL, autonomous execution expands the attack surface: malicious or malformed ingested content, unexpected wiki paths, or symlinked directories could trigger unintended file processing or resource exhaustion.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The generated report hard-codes the document language as `zh-CN`, which imposes a specific locale regardless of user preference or content language. The file does not provide any opt-in, configuration, or justification showing that the skill is intentionally region-specific.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The generated report loads JavaScript from unpkg.com at runtime, which introduces external code execution into what is otherwise a local validation/reporting workflow. If the CDN asset is modified, unavailable, blocked, or replaced via dependency compromise, opening the local HTML report will execute untrusted third-party code in the user's browser and may expose embedded wiki data to that script.

Natural-Language Policy Violations

Medium
Confidence
85% confidence
Finding
The document explicitly designates a set of Chinese channels as acceptable sources, which creates a locale-specific sourcing policy in natural language. Because the file does not explain that the skill is limited to a China-specific use case or offer an alternative locale choice, this can be read as a forced locale preference.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The specification instructs the agent to create and populate `.wiki/` and `.wiki/.obsidian/` in the user's working tree automatically, which is a state-changing filesystem side effect. In an agent setting, making workspace modifications without an explicit user notice/confirmation can surprise users, alter repositories, and persist artifacts across sessions in ways they did not intend.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
Recommending edits to `.gitignore` and especially suggesting `git init` inside `.wiki/` introduces repository-affecting side effects that can change version-control behavior and user expectations. In an automated skill, touching VCS configuration without a warning or opt-in can hide files from tracking or create nested repos that complicate tooling and audits.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The spec permits fetching arbitrary URLs with WebFetch during ingest without an explicit warning that this causes network access and may transmit user-supplied targets or related metadata externally. In agent workflows, unannounced outbound requests can create privacy, compliance, and SSRF-like risk depending on what URLs the agent is allowed to access.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
Line L56 states that concept names use English but explanations and non-mixing rules use Chinese, effectively prescribing a specific language choice. This is a natural-language policy concern because it forces a locale/language without indicating user choice or a documented region-specific justification.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
This markdown file includes a dedicated 'Chinese Mapping' column, which introduces a locale-specific constraint in the skill content. The file does not state that Chinese terminology is optional, user-selected, or required for a specific regional compliance context, so it appears to force a language/locale preference without opt-in.

Natural-Language Policy Violations

Low
Confidence
76% confidence
Finding
The file defines recall mode as causing the agent to "answer all subsequent questions by checking wiki first," but it does not offer any user-selectable language or locale behavior despite being a broad conversational mode. While not an explicit locale lock, this kind of persistent instruction could override user expectations unless the mode boundaries and user controls are made more explicit.

Natural-Language Policy Violations

Low
Confidence
83% confidence
Finding
The locale-specific directive for Chinese figures hard-codes preferred and blacklisted sources without user opt-in, neutrality guidance, or explanation of jurisdictional/privacy implications. While not inherently malicious, this can introduce bias, uneven treatment by nationality or language group, and increase the chance of collecting personal-profile data under assumptions the user did not authorize.

Description-Behavior Mismatch

Low
Confidence
86% confidence
Finding
The module docstring presents this file as a 'Pydantic validation model' that agents should run after ingest and during lint, which implies schema validation behavior. However, the same file also scans the wiki, reads SQLite data, constructs graph/report data, and writes a `_report.html` visualization artifact, which is additional behavior not reflected in the file's stated purpose/documentation.

Missing User Warnings

Low
Confidence
83% confidence
Finding
The code generates and writes `_report.html` containing collected wiki metadata, page relationships, and data rows. Although file output is part of the implementation, there is no warning in the function docstring or broader file comments that the report materializes potentially sensitive wiki contents into a browsable HTML file.

Missing User Warnings

Low
Confidence
84% confidence
Finding
The markdown tells the agent to run a command that generates `_report.html`, which is a file write operation in the user's workspace. While the purpose is described, there is no explicit user warning that a generated artifact will be created and may need to be excluded or cleaned up.

Missing User Warnings

Low
Confidence
87% confidence
Finding
The spec states that when a wiki is created, the agent runs `python store.py init .wiki/{topic}/` to initialize a SQLite database. This creates local persistent storage containing structured data, but the markdown does not explicitly warn the user that such a database file will be created and populated.

Missing User Warnings

Low
Confidence
77% confidence
Finding
This code creates and persists a `data.db` file on disk, which is a file-write operation. While the CLI mentions `initialize data.db`, the `init_db` method itself has only a generic docstring and no user-facing disclosure when used as a library, so the write behavior is not clearly warned at the operation point.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
Line L239 states that Chinese concepts use a Chinese slug, which is a language/locale requirement expressed in natural language. The document does not present this as an opt-in choice for users overall, and the justification given ('Obsidian-friendly') does not clearly establish a necessary region-specific constraint.

Static analysis

No suspicious patterns detected.