Back to skill

Security audit

lecture-notes-master

Security checks for vulnerabilities and agentic risk

Overview

This skill is for creating Obsidian study notes, but it needs review because it can create or overwrite many local vault files and does not safely constrain output paths.

Review before installing. Use it only if you want English-Chinese Obsidian notes written into the configured vault, confirm the target folder and file tree before any run, avoid untrusted titles or concept names, keep backups, and prefer a dedicated sandbox/output folder. Install optional Python dependencies in an isolated, pinned environment, and treat URL/video extraction as external processing that may reveal the provided links or content.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/generate.py:256
Finding
User-Controlled Filenames Permit Path Traversal and File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate.py`, lines 256–257, 327–340, 355–356, 369–372, and 381–382 **Vulnerability Type**: Path traversal and unsafe file creation **Risk Level**: High ### Vulnerable Code ```python def write_file(content, filepath): """Write content to file, creating directories if needed.""" os.makedirs(os.path.dirname(filepath), exist_ok=True) with open(filepath, "w", encoding="utf-8") as f: f.write(content) print(f" [OK] Created: {filepath}") ``` The vulnerable function receives paths constructed directly from command-line input: ```python filename = f"{args.title.replace(' ', '-')}-Notes.md" write_file(content, os.path.join(output_dir, filename)) ``` ```python atomic_filename = f"{concept.replace(' ', '-')}.md" write_file(atomic_content, os.path.join(output_dir, atomic_filename)) ``` ```python filename = f"{args.concept.replace(' ', '-')}.md" write_file(content, os.path.join(output_dir, filename)) ``` ```python if args.term_cn: filename = f"{args.term_en}({args.term_cn}).md" else: filename = f"{args.term_en}.md" write_file(content, os.path.join(output_dir, filename)) ``` ```python filename = f"{args.course.replace(' ', '-')}-MOC.md" write_file(content, os.path.join(output_dir, filename)) ``` ### Technical Analysis The `--title`, `--concepts`, `--concept`, `--term-en`, `--term-cn`, and `--course` arguments are incorporated into filesystem paths without rejecting path separators, absolute paths, or `..` traversal components. Replacing spaces with hyphens does not make a filename safe. `os.path.join(output_dir, filename)` does not guarantee that the resulting path remains inside `output_dir`. A filename containing traversal components can resolve outside the selected directory. If the generated component is absolute, `os.path.join` can discard the output-directory prefix entirely. The final path is then passed to: ```python os.makedirs(os.path.dirname(filepath), exist_ ...[truncated 2070 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Apply a strict filename policy to every user-controlled filename component: - Reject `/`, `\`, null bytes, and platform-specific separators. - Reject absolute paths. - Reject `.` and `..` path components. - Permit only a conservative set of Unicode letters, numbers, spaces, hyphens, underscores, and parentheses. - Enforce a reasonable maximum filename length. 2. Resolve and validate the destination before writing: ```python from pathlib import Path def safe_destination(output_dir, filename): base = Path(output_dir).expanduser().resolve() destination = (base / filename).resolve() if base not in destination.parents: raise ValueError("Output path escapes the configured output directory") return destination ``` 3. Use a dedicated slugification function instead of only replacing spaces: ```python def safe_slug(value): value = value.strip().replace(" ", "-") if not value or value in {".", ".."}: raise ValueError("Invalid filename") if "/" in value or "\\" in value: raise ValueError("Path separators are not allowed") return value ``` 4. Perform containment validation after appending the required suffix, not before it. 5. Avoid silent overwrite: - Use exclusive creation mode (`"x"`) by default. - Add an explicit `--overwrite` option when replacement is intentional. - Refuse to follow symbolic links where supported. 6. Add tests covering: - `../` traversal. - Absolute paths. - Backslash traversal on Windows. - Nested separators in glossary terms. - Existing-file overwrite. - Symlink-based escape attempts. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:163
Finding
Unpinned Third-Party Dependency Installation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, line 163 **Vulnerability Type**: Unpinned and unhashed dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash python3 --version || python --version pip3 install matplotlib numpy # For visualization scripts (optional) ``` Related runtime guidance appears in `scripts/visualize.py`: ```python except ImportError: print( "Error: matplotlib not installed. Run: pip3 install matplotlib", file=sys.stderr, ) sys.exit(1) ``` ```python except ImportError: print("Error: numpy not installed. Run: pip3 install numpy", file=sys.stderr) sys.exit(1) ``` ### Technical Analysis The Skill directs users to install `matplotlib` and `numpy` without exact versions, integrity hashes, a lock file, or an explicitly trusted package index. Installation therefore depends on mutable package releases, transitive dependency resolution, and the user's active pip configuration. Although both package names are legitimate and widely used, the documented process does not provide reproducible or integrity-verified dependency resolution. A compromised upstream release, transitive dependency, package index, mirror, or local pip configuration could cause unreviewed code to be installed. Python package installation can execute package build logic and subsequently exposes the installed package code to execution when `visualize.py` imports it. ### Attack Path 1. A user follows the documented prerequisite or the runtime installation prompt. 2. pip contacts the package index or mirror configured in the user's environment. 3. pip selects current versions and transitive dependencies because no versions or hashes are fixed. 4. A compromised or substituted distribution is downloaded. 5. Package installation or build logic executes under the user's account. 6. The malicious package is later imported by `visualize.py`, allowing its code to run in the Skill's process. ### Impact Asse ...[truncated 739 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Provide a reviewed dependency file with exact versions: ```text matplotlib==<reviewed-version> numpy==<reviewed-version> ``` 2. Generate and publish cryptographic hashes for all direct and transitive distributions, then require verification: ```bash python3 -m pip install --require-hashes -r requirements.txt ``` 3. Document the expected trusted package index and avoid implicitly relying on arbitrary user-configured mirrors. 4. Install dependencies in an isolated virtual environment rather than the global Python environment: ```bash python3 -m venv .venv . .venv/bin/activate python3 -m pip install --require-hashes -r requirements.txt ``` 5. Record and periodically review transitive dependencies. 6. Replace the runtime messages with instructions referencing the locked requirements file rather than recommending an unconstrained `pip install`. 7. Consider providing a reproducible container or packaged environment with reviewed dependency versions. ]]>
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (22)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The description overstates the implemented functionality. The code does generate Obsidian-compatible markdown scaffolds with wikilinks and bilingual glossary fields, so it is related in theme. However, it does not process the broad declared input modalities at all; it only uses CLI arguments. Its 'recursive atomic decomposition' is not implemented as automatic multi-layer generation—lecture mode generates only the main note and first-level atomic notes, while deeper layers require manual separate runs. Rich outputs like Mermaid diagrams and comparison tables are not synthesized by code, only left as TODO/template content. Additionally, the code supports generating a course MOC, an undeclared capability. Therefore the declared description does not accurately represent the actual behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description centers on creating structured Obsidian lecture notes and recursively decomposed atomic notes from source materials. The supplied code does not perform note generation, decomposition, source ingestion, or Obsidian vault construction. Instead, it loads local CSV files and runs BM25-based search over glossary, Mermaid templates, writing rules, and review questions, then formats search results for display. While glossary and Mermaid-related content are tangentially related to the declared domain, the code’s actual primary purpose is search/retrieval of reference data, not lecture note generation. This is a material description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description presents a full lecture-note generation system for Obsidian, centered on transforming source materials into richly structured markdown notes with diagrams, tables, glossary content, and wikilinks. In contrast, this code chunk only implements a visualization generator script. It accepts command-line arguments for chart type, title, JSON data, and output path, then renders and saves image files using Matplotlib. While charts could be a supporting component of a larger note-generation workflow, this specific code neither ingests the declared educational inputs nor produces the declared note outputs. Its primary purpose is materially different from the declared skill purpose, so this is a clear mismatch.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
This markdown example presents the skill being invoked and used in Chinese, and the rest of the examples consistently structure outputs with Chinese labels and bilingual Chinese-first formatting. Because the file does not indicate that language choice is optional or user-configurable, it suggests a fixed locale behavior that may violate language/locale policy expectations.

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill instructs file reads/writes into the user's Obsidian vault but does not declare an explicit tool scope such as allowed tools or permissions. In an agentic environment, undeclared filesystem capabilities reduce transparency and make it easier for a broadly triggered skill to modify local content unexpectedly.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The trigger phrases are broad enough to match ordinary summarization or note-taking requests, increasing the chance the skill activates when the user did not intend large-scale vault modifications. Because the skill also prescribes directory creation, many file writes, and optional network fetching, overbroad activation materially raises the chance of unintended side effects.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The user profile hard-codes the language policy as "Bilingual — English primary, Chinese secondary" and mandates a specific term format. This forces a locale/language preference rather than offering the user a choice or making the behavior clearly optional.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill explicitly instructs creation of directories and writing numerous files into the user's vault without an explicit user-facing warning or confirmation step. In context, this is risky because activation may be broad and the write pattern is recursive and high-volume, making accidental content sprawl or overwriting more likely.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The rule explicitly requires all technical terms to be presented as English plus Chinese, regardless of user preference or locale. In a note-generation skill that accepts arbitrary user inputs and produces educational content, this creates a policy-level prompt injection/output steering issue: it can force unsolicited language transformation and disclosure of translated terminology that the user did not request. The skill context makes this more relevant because the CSV appears to define mandatory generation behavior across all notes, so the requirement is likely to be applied broadly and consistently.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
This code generates note content containing Chinese text such as '详见' and '关键要点' directly in the output scaffold. Because the skill does not present this as an opt-in language choice or justify it as a region-specific tool, it violates the policy against forcing a specific language/locale by default.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The template hardcodes bilingual formatting in the title and throughout the document, requiring Chinese alongside English rather than letting the user choose a preferred language. This is a natural-language policy concern because it imposes a specific locale/language convention without visible opt-in or documented justification.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The template repeatedly hardcodes Chinese labels such as 概述, 关键要点, 总结, and 相关笔记, establishing a fixed bilingual locale across the document. Because no user choice or scope limitation is provided, this can violate language/locale policy expectations for user-controlled output language.

Vague Triggers

Low
Confidence
88% confidence
Finding
The standalone trigger "Exam prep / study materials" is too vague to distinguish this skill from many other educational or summarization workflows. It lacks constraints about format, required outputs, or Obsidian-specific context, increasing the risk of unintended invocation.

Missing User Warnings

Low
Confidence
84% confidence
Finding
The skill directs the agent to fetch URLs, extract transcripts, and use external tools without disclosing that network requests and third-party processing may occur. This can expose user-provided links, study materials, or browsing intent to external services and may surprise users who expected local-only note generation.

Scope Creep

Low
Category
Excessive Agency
Content
Generates Obsidian-compatible markdown notes from templates.

Usage:
    # Main lecture note with N concepts (not limited to 3)
    python3 generate.py --type lecture --title "Memory Optimization" \
        --concepts "Shared Memory,Bank Conflicts,Tiling,Coalescing" \
        --output "/path/to/00-Inbox/Topic/"
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Scope Creep

Low
Category
Excessive Agency
Content
Generates Obsidian-compatible markdown notes from templates.

Usage:
    # Main lecture note with N concepts (not limited to 3)
    python3 generate.py --type lecture --title "Memory Optimization" \
        --concepts "Shared Memory,Bank Conflicts,Tiling,Coalescing" \
        --output "/path/to/00-Inbox/Topic/"
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Natural-Language Policy Violations

Low
Confidence
82% confidence
Finding
The docstring states 'Supports both English and Chinese queries,' which communicates an explicit language constraint. Under the policy rule, forcing a specific language set without user opt-in or a clear justification can be a natural-language locale-policy issue.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The template consistently requires both English and Chinese fields and section headings, such as paired title aliases and bilingual headings throughout the document. This imposes a specific language/locale format by default rather than offering a user choice or documenting that the template is region-specific.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The markdown explicitly states 'Language(语言) | English (Bilingual notes)', which imposes a specific language setting in the template. Under the policy rules, forcing a language without offering user choice or documenting a justified locale constraint is a natural-language policy violation.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
This markdown template hardcodes Chinese punctuation and section labels such as '定义' and '相关笔记', and requires bilingual English/Chinese output. That imposes a specific language/locale convention in the generated content without indicating that the user can choose another language or opt in to this format.

Scope Creep

Low
Category
Excessive Agency
Content
<!-- 
  REPEAT for as many sections as the content demands.
  NOT limited to 3. Typically 3-7 sections.
  Each section corresponds to one L1 atomic note.
-->
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Scope Creep

Low
Category
Excessive Agency
Content
<!-- 
  REPEAT for as many sections as the content demands.
  NOT limited to 3. Typically 3-7 sections.
  Each section corresponds to one L1 atomic note.
-->
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Static analysis

No suspicious patterns detected.