Back to skill

Security audit

Agent Memory Cleanup

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent memory-cleanup tool, but it needs review because it can rewrite persistent memory files and keeps raw backups that may retain secrets.

Install only if you are comfortable letting the agent inspect and edit memory files you explicitly name. Review proposed diffs before applying, keep paths limited to real memory files, and be aware that backups may still contain any secrets removed from the active memory file.

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/audit_memory.py:105
Finding

Explicit paths can rewrite unrelated files without enforceable scope or approval validation

Content
View full analysis

Vulnerability Details

File Location: scripts/audit_memory.py:105-109, scripts/audit_memory.py:508-522, scripts/audit_memory.py:624-648
Vulnerability Type: Insufficient target validation and authorization enforcement
Risk Level: Medium

Vulnerable Code

python
def is_allowed_memory_path(self, path: Path) -> bool:
    suffix = path.suffix.lower()
    if suffix in self.rules.blocked_memory_extensions:
        return False
    return suffix in self.rules.allowed_memory_extensions
python
def parse_args(argv: list[str]) -> argparse.Namespace:
    parser = argparse.ArgumentParser(description="Audit agent memory markdown files.")
    parser.add_argument("paths", nargs="*", help="Memory files to audit. If omitted, scan likely files in the current workspace.")
    parser.add_argument(
        "--mode",
        choices=["audit-only", "propose-patch", "apply-approved"],
        default="audit-only",
        help="Execution mode. Only apply-approved writes files.",
    )
    parser.add_argument("--rules", help="Optional path to a JSON rules file.")
    parser.add_argument("--json", action="store_true", help="Emit JSON instead of markdown.")
    parser.add_argument("--summary-json", action="store_true", help="Emit compact machine-readable summary JSON.")
    parser.add_argument("--candidate", help="Lint a proposed memory entry before writing it to global memory.")
    parser.add_argument("--include-diff", action="store_true", help="Include unified diffs in markdown output.")
    parser.add_argument("--output", help="Write report to this path instead of stdout.")
    parser.add_argument("--write-proposed", help="Write the first proposed cleaned memory to this path.")
    return parser.parse_args(argv)
python
def main(argv: list[str] | None = None) -> int:
    args = parse_args(argv or sys.argv[1:])
    rules = RuleConfig.load(Path(args.rules) if args.rules else None)
...[truncated 2960 chars]
Remediation
View remediation

Remediation Suggestions

  1. Apply the configured likely-memory filename allowlist to explicit paths as well as automatically discovered paths.
  2. Require targets to reside under user-provided or explicitly configured memory roots.
  3. Reject known project policies, Skill manifests, prompt templates, source files, and configuration files by default.
  4. Require an explicit override for unusual filenames, accompanied by a clear warning that the target is outside normal memory scope.
  5. Separate proposal and application into cryptographically or structurally bound stages. Record the canonical target path, source SHA-256 hash, proposal hash, and approval decision.
  6. Before writing, verify that the source hash still matches the reviewed version and reject stale approvals.
  7. Use a distinct approval argument or approval manifest rather than treating the apply-approved mode name as proof of consent.
  8. For --output and --write-proposed, reject existing destinations by default or require an explicit overwrite option.
  9. Add regression tests demonstrating that unrelated .md, .txt, and .json files cannot be applied as memory without an explicit scoped override.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/audit_memory.py:390
Finding

Secret cleanup creates persistent plaintext backups containing the original credentials

Content
View full analysis

Vulnerability Details

File Location: scripts/audit_memory.py:390-428
Vulnerability Type: Plaintext retention of sensitive information
Risk Level: Medium

Vulnerable Code

python
class BackupWriter:
    def apply(self, report: FileReport) -> None:
        if not report.exists or not report.proposal:
            return
        path = Path(report.path)
        timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
        backup = path.with_name(f"{path.name}.bak-{timestamp}")
        tmp_path: Path | None = None
        try:
            shutil.copy2(path, backup)
        except OSError as exc:
            report.error = f"backup failed: {exc}"
            return
        try:
            with tempfile.NamedTemporaryFile(
                "w",
                encoding="utf-8",
                dir=str(path.parent),
                prefix=f".{path.name}.",
                suffix=".tmp",
                delete=False,
            ) as tmp_file:
                tmp_file.write(report.proposal.proposed_markdown)
                tmp_file.flush()
                tmp_path = Path(tmp_file.name)
            tmp_path.replace(path)
        except OSError as exc:
            report.error = f"atomic write failed after backup: {exc}"
            if tmp_path and tmp_path.exists():
                try:
                    tmp_path.unlink()
                except OSError:
                    pass
            return
        report.backup_path = str(backup)
        report.updated = True

Technical Analysis

The cleanup engine correctly removes recognized secrets from the proposed active memory file. However, before writing that sanitized content, it copies the complete original file to a predictable sibling backup using shutil.copy2().

If the original memory contains API keys, passwords, bearer tokens, or other credentials, the backup contains those values in plaintex ...[truncated 1625 chars]

Remediation
View remediation

