Back to skill

Security audit

Novel

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to be a local novel-note logging tool, but it is under-scoped and retains potentially private writing content in plaintext with weak controls.

Install only if you are comfortable with private writing notes or prompts being stored locally in plaintext under ~/.local/share/novel. Avoid entering unpublished manuscript text or sensitive notes unless the tool adds clear delete/export controls and hardens file permissions. This review found no remote payloads, credential access, privilege escalation, or destructive behavior.

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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/script.sh:6
Finding

Locally Stored User Data Inherits Potentially Insecure Filesystem Permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/script.sh:6-9
Vulnerability Type: Insecure file permissions
Risk Level: Medium

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

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

Technical Analysis

The application stores user-supplied novel content and activity history beneath ~/.local/share/novel, but it does not establish owner-only permissions for the directory or files. Both directory creation and subsequent output redirection inherit permissions from the process's current umask.

If the application is executed with a permissive umask, the resulting directory or files may be readable or writable by other local users. The stored data can include unpublished manuscript content and a history of user activity.

This issue does not independently provide remote access or elevated privileges. Exploitation requires another account or process with local filesystem access and permissions granted by the resulting mode bits.

Attack Path

  1. A victim executes the script in an environment with a permissive umask.
  2. The script creates ~/.local/share/novel without explicitly applying mode 0700.
  3. Log files are created through shell redirection without explicitly applying mode 0600.
  4. The victim submits manuscript content or other private text, which is written to these files.
  5. Another local user or process reads or modifies the files if the inherited permissions permit access.

Impact Assessment

Exploitation may disclose unpublished manuscript content, command inputs, and activity history to other local users. If write access is inherited, another local user may also corrupt or replace application records.

The scope is limited to data accessible through the affected directory and files. This vulnerability does not grant administrative privileges or direct code execution.

Remediation
View remediation

Remediation Suggestions

  • Set a restrictive process mask before creating or writing sensitive data:

    bash
    umask 077
    
  • Create the data directory with explicit owner-only permissions:

    bash
    install -d -m 700 "$DATA_DIR"
    
  • Ensure existing directories and files are hardened:

    bash
    chmod 700 "$DATA_DIR"
    find "$DATA_DIR" -type f -exec chmod 600 {} +
    
  • Verify that the directory is owned by the current user before writing to it.

  • Reject symbolic links and unexpected filesystem objects where practical, particularly if the execution environment may be influenced by another local account.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/script.sh:129
Finding

Unescaped User Input Permits Log Record Injection

Content
View full analysis

Vulnerability Details

File Location: scripts/script.sh:129-133
Vulnerability Type: Log injection and record-boundary corruption
Risk Level: Low

bash
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 "  [Novel] run: $input"

Equivalent unescaped writes occur in the other command handlers at lines 144-296.

Technical Analysis

Command arguments are concatenated and written directly into pipe-delimited log records. The input is not validated or encoded before storage. An argument containing a newline can terminate the intended record and add arbitrary attacker-controlled lines. A pipe character can also alter the expected field structure.

For example, an argument containing a newline followed by a fabricated timestamp and value can make one command invocation appear to be multiple stored records. This is an integrity flaw rather than shell command injection because the value is expanded inside a quoted string and is not evaluated as shell syntax.

The dormant export implementation also inserts stored values directly into JSON and CSV without context-appropriate escaping at lines 68 and 78. However, the current dispatcher contains earlier duplicate export branches, making _export unreachable in the reviewed version. Consequently, malformed export generation is not presently a complete runtime attack path, but the unsafe serializer should still be corrected before it is made reachable.

Attack Path

  1. An attacker supplies crafted input to one of the logging commands, such as an argument containing embedded newline or pipe characters.
  2. The command handler concatenates the arguments into input.
  3. The script appends the value directly to a pipe-delimited log file.
  4. Embedded newlines create additional apparent records, while embedded pipes corrupt field boundaries.
  5. Subsequent recent, `se ...[truncated 547 chars]
Remediation
View remediation

Remediation Suggestions

  • Use a structured storage format rather than a custom unescaped pipe-delimited format.

  • Serialize records with a tool that correctly escapes values, such as jq for JSON.

  • If the existing format must be retained, reject or encode newlines, carriage returns, pipes, and other control characters before writing.

  • Use printf rather than echo for predictable output behavior:

    bash
    sanitized=${input//$'\r'/}
    sanitized=${sanitized//$'\n'/\\n}
    sanitized=${sanitized//|/\\|}
    printf '%s|%s\n' "$ts" "$sanitized" >> "$DATA_DIR/run.log"
    
  • Correct the duplicate export dispatcher branches before enabling export functionality.

  • For JSON export, use a standards-compliant serializer rather than interpolating values into JSON text.

  • For CSV export, apply RFC 4180 quoting and consider neutralizing cells beginning with =, +, -, or @ if files may be opened in spreadsheet software.

Vulnerability Patterns
  • 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
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (8)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The documented purpose is narrowly framed as managing novel-specific data, but the listed behavior is much broader and includes generic command capture, persistent logging, export, search, and status/report functions. That mismatch is dangerous because users may provide sensitive manuscript notes or prompts under the assumption of a focused local organizer, while the skill appears to retain and process arbitrary inputs in ways not clearly disclosed or scoped.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest describes a terminal tool for managing novel-specific data such as chapters, characters, and plots, but the exposed commands and implementation are generic verbs like run, check, convert, analyze, batch, config, and status. Across the file, these commands merely append arbitrary user input to per-command log files under ~/.local/share/novel, with no code representing novel entities or workflows.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill advertises automatic history and activity logging plus local storage, but it does not clearly warn that user inputs and actions will be persisted. This creates a privacy and confidentiality risk because users may enter sensitive story content, notes, or other text without realizing those inputs will be written to disk and retained.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The help output documents 'export Export (json|csv|txt)', implying a functional export feature. However, the case statement defines an earlier export branch that treats export like every other logging command, so the later 'export) shift; _export "$@" ;;' branch is unreachable and the documented behavior does not occur.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The documentation says status should perform a health check, and a dedicated _status function exists for that purpose. But the case dispatcher matches an earlier status branch that behaves like a generic log writer, making the later 'status) _status ;;' branch unreachable and contradicting the documented intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The export function aggregates all previously logged plaintext data into new files, multiplying the number of copies of sensitive content on disk. Because the tool is positioned around creative-work management, exports may contain unpublished manuscripts or private notes, increasing the chance of accidental disclosure through syncing, backups, or user sharing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

User-supplied content is persistently stored in plaintext log files under ~/.local/share/novel without any clear consent, minimization, or retention controls. In this skill context, users may enter plot notes, character bios, drafts, or other sensitive unpublished material, which can later be exposed to other local users, backup systems, or accidental sharing.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The tool records raw user inputs and later re-displays them via recent/search/status/export flows, creating a straightforward natural-language data leakage channel for sensitive content. In a novel-writing context this is more dangerous than generic telemetry because users are likely to paste proprietary drafts, personal notes, or other high-value text that remains readable in logs and terminal output.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.