Back to skill

Security audit

memory-recall

Security checks for vulnerabilities and agentic risk

Overview

This local note-search skill is not malicious, but it needs review because it can search personal files and persist usage data while its privacy boundaries are not fully enforced.

Install only if you are comfortable giving it access to selected local note folders. Use narrow roots, avoid folders containing secrets, and do not use the learner commands unless you accept local persistence of usage notes and preferences. Treat search output as potentially sensitive because redaction and symlink boundary checks are not implemented.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/memory_search.py:80
Finding

Search Results May Disclose Credentials and Other Sensitive Note Content

Content
View full analysis

Vulnerability Details

File Location: scripts/memory_search.py, lines 24–25 and 80–82
Vulnerability Type: Sensitive information exposure
Risk Level: Medium

Vulnerable Code:

python
with open(path, encoding="utf-8", errors="replace") as fh:
    lines = fh.read().splitlines()
python
print(f"\n📄 {r['path']}  (score={r['score']}, 命中{r['matched']}行)")
for ln, snippet in r["hits"][:5]:
    print(f"  L{ln}: {snippet[:160]}")

Technical Analysis

The search function reads the complete contents of every eligible note and returns matching excerpts without classifying or redacting sensitive information. The output includes both the source path and up to 160 characters from each selected context snippet.

Consequently, passwords, API tokens, private-key material, connection strings, recovery codes, or other secrets stored in Markdown or text notes may be emitted into terminal history, application logs, agent context, or downstream responses. This behavior also conflicts with the security boundary documented in SKILL.md, which states that credential-like content must not be exposed in responses.

The vulnerability does not independently grant access to files that the process cannot read. Exploitation requires a sensitive file to be included in the selected search scope and a query that causes its sensitive content or surrounding context to be returned.

Attack Path

  1. A credential or another secret is stored in an indexed .md, .txt, or .markdown file.
  2. The user or an attacker influencing the query submits a term appearing in or near the secret.
  3. score_file reads the complete file and constructs a context snippet around the matching line.
  4. main prints the snippet without sensitive-data detection or redaction.
  5. The secret becomes available through command output, logs, agent context, or a response generated from that output.

Impact Assessment

An attacker may ob ...[truncated 385 chars]

Remediation
View remediation

Remediation Suggestions

  • Apply output redaction before printing snippets. Detect common API-token formats, password assignments, authorization headers, connection strings, recovery codes, and private-key blocks.
  • Suppress or mask the sensitive value while retaining only enough surrounding context to identify the source safely.
  • Exclude known credential and secret files by default, including environment files, key files, password stores, and backup copies.
  • Require explicit confirmation before displaying a result classified as potentially sensitive.
  • Avoid placing raw search output in persistent logs or unrestricted agent context.
  • Add automated tests verifying that representative credentials and private-key blocks are never returned verbatim.

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/memory_search.py:7
Finding

Symbolic-Link Files Can Bypass the Selected Search-Root Boundary

Content
View full analysis

Vulnerability Details

File Location: scripts/memory_search.py, lines 7–11 and 24–25
Vulnerability Type: Search-root boundary bypass through symbolic links
Risk Level: Medium

Vulnerable Code:

python
def iter_text_files(root):
    for dirpath, _, files in os.walk(root):
        for f in files:
            if f.lower().endswith((".md", ".txt", ".markdown")):
                yield os.path.join(dirpath, f)
python
try:
    with open(path, encoding="utf-8", errors="replace") as fh:
        lines = fh.read().splitlines()
except Exception:
    return None

Technical Analysis

Candidate paths are selected according to their lexical location and filename extension, but the code does not resolve each candidate to its canonical path before opening it. Although os.walk does not follow symbolic-link directories by default, a symbolic link presented as an individual .md, .txt, or .markdown file can still be yielded and opened.

A file symlink located inside the authorized root can therefore point to a readable text file outside that root. The open operation follows the link, allowing external content to be searched and returned even though the documented security model states that only the user-selected directory should be searched.

Exploitation requires the attacker to create or control a symbolic-link file within the selected search tree. The external target must also be readable by the process.

Attack Path

  1. An attacker obtains write access to a directory that the user will select as the search root.
  2. The attacker creates a file symlink such as notes/external.txt that points to a readable file outside the selected root.
  3. The user runs memory_search.py against notes.
  4. iter_text_files accepts the symlink because its displayed filename has an allowed extension.
  5. open(path) follows the symbolic link and reads the out-of-scope target.
  6. If the quer ...[truncated 511 chars]
Remediation
View remediation

Remediation Suggestions

  • Resolve the root once with os.path.realpath and resolve every candidate before opening it.
  • Validate containment with os.path.commonpath; reject a candidate unless its canonical path remains under the canonical root.
  • Reject symbolic-link files explicitly with os.path.islink when links are not required.
  • Perform validation immediately before opening the file to reduce time-of-check/time-of-use exposure.
  • Where supported, open files using no-follow semantics such as O_NOFOLLOW, then validate the opened file descriptor.
  • Add tests covering file symlinks, chained symlinks, relative symlink targets, and links that point outside the authorized root.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared purpose is note retrieval, but the observed behavior includes usage analytics, preference storage, and self-reflection features that are not disclosed in the primary description. This mismatch is dangerous because users and policy systems may authorize the skill expecting passive search, while the skill also persists behavioral data and modifies local state, creating hidden privacy and trust risks.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file’s stated behavior is a generic cross-skill self-learning and telemetry mechanism, which is materially broader than the memory-recall skill’s declared purpose of local note retrieval. Capability mismatch is dangerous because it expands data collection and persistence beyond user expectations, creating an undeclared stateful tracking surface that could be reused by unrelated skills.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill advertises filesystem-related behavior but does not declare any explicit tool scope such as allowed tools or permission boundaries. For a skill that searches local notes and also references learner scripts that can record data, this omission weakens enforcement and makes it easier for the skill to read or write beyond the minimally necessary scope if the hosting agent grants broad defaults.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases are broad conversational requests such as asking to 'search my memory' or 'recall what we discussed before,' which can overlap with ordinary dialogue. This can cause unintended invocation of a skill that searches local files, increasing the chance of unnecessary access to personal notes or disclosure of sensitive snippets when the user did not intend a filesystem search.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The natural-language description and operational guidance are entirely in Chinese, with no indication that the user can choose another language or that the skill is intentionally limited to a Chinese-language context. Under the language/locale policy, a skill should not implicitly force a specific language without opt-in or clear regional justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The module docstring, CLI description, and output messages are all written in Chinese, with no indication that language is configurable or intentionally restricted to a region-specific context. This creates a language-policy issue because users are implicitly forced into one locale without opt-in.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The code stores cross-session preferences, operation history, error patterns, and notes in learned_patterns.json, which exceeds what a note-recall assistant needs to answer retrieval queries. In this skill context, that broader persistent memory can silently accumulate sensitive behavioral data and make later unintended disclosure or misuse more likely.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

record_op() persists free-form notes and error history, including lastNote and recentOps.note, without warning that user-supplied text will be retained across sessions. In a note-recall assistant, these notes can easily contain excerpts of personal memories, search targets, or other sensitive context, making the hidden logging especially risky.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

record_preference() writes arbitrary key/value user preferences to disk without any visible warning, consent, or sensitivity checks. For a memory-related skill, preferences may include personal or sensitive data, so silent persistence increases privacy risk and can expose information if the local skill directory is accessed by other tools or users.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The file's top-level natural-language description is written only in Chinese, and the script's user-facing output strings are also Chinese-only. This creates a locale/language constraint without offering the user a language choice or documenting a justified region-specific limitation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.