Back to skill

Security audit

cornell note tool

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real Cornell notes skill, but it adds avoidable local code-execution risk through a predictable /tmp script path and environment-selected editors.

Review before installing. Use it only if you are comfortable saving notes persistently under ~/cornell-notes and launching a local editor. Prefer running the bundled scripts/cornell.py directly from the skill directory, avoid the /tmp/cornell.py workflow, and ensure $EDITOR or $VISUAL points to a trusted editor.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:30
Finding
Predictable Temporary Script Path Enables Local Code Substitution## Vulnerability Details **File Location**: `SKILL.md:30-33` and `SKILL.md:60-62` **Vulnerability Type**: Unsafe temporary-file handling and execution **Risk Level**: Medium The documented workflow recommends copying the bundled Python script to a predictable path in the shared temporary directory and subsequently executing that copy. ```bash cp <skill_root>/scripts/cornell.py /tmp/cornell.py ``` ```bash python /tmp/cornell.py new "<title>" ``` ### Technical Analysis `/tmp/cornell.py` is a fixed, predictable path in a generally shared and attacker-writable directory. A local attacker or compromised process may attempt to pre-create the destination as a symbolic link, replace the copied file after the copy, or modify it before execution. Because the workflow later passes this path to the Python interpreter, successful substitution results in execution of attacker-controlled Python code. Separating the copy and execution into distinct commands creates a time-of-check/time-of-use opportunity. The risk is unnecessary because the trusted script can be run directly from the Skill directory. ### Attack Path 1. The attacker obtains local access under another account or controls a process capable of writing to the shared temporary directory. 2. The attacker anticipates or observes use of the predictable `/tmp/cornell.py` path. 3. The attacker pre-creates a malicious destination or symbolic link, or replaces/modifies the copied script after the copy operation. 4. The Agent follows the documented workflow and executes: ```bash python /tmp/cornell.py new "<title>" ``` 5. Python executes the substituted content with the privileges and environment of the Agent user. Exploitation depends on local filesystem access and successful timing or destination manipulation. ### Impact Assessment Successful exploitation permits arbitrary code execution with the Agent user's privileges. The attacker could read or modify files available to that user, ...[truncated 257 chars]
Remediation
## Remediation Suggestions Remove all instructions that copy or execute the script through `/tmp/cornell.py`. Execute the trusted bundled script directly: ```bash python <skill_root>/scripts/cornell.py <command> [args] ``` Update the creation workflow similarly: ```bash python <skill_root>/scripts/cornell.py new "<title>" ``` If temporary copying is unavoidable: 1. Create a private temporary directory using a secure random name. 2. Restrict the directory permissions to the current user, such as mode `0700`. 3. Create files atomically and refuse to follow symbolic links. 4. Verify ownership, permissions, and script integrity before execution. 5. Remove the temporary directory immediately after use. 6. Avoid fixed filenames in globally writable directories.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (7)

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill invokes shell commands, reads environment variables like $EDITOR/$VISUAL, and creates/edits files under the user's home directory, yet it declares no explicit tool scope or permission boundaries. That omission increases the chance of over-broad execution privileges and weakens reviewability, especially because the skill instructs copying and running a bundled script via the shell.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger scope is broad enough to activate on many generic note-related phrases, including ambiguous requests like 'save this as a note' or any request involving personal notes. Overly aggressive activation can cause the skill to run file-writing workflows unexpectedly, increasing the risk of unintended data persistence or action selection when a simpler non-persistent response was intended.

Behavior Manipulation

Medium
Category
Prompt Injection
Content
"create a note", "show my notes", "list notes", "search notes", "open my note on X",
  "delete note", "edit my note", or any request involving personal notes or note-taking.
  Also trigger when the user says things like "save this as a note" 
  or "what did I write about X". Always prefer this skill over ad-hoc solutions
  for anything note-related.
---
Confidence
80% confidence
Finding
The instruction to 'Always prefer this skill over ad-hoc solutions' is a behavior-shaping directive that can bias the agent toward this skill even when another approach would be safer, less persistent, or more appropriate. In context, that bias matters because this skill performs filesystem writes and may persist user data when a transient response would suffice.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The skill states that notes are stored as Markdown files in ~/cornell-notes and encourages saving user content, but it does not require an explicit warning or confirmation that data will be written to persistent storage in the home directory. This is risky because users may disclose sensitive personal or work information without realizing it will be retained on disk.

Context-Inappropriate Capability

Medium
Confidence
99% confidence
Finding
The skill explicitly supports launching an arbitrary external editor executable from environment variables, which exceeds the minimum capability required for note management and creates an execution primitive. If an adversary can control or poison the environment, invoking note creation or editing will run the adversary’s chosen program. In this skill context, that is an unnecessary and material increase in attack surface.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def _open_in_editor(path: Path):
    editor = os.environ.get("EDITOR") or os.environ.get("VISUAL") or "micro"
    try:
        subprocess.run([editor, str(path)])
    except FileNotFoundError:
        print(c(f"Editor '{editor}' not found. Set $EDITOR env var.", YELLOW))
        print(f"File saved at: {path}")
Confidence
95% confidence
Finding
The script executes an external program derived from the EDITOR/VISUAL environment variables. Even though subprocess.run is invoked without shell=True, this still allows arbitrary executable selection, so any caller who can influence the environment can cause unintended code execution when a user creates or edits a note. In a note-management skill, launching arbitrary host executables expands the trust boundary beyond simple file operations and is riskier than the skill’s stated purpose suggests.

Tainted flow: 'editor' from os.environ.get (line 312, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Content
def _open_in_editor(path: Path):
    editor = os.environ.get("EDITOR") or os.environ.get("VISUAL") or "micro"
    try:
        subprocess.run([editor, str(path)])
    except FileNotFoundError:
        print(c(f"Editor '{editor}' not found. Set $EDITOR env var.", YELLOW))
        print(f"File saved at: {path}")
Confidence
98% confidence
Finding
There is a real tainted-data flow from environment-controlled input (EDITOR/VISUAL) into subprocess.run. This permits execution of an attacker-chosen binary whenever the edit path is triggered, which is effectively arbitrary code execution in the user context if the environment is attacker-influenced. The skill context makes this more dangerous because users expect note manipulation, not process launching based on ambient environment state.

Static analysis

No suspicious patterns detected.