Remediation Suggestions

  1. Detect whether the source contains suspected secrets before selecting the backup strategy.
  2. For secret-bearing files, require explicit informed consent before retaining an unsanitized backup.
  3. Store sensitive backups outside synchronized or repository-managed directories.
  4. Encrypt raw backups using a user-controlled key, or place them in a protected operating-system credential or backup facility.
  5. Create backup files with owner-only permissions and verify the resulting permissions after creation.
  6. Clearly report that the backup still contains the original sensitive material and provide its location.
  7. Implement a documented retention and secure-deletion policy for sensitive backups.
  8. Consider creating a sanitized backup by default while offering raw recovery only through an explicit high-risk option.
  9. Add tests verifying backup permissions, secret-retention warnings, and secure handling of files containing recognized credentials.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (19)

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

Scanner excerpt · SKILL.md (reported line 14)May include surrounding context.

md
# Agent Memory Cleanup

This skill should be lightweight and low-noise. Do not require the user to know internal implementation names unless they ask. The user should still receive clear memory-state prompts, such as "memory appears too large, stale, duplicated, conflicted, or unsafe," when action is useful.

## Default Flow

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

Scanner excerpt · scripts/run_tests.py (reported line 146)May include surrounding context.

python
# Agent Memory Cleanup

This skill should be lightweight and low-noise. Do not require the user to know internal implementation names unless they ask. The user should still receive clear memory-state prompts, such as "memory appears too large, stale, duplicated, conflicted, or unsafe," when action is useful.

## Default Flow

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 22)May include surrounding context.

md
python scripts/audit_memory.py memory.md --summary-json

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 30)May include surrounding context.

md
python scripts/audit_memory.py memory.md --summary-json

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 36)May include surrounding context.

md
python scripts/audit_memory.py memory.md --summary-json

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 51)May include surrounding context.

md
python scripts/audit_memory.py memory.md --summary-json

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/audit_memory.py (reported line 333)May include surrounding context.

python
for rule in self.rules.condense_rewrites:
            needles = [value.lower() for value in rule.get("when_contains_any", [])]
            if any(needle in lower for needle in needles):
                return rule.get("rewrite")
        if "prefer" in lower or "concise" in lower or "direct" in lower:
            return self.canonicalize_keep(text)
        return None

Ssd 3

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Storing a temporary API token in a memory file is dangerous because memory artifacts are likely to be surfaced, copied, summarized, backed up, or reused by agents later, which can disclose valid credentials beyond their intended context. In this skill context, the risk is heightened because the skill explicitly audits and edits long-term memory files, making secret propagation and retention a central concern rather than an incidental one.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The memory file stores a plaintext staging password in natural language, which is sensitive credential material and should not be retained in agent memory. In the context of a memory-cleanup skill, this is especially dangerous because these files are likely to be read, summarized, migrated, or edited by automation, increasing the chance the secret is surfaced, copied, or leaked.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This is a direct case of a user's plaintext staging password being stored in long-term memory, creating a clear disclosure risk if the agent later references, summarizes, backs up, or exposes memory contents. The skill context makes this more dangerous, not less, because the skill explicitly operates on memory files and may duplicate or preserve the secret in backups unless sanitization is handled carefully.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill invokes local Python and file-modifying workflows but does not declare any explicit tool or permission scope. That creates ambiguity about what capabilities the agent may use and weakens policy enforcement, increasing the risk of unintended shell execution, file access, or expansion of scope beyond the intended memory files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The --write-proposed option writes generated content to any filesystem path supplied on the command line with no path restrictions, confirmation, or safety checks. In an agent setting, if an upstream component or prompt can influence CLI arguments, this can overwrite arbitrary user files or place attacker-controlled content in sensitive locations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The --output option writes the full report payload to any path provided, again without confirmation or destination validation. Because the payload can include redacted findings, diffs, and metadata, an attacker who can steer arguments could overwrite arbitrary files or exfiltrate/report sensitive content into unintended locations.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/run_tests.py (reported line 21)May include surrounding context.

python
def run_cli(*args: str) -> str:
    result = subprocess.run(
        [sys.executable, str(AUDIT), *args],
        cwd=str(ROOT),
        check=True,

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The test fails if any file contains non-ASCII bytes, effectively prohibiting non-English characters and many locale-specific scripts in all repository files. This is a natural-language policy concern because it enforces a language/character-set constraint without any user opt-in or documented regional justification in this file.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · references/default-rules.json (reported line 132)May include surrounding context.

json
- The user prefers concise direct answers unless they ask for detail.
- Current task: remember that PR #221 is blocked by a failing Windows path test.
- The user wants memory cleanup to ask before editing user-level memory.
- The user wants automatic memory cleanup to apply without asking.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · test-fixtures/conflicting-memory.md (reported line 7)May include surrounding context.

md
- The user prefers concise direct answers unless they ask for detail.
- Current task: remember that PR #221 is blocked by a failing Windows path test.
- The user wants memory cleanup to ask before editing user-level memory.
- The user wants automatic memory cleanup to apply without asking.

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

Scanner excerpt · LICENSE (reported line 12)May include surrounding context.

text
permit persons to whom the Software is furnished to do so.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

These lines state that responses should be in Chinese when the user writes in Chinese, and then more broadly that the user prefers Chinese replies. This can function as a locale/language policy constraint in natural language without showing explicit opt-in, choice, or justification in the file.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
test-fixtures/secret-memory.md:4

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
test-fixtures/short-polluted-memory.md:6