Back to skill

Security audit

Agent Dream Journal

Security checks for vulnerabilities and agentic risk

Overview

This is a simple local journal tool whose plaintext recording of supplied reasoning text is purpose-aligned but privacy-sensitive.

Install only if you are comfortable with a local plaintext journal. Do not pass secrets, credentials, private prompts, personal data, or confidential customer content in `--thought` or `--meta`; run it from a private directory and delete `agent_dreams.jsonl` when no longer needed.

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
tool.py:18
Finding
Plaintext Storage and Disclosure of Potentially Sensitive Agent Reasoning## Vulnerability Details **File Location**: `tool.py`, lines 18-29, 32-49, and 83-85 **Vulnerability Type**: Plaintext sensitive-data storage and output **Risk Level**: Medium ### Vulnerable Code ```python log_entry = { "timestamp": timestamp, "epoch_ms": step_data.get("epoch", timestamp * 1000), "state_embedding": step_data.get("state", []), "action_log_prob": step_data.get("log_prob", 0.0), "thought_chain": step_data.get("thought", ""), "novelty_score": step_data.get("novelty", 0.0), "metadata": step_data.get("meta", {}) } with open("agent_dreams.jsonl", "a") as f: f.write(json.dumps(log_entry) + "\n") ``` ```python def analyze_dreams(threshold: float = 0.8) -> List[Dict[str, Any]]: """Parse recorded dreams and extract high-novelty thought chains.""" insights = [] if not os.path.exists("agent_dreams.jsonl"): print("No dream data found. Run with --record first.") return [] with open("agent_dreams.jsonl", "r") as f: for line in f: try: entry = json.loads(line.strip()) if entry["novelty_score"] >= threshold: insights.append(entry) except json.JSONDecodeError: continue # Skip malformed lines return insights ``` ```python for i, dream in enumerate(insights, 1): print(f"{i}. [{dream['timestamp']}] {dream['thought'][:100]}...") ``` ### Technical Analysis The application deliberately captures the value supplied through `--thought`, together with state embeddings and arbitrary metadata, and stores the resulting record in `agent_dreams.jsonl`. The file is created using the process's default permissions, subject only to its current `umask`. No explicit private permission mode, encryption, secret filtering, data minimization, or retention policy is applied. Internal reasoning and metadata can contain credentials ...[truncated 1506 chars]
Remediation
## Remediation Suggestions - Do not collect hidden reasoning or unrestricted internal thought chains. Accept a deliberately sanitized summary containing only information needed for analysis. - Document that journal input must not contain credentials, tokens, personal data, or proprietary context. - Create the journal in a private, application-controlled directory rather than the caller's current working directory. - Create new files with permissions equivalent to `0600`, independently of the ambient `umask`. - Apply schema validation and secret redaction to thought and metadata fields before persistence. - Encrypt sensitive records at rest when persistent storage is necessary, with keys kept separately from the journal. - Add configurable retention limits, secure deletion, and an explicit command for clearing stored records. - Avoid printing raw reasoning. Display sanitized summaries and require an explicit opt-in before outputting sensitive fields. - Warn users when output is likely to enter CI or centralized logs.

T09 · Insecure Skill Coding Practices

Warning
Location
tool.py:28
Finding
Predictable Journal Path Permits Symbolic-Link File Redirection## Vulnerability Details **File Location**: `tool.py`, lines 28-29 and 38-42 **Vulnerability Type**: Unsafe fixed-path file handling and symbolic-link following **Risk Level**: Medium ### Vulnerable Code ```python with open("agent_dreams.jsonl", "a") as f: f.write(json.dumps(log_entry) + "\n") ``` ```python if not os.path.exists("agent_dreams.jsonl"): print("No dream data found. Run with --record first.") return [] with open("agent_dreams.jsonl", "r") as f: for line in f: ``` ### Technical Analysis The application uses a predictable relative filename in the current working directory and opens it with normal Python file operations. These operations follow symbolic links. The code does not verify that the path is a regular file, confirm ownership, reject links, or ensure that the containing directory is trusted. In an attacker-controlled or shared working directory, an attacker can create `agent_dreams.jsonl` as a symbolic link before the victim runs the program. Record mode then appends attacker-influenced JSON to the link target with the victim process's filesystem permissions. Analyze mode is also susceptible to path redirection. An attacker can point the journal path at a chosen JSONL-compatible file or replace the path between the existence check and the open operation. Crafted entries may then be presented as legitimate dream records. This is primarily an integrity and local file-safety issue; the reviewed code does not execute journal contents. ### Attack Path 1. The attacker obtains write access to the directory from which the victim will run the tool. 2. The attacker creates a symbolic link named `agent_dreams.jsonl` targeting another file writable by the victim. 3. The victim invokes `python tool.py record` from that directory. 4. Python follows the symbolic link while opening the predictable filename in append mode. 5. The program appends serialized journal content to the target ...[truncated 1170 chars]
Remediation
## Remediation Suggestions - Store journals beneath a private application data directory owned by the invoking user, with directory permissions equivalent to `0700`. - Open the file through `os.open` using `O_CREAT | O_APPEND | O_WRONLY | O_NOFOLLOW`, where supported, and request mode `0600`. - After opening, use `os.fstat` to confirm that the descriptor references a regular file and that its owner is the expected user. - Convert the validated descriptor to a Python file object with `os.fdopen` rather than reopening the path. - Apply equivalent no-follow and regular-file checks when opening the journal for analysis. - Do not rely on a separate existence check before opening the file; this creates an avoidable check-to-use race. - Refuse to operate when the journal directory is group-writable or world-writable unless explicit safe ownership and sticky-directory requirements are met. - If portability prevents use of `O_NOFOLLOW`, use a securely created private directory and verify the resolved path, ownership, and file type before processing.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (4)

Ssd 3

High
Confidence
97% confidence
Finding
The code explicitly records 'thought_chain' in plain text to disk, creating a direct data-exfiltration and privacy-leak path for sensitive model internals or user content. In the context of an agent skill, storing chain-of-thought-like traces is especially dangerous because they may include credentials, personal data, hidden prompts, or intermediate reasoning that should never be retained or exposed.

Ssd 3

High
Confidence
96% confidence
Finding
The analysis mode prints previously captured thought content back to stdout, which can expose sensitive information to terminal history, logs, calling applications, or users who should not see it. Even truncated output still leaks content and confirms the presence of sensitive traces collected earlier.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The tool persists internal reasoning traces and metadata to a local JSONL file without warning, consent, minimization, or access controls. In an agent setting, these traces can contain sensitive user-derived content, secrets, or operational details that remain on disk and may be read later by other users, processes, backups, or logs.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The recording path stores reasoning text under the key 'thought_chain' (L19, L73-L78), and the analyzer claims it will 'extract high-novelty thought chains' (L29). However, output formatting later reads dream['thought'] (L86), which does not match the stored schema and prevents the advertised thought-chain extraction from actually working.

Static analysis

No suspicious patterns detected.