Back to skill

Security audit

Memory Curator

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly does what it says, but its digest script accepts an unchecked date argument that can escape the intended memory folder and read or overwrite other accessible Markdown files.

Install only if you are comfortable with a local script reading your Clawd memory logs and writing digest files. Until the date argument is validated and existing digest overwrites are handled more carefully, avoid running it with any untrusted or non-YYYY-MM-DD argument and be cautious about automating it with cron.

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/generate-digest.sh:9
Finding
Path Traversal Through Unvalidated Date Argument<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate-digest.sh`, lines 9-11, 16-19, and 61-64 **Vulnerability Type**: Path traversal resulting in unauthorized file reads and file overwrites **Risk Level**: Medium ### Vulnerable Code ```bash MEMORY_DIR="$HOME/clawd/memory" DATE="${1:-$(date -u +%Y-%m-%d)}" LOG_FILE="$MEMORY_DIR/$DATE.md" DIGEST_FILE="$MEMORY_DIR/digests/$DATE-digest.md" # Check if log exists if [ ! -f "$LOG_FILE" ]; then echo "Error: No log found at $LOG_FILE" exit 1 fi # Generate digest skeleton mkdir -p "$MEMORY_DIR/digests" cat > "$DIGEST_FILE" << EOF ``` ### Technical Analysis The command-line argument is documented as a date in `YYYY-MM-DD` format, but the script neither validates that format nor verifies that the resulting paths remain inside `$MEMORY_DIR`. The attacker-controlled `DATE` value is directly embedded in both `LOG_FILE` and `DIGEST_FILE`. Although the variables are correctly quoted and therefore do not permit shell command injection, quoting does not prevent filesystem traversal through `../` components. By supplying enough parent-directory components, a caller can make the source path resolve outside `$HOME/clawd/memory` and make the destination path resolve outside `$HOME/clawd/memory/digests`. The `.md` and `-digest.md` suffixes restrict which filenames can be targeted, but do not enforce the intended directory boundary. The script reads the selected source file through commands such as `wc`, `grep`, `sed`, and `awk`, then incorporates extracted content into a newly generated digest file. ### Attack Path 1. The attacker creates or identifies a readable file outside the memory directory whose name ends in `.md`. 2. The attacker supplies a traversal string instead of a valid date, for example: ```bash ./scripts/generate-digest.sh "../../../../../../tmp/source" ``` 3. After path normalization, `LOG_FILE` can resolve to `/tmp/source.md`, assuming a typical home-directory layout and ...[truncated 1364 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Enforce the documented date format before constructing any path: ```bash if [[ ! "$DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then echo "Error: Date must use YYYY-MM-DD format" >&2 exit 1 fi ``` 2. Validate that the value represents a real calendar date: ```bash if ! parsed_date=$(date -u -d "$DATE" +%Y-%m-%d 2>/dev/null) || [[ "$parsed_date" != "$DATE" ]]; then echo "Error: Invalid calendar date" >&2 exit 1 fi ``` Use a platform-appropriate equivalent where GNU `date` is unavailable. 3. Resolve and verify the source and destination paths before accessing them. Their canonical paths must remain beneath the intended directories: ```bash MEMORY_DIR=$(realpath "$HOME/clawd/memory") DIGEST_DIR="$MEMORY_DIR/digests" mkdir -p "$DIGEST_DIR" LOG_FILE=$(realpath -m "$MEMORY_DIR/$DATE.md") DIGEST_FILE=$(realpath -m "$DIGEST_DIR/$DATE-digest.md") case "$LOG_FILE" in "$MEMORY_DIR"/*) ;; *) echo "Error: Source path escapes memory directory" >&2; exit 1 ;; esac case "$DIGEST_FILE" in "$DIGEST_DIR"/*) ;; *) echo "Error: Destination path escapes digest directory" >&2; exit 1 ;; esac ``` 4. Use restrictive creation permissions where digests may contain sensitive information: ```bash umask 077 ``` 5. Consider refusing to overwrite an existing digest unless the user explicitly supplies an overwrite option. If overwriting is required, write to a securely created temporary file in the digest directory and atomically rename it after successful generation. ]]>
Vulnerability Patterns
  • 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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (1)

Missing User Warnings

Low
Confidence
87% confidence
Finding
This code creates and overwrites a markdown digest file containing extracted names, timestamps, sections, and other information from the user's daily log. While the script prints success messages afterward, there is no prior warning, confirmation, or explanatory notice about writing a new file with potentially sensitive personal data.

Static analysis

No suspicious patterns detected.