Back to skill

Security audit

Mini Diary

Security checks for vulnerabilities and agentic risk

Overview

This diary skill is mostly purpose-aligned, but it needs review because it can write or copy sensitive diary data through broadly scoped paths and includes risky NextCloud admin guidance.

Review before installing. Use a dedicated .md diary file, do not point DIARY_FILE at shell profiles or other important files, leave NEXTCLOUD_SYNC_DIR unset unless you intentionally want the full diary copied to a sync location, and avoid the sudo/docker/recursive chown and cron examples unless you have verified the exact target paths and understand the system impact.

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

Error
Location
scripts/add_note.sh:13
Finding
Insufficient Path Validation Allows Arbitrary User-Scoped File Modification and Unsafe NextCloud Copies## Vulnerability Details **File Location**: `scripts/add_note.sh:13-45`, `scripts/add_note.sh:54-55`, `scripts/add_note.sh:135-159`, and `scripts/add_note.sh:165-179` **Vulnerability Type**: Improper path validation and arbitrary file write **Risk Level**: High ### Vulnerable Code ```bash validate_safe_path() { local path="$1" local purpose="$2" # Convert to absolute path local abs_path=$(realpath -m "$path" 2>/dev/null || echo "$path") # Security checks if [[ "$abs_path" =~ ^/etc/ ]]; then echo "❌ Security error: Cannot write to system directory /etc/" >&2 exit 1 fi if [[ "$abs_path" =~ ^/usr/ ]]; then echo "❌ Security error: Cannot write to system directory /usr/" >&2 exit 1 fi if [[ "$abs_path" =~ ^/bin/|^/sbin/|^/lib/|^/lib64/ ]]; then echo "❌ Security error: Cannot write to system binaries directory" >&2 exit 1 fi # Ensure it's within user's home or current directory local user_home="${HOME:-/tmp}" if [[ ! "$abs_path" =~ ^$user_home ]] && [[ ! "$abs_path" =~ ^$(pwd) ]]; then echo "⚠️ Warning: $purpose path is outside user directory: $abs_path" >&2 echo " Only writing to user home or current directory is allowed for safety." >&2 exit 1 fi # Ensure it's a .md file for diary if [[ "$purpose" == "diary" ]] && [[ ! "$abs_path" =~ \.md$ ]]; then echo "⚠️ Warning: Diary file should have .md extension" >&2 # Allow but warn fi echo "$abs_path" } DEFAULT_DIARY="$HOME/diary.md" DIARY_FILE="${DIARY_FILE:-$DEFAULT_DIARY}" DIARY_FILE=$(validate_safe_path "$DIARY_FILE" "diary") ``` The validated path is subsequently modified without enforcing the Markdown extension: ```bash # Check if diary file exists, create if not if [ ! -f "$DIARY_FILE" ]; then echo "# 📓 ...[truncated 4451 chars]
Remediation
## Remediation Suggestions 1. Restrict diary files to a dedicated canonical directory, such as `$HOME/.local/share/mini-diary/`, rather than permitting every file below the home directory. 2. Canonicalize both the target and its parent directory. For a new file, resolve the parent with `realpath` and then append a validated basename. 3. Compare canonical paths using path-component-aware string logic rather than regular expressions. For example, accept only the exact root or paths beginning with `"$allowed_root/"`. 4. Reject diary paths that do not end in `.md`; do not merely warn. 5. Reject symbolic links for diary files and synchronization destinations, or explicitly resolve them and validate the resolved destination. 6. Validate `NEXTCLOUD_SYNC_DIR` against a separately configured, canonical synchronization root. 7. Write new files atomically with restrictive permissions and avoid following links. Where supported, use secure file-descriptor operations with no-follow semantics. 8. Reject control characters, including carriage returns and newlines, in note input if each invocation is intended to create one Markdown list item. 9. Add tests for sibling-prefix paths, regex metacharacters in `HOME`, non-Markdown targets, multiline note input, and symlinked NextCloud destinations.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/search_diary.sh:75
Finding
User-Controlled Search Terms Are Interpreted as grep Options## Vulnerability Details **File Location**: `scripts/search_diary.sh:75-92` and `scripts/search_diary.sh:121-138` **Vulnerability Type**: Argument and option injection **Risk Level**: Medium ### Vulnerable Code ```bash search_by_tag() { local tag="$1" echo "🔍 Searching for tag: $tag" echo "======================" grep -n "$tag" "$DIARY_FILE" | while IFS=: read -r line_num content; do # Get date context local date_line=$(grep -B10 ":$line_num:" <(cat -n "$DIARY_FILE") | grep "## 📅" | tail -1) if [ -n "$date_line" ]; then local date_info=$(echo "$date_line" | sed 's/.*## 📅 //') echo "📅 $date_info" fi echo "📝 $content" echo "---" done local count=$(grep -c "$tag" "$DIARY_FILE" 2>/dev/null || echo 0) echo "📊 Found $count notes with tag: $tag" } ``` ```bash search_in_content() { local query="$1" echo "🔍 Searching for: \"$query\"" echo "======================" grep -i -n "$query" "$DIARY_FILE" | while IFS=: read -r line_num content; do # Get date context local date_line=$(grep -B10 ":$line_num:" <(cat -n "$DIARY_FILE") | grep "## 📅" | tail -1) if [ -n "$date_line" ]; then local date_info=$(echo "$date_line" | sed 's/.*## 📅 //') echo "📅 $date_info" fi echo "📝 $content" echo "---" done local count=$(grep -i -c "$query" "$DIARY_FILE" 2>/dev/null || echo 0) echo "📊 Found $count notes containing: \"$query\"" } ``` ### Technical Analysis Shell quoting prevents word splitting and shell metacharacter execution, but it does not stop a value beginning with `-` from being interpreted as a command-line option by `grep`. The calls omit the conventional `--` end-of-options delimiter. Consequently, a crafted tag or content query can change `grep` behavi ...[truncated 1507 chars]
Remediation
## Remediation Suggestions 1. Add an explicit end-of-options delimiter to every invocation that accepts user input: ```bash grep -n -- "$tag" "$DIARY_FILE" grep -c -- "$tag" "$DIARY_FILE" grep -i -n -- "$query" "$DIARY_FILE" grep -i -c -- "$query" "$DIARY_FILE" ``` 2. Use fixed-string matching when regular expressions are not an intended feature: ```bash grep -F -n -- "$tag" "$DIARY_FILE" grep -F -i -n -- "$query" "$DIARY_FILE" ``` 3. Apply the same `--` convention consistently to all command invocations receiving variable data. 4. Add regression tests with values such as `-n`, `-e`, `-fFILE`, `--help`, and strings containing regular-expression metacharacters. 5. Consider imposing a reasonable maximum search-term length to limit accidental or malicious resource consumption.
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
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The description presents a broader diary application with AI assistance, automatic tagging, and optional cloud synchronization. The supplied code is only a search utility over an existing local diary file. It validates the path, reads the file, searches by tag/date/content, computes simple tag statistics, and lists tags. There is no journaling interface, no note creation or modification, no AI behavior, no tagging engine, and no network/cloud operations. This is a material description-to-behavior mismatch, even though the code is plausibly related to a diary system.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents an end-user diary application with AI tagging and optional cloud sync. The supplied code chunk does not implement diary features, tagging, syncing, or journaling workflows. Instead, it is a security test harness for shell scripts, focused on validating safe path handling, permission operations, and command hygiene. These behaviors are materially different from the declared primary purpose, so this is a description/behavior mismatch.

Instruction Override

High
Category
Prompt Injection
Content
**Solution**: Ensure installation completed and scripts are executable

**Problem**: Tags not appearing
**Solution**: Check note content matches tag rules, enable debug mode

**Problem**: Search returns no results
**Solution**: Verify diary file exists and has content
Confidence
70% confidence
Finding
This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding
The skill uses 'shell' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill encourages optional NextCloud sync for diary entries, which may contain sensitive personal or work information, but it does not prominently warn users that enabling sync copies that content to external storage and may expose it through server, admin, backup, or misconfiguration risks. This can lead users to unintentionally disclose private journal data beyond the local machine.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The guide states that diary content is automatically copied and synced to a NextCloud directory but does not clearly warn that journal entries may contain sensitive personal, work, or financial information. Users could enable sync without understanding the privacy, retention, access-control, or multi-device exposure implications, increasing the chance of unintended data disclosure.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
ls -la /path/to/nextcloud/diary/diary.md

# Fix ownership (if needed)
sudo chown www-data:www-data /path/to/nextcloud/diary/diary.md

# Docker version
docker exec nextcloud_app chown www-data:www-data /var/www/html/data/.../diary.md
Confidence
88% confidence
Finding
The documentation instructs users to run privileged ownership-changing commands against NextCloud-managed files. Even though this is operational guidance, normalizing sudo/chown in a diary skill can cause accidental permission damage, broaden access to sensitive diary data, or encourage unsafe copy-paste execution in environments where paths are incorrect.

Session Persistence

Medium
Category
Rogue Agent
Content
```

### Custom Tags
Create `~/.mini-diary-tags.json`:
```json
{
  "custom_tags": {
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
**Solution**:
```bash
# Fix ownership
sudo chown -R www-data:www-data /path/to/nextcloud/diary/

# Or for Docker
docker exec nextcloud_app chown -R www-data:www-data /var/www/html/data/.../
Confidence
90% confidence
Finding
This troubleshooting advice recommends recursive ownership changes with sudo or container-level chown across an entire NextCloud diary directory. Recursive privileged file operations are especially risky because a mistaken path or misunderstanding of deployment layout can alter permissions on large data sets and expose or disrupt synced personal records.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The manifest advertises "cloud sync" functionality but provides no user-facing warning or privacy notice about possible transmission of diary contents to external services. Because this skill handles highly sensitive personal journal data, users may unknowingly expose intimate or work-related information off-device, making the omission materially risky even in metadata.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The script’s security claims are inaccurate: it states there is no network access and only safe diary-file writes, yet it optionally copies the diary into a user-controlled NextCloud sync directory via the NEXTCLOUD_SYNC_DIR environment variable. Even though the script does not itself open a network connection, placing sensitive diary contents into a sync folder can trigger unintended cloud exfiltration and weakens user trust in the documented security boundary.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The installer’s comments and security messaging state it only copies files and sets permissions, but it also writes new files into the user’s home directory, including a default diary and config example. Misleading security claims reduce informed consent and can cause users or automation to trust the script more than warranted, especially since self-asserted safety language is a red flag in adversarial review.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
if [ -d "$INSTALL_DIR/scripts" ]; then
    for script in "$INSTALL_DIR/scripts/"*.sh; do
        if [ -f "$script" ] && [ -O "$script" ]; then  # -O checks if file is owned by effective user
            chmod 755 "$script"
            echo "  ✓ $(basename "$script") set to 755"
        else
            echo "  ⚠️  Skipping $(basename "$script") - not owned by user"
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Session Persistence

Medium
Category
Rogue Agent
Content
done
fi

# Create default diary file if it doesn't exist
DEFAULT_DIARY="$HOME/diary.md"
if [ ! -f "$DEFAULT_DIARY" ]; then
    echo "📓 Creating default diary file: $DEFAULT_DIARY"
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Intent-Code Divergence

Medium
Confidence
88% confidence
Finding
The header and disclaimer state that the script only reads user diary files, implying access is limited to an actual diary file. In practice, DIARY_FILE is taken from the environment and accepted as any file under HOME or the current directory, so the script can be used to search arbitrary user-accessible files rather than specifically a diary.

Intent-Code Divergence

Low
Confidence
97% confidence
Finding
The output in list_tags tells users that tags are automatically added based on note content, which describes tagging behavior not implemented anywhere in this file. This is an intent/documentation mismatch because the script is purely read-only search/statistics functionality.

Missing User Warnings

Low
Confidence
83% confidence
Finding
This markdown file includes operational instructions to run `docker exec nextcloud_app php occ files:scan [username]`, which affects a live NextCloud instance and user file indexing. The section labels the step as 'Important' but does not warn users about the command's impact, expected context, or that it should only be run against the intended account/server.

Static analysis

No suspicious patterns detected.