Back to skill

Security audit

Quote

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to be a local quote/logging CLI, but its documented quote features and command behavior do not line up, and it stores user input persistently in plaintext.

Install only if you are comfortable with a simple local plaintext logger rather than a full quote analysis tool. Do not submit secrets, credentials, private notes, or sensitive business text unless the storage directory and files are locked down and you have a plan to delete old logs.

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
scripts/script.sh:6
Finding

Locally Stored User Data Is Created Without Restrictive Permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/script.sh:6-9, with repeated file writes at scripts/script.sh:124-297
Vulnerability Type: Insecure file and directory permissions
Risk Level: Medium

Vulnerable Code

bash
DATA_DIR="${HOME}/.local/share/quote"
mkdir -p "$DATA_DIR"

_log() { echo "$(date '+%m-%d %H:%M') $1: $2" >> "$DATA_DIR/history.log"; }

A representative input-storage branch is:

bash
run)
    shift
    if [ $# -eq 0 ]; then
        echo "Recent run entries:"
        tail -20 "$DATA_DIR/run.log" 2>/dev/null || echo "  No entries yet. Use: quote run <input>"
    else
        local input="$*"
        local ts=$(date '+%Y-%m-%d %H:%M')
        echo "$ts|$input" >> "$DATA_DIR/run.log"
        local total=$(wc -l < "$DATA_DIR/run.log")
        echo "  [Quote] run: $input"
        echo "  Saved. Total run entries: $total"
        _log "run" "$input"
    fi
    ;;

The same storage pattern is repeated for the check, convert, analyze, generate, preview, batch, compare, export, config, status, and report commands.

Technical Analysis

The script stores complete command inputs in files beneath ~/.local/share/quote/, but it neither establishes a restrictive process umask nor explicitly assigns private permissions to the directory and files.

Consequently, permissions depend on the invoking environment. With a common 022 umask, mkdir -p can create the quote directory with mode 0755, while shell redirection can create log and export files with mode 0644. If parent-directory traversal is permitted, other local accounts may therefore read the stored records.

Each submitted value is written both to a command-specific log and, through _log, to history.log. This duplication increases the number of files from which user-entered content may be disclosed. Export files created by _export are subject to ...[truncated 1313 chars]

Remediation
View remediation

Remediation Suggestions

  1. Establish a private umask before creating any files:

    bash
    umask 077
    
  2. Create and validate the data directory with owner-only access:

    bash
    DATA_DIR="${HOME}/.local/share/quote"
    mkdir -p -- "$DATA_DIR"
    chmod 700 -- "$DATA_DIR"
    
  3. Restrict existing and newly created data files:

    bash
    find "$DATA_DIR" -maxdepth 1 -type f -exec chmod 600 -- {} +
    
  4. Create export files atomically with mode 0600, and avoid following unexpected symbolic links. Where available, use a secure temporary file in the protected directory and rename it after the export is complete.

  5. Consider removing duplicate plaintext values from history.log, or log only command names and timestamps when the full input is unnecessary.

  6. Document that users should not enter credentials or secrets. Provide a retention or deletion command so stored records can be securely managed.

  7. Before writing, verify that the data directory is owned by the current user and is not a symbolic link or an unexpectedly shared location.

Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill’s documented purpose is narrowly quote-related, but the command surface and examples describe a much broader activity logger and generic utility interface. This is dangerous because users or an invoking agent may provide arbitrary sensitive text under the assumption it is being handled as a quote tool, while the skill persistently stores and exports that content without clear scope boundaries.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill description encourages use across many loosely defined tasks such as saving favorites, checking attribution, converting collections, analyzing themes, and generating picks, without clear trigger boundaries. In agent ecosystems, broad invocation guidance increases the chance the skill is selected for unrelated inputs, leading to unnecessary local collection and logging of sensitive content.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The documentation frames the skill as a quote tool, but the listed commands expand into generic operations like config, report, batch, compare, and run without clear quote-only constraints. In an agent setting, this ambiguity can cause over-broad invocation and unintended handling or retention of unrelated user data.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest says this skill is for recording, searching, and displaying quotes and sayings, including attribution and theme analysis. However, the help text and command surface expose a broad 'utility toolkit' with generic commands like run, check, preview, batch, compare, config, status, and report, and the rest of the script merely stores arbitrary input strings under those labels rather than performing quote-specific operations.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The help text states 'export Export (json|csv|txt)', implying a functional exporter. In the case statement, the first 'export)' branch at L243-L257 captures the command and only records input to export.log; because case arms are matched in order, the later real '_export' dispatch at L304 is unreachable, so the documented behavior is contradicted by actual execution.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The help text describes 'status' as a health check, which matches the dedicated _status function. But the earlier 'status)' case at L273-L287 intercepts the command and just appends user input to status.log; the later '_status' dispatch at L307 is unreachable, so the documented status behavior is contradicted by the implemented control flow.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Commands such as check, convert, analyze, generate, compare, report, and config suggest substantive processing relevant to quotes, but each branch only appends the provided text to a corresponding log file and echoes it back. This diverges from the manifest's promise of checking attribution, converting collections, analyzing themes, and generating picks, because no such behavior exists in code.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script persistently stores user-supplied input in plaintext under ~/.local/share/quote/*.log and appends it to history.log without any notice, consent, retention limit, or sensitivity filtering. In this skill context, users may enter personal notes, favorite quotes, API snippets, or other sensitive text believing they are using a quote utility, so undisclosed retention increases privacy and data-exposure risk on multi-user or compromised systems.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The claim at L017 states an absolute offline guarantee, yet the same file includes external homepage and feedback URLs, implying at least some documented interaction with remote services. While the file does not show executable network code, the documentation itself presents conflicting intent about whether the skill is fully offline.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

Automatic history and activity logging materially affects privacy expectations, especially for a skill that may receive arbitrary user text. If the logging behavior is not prominently disclosed near the description and usage guidance, users and agents may submit sensitive content without understanding it will be retained on disk.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.