Back to skill

Security audit

AAR Loop

Security checks for vulnerabilities and agentic risk

Overview

This skill openly logs agent lessons, but its always-on persistent memory workflow is too broad for ordinary use without stronger user control.

Install only if you are comfortable with the agent creating persistent workspace memory after tasks. Use it with explicit invocation or review, avoid logging secrets or sensitive client data, and do not add the LESSONS.md auto-load pointer unless you trust and regularly review the stored lessons.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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
  • 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)

T02 · Agent Memory Poisoning

Warning
Location
scripts/append_lesson.py:35
Finding

Persistent Indirect Prompt Injection Through Agent Lesson Storage

Content
View full analysis

Vulnerability Details

File Location: scripts/append_lesson.py:35-42, scripts/append_lesson.py:54-62, SKILL.md:154-165, CLAWHUB.md:42-46
Vulnerability Type: Persistent indirect prompt injection and memory poisoning
Risk Level: Medium

Vulnerable Code

scripts/append_lesson.py:35-42:

python
tags_str = ", ".join([t.strip() for t in tags.split(",")]) if tags else ""
fix_applied = "true" if fix_target and fix_edit else "false"
fix_plan = ""
if fix_target and fix_edit:
    fix_plan = f"**Target:** `{fix_target}`\n**Edit:** `{fix_edit}`"
content = content.format(date=date_str, tags=tags_str, task=task, expected=expected, actual=actual, why=why, lesson=lesson, fix_applied=fix_applied, fix_plan=fix_plan)
filepath.write_text(content)
print(f"Created lesson file: {filepath}")

scripts/append_lesson.py:54-62:

python
content = LESSONS_INDEX.read_text()
tags_list = [t.strip() for t in tags.split(",")] if tags else []
tags_str = ", ".join(tags_list)
new_entry = f"## {date_str} - {task}\n- Task: {task}\n- Lesson: {lesson}\n- Detail: [lessons/{filename}](lessons/{filename})\n- Tags: {tags_str}\n"
entry_header = f"## {date_str} - {task}"
if entry_header in content:
    print(f"Entry already exists in index, skipping")
    return
lines = content.split('\n')

SKILL.md:154-165:

markdown
## Loading lessons next session

Two ways to make lessons automatic:

1. **Project-local:** AGENTS.md has pointer: "Read LESSONS.md before starting work."
2. **On demand:** Before similar task, run `python3 scripts/append_lesson.py --search <keyword>`

A lessons file nobody loads is a diary, not a loop. The loop only closes when the next session actually reads it before acting.

CLAWHUB.md:42-46:

markdown
## Integration

Add to AGENTS.md or project instructions:

Read LESSONS.md before starting work on tasks similar to past ones. Run `python3 skil ...[truncated 2622 chars]

Remediation
View remediation

Remediation Suggestions

  1. Treat all lesson fields as untrusted data rather than agent instructions.
  2. Store structured records in JSON or another format with explicit data boundaries instead of interpolating raw values into instruction-bearing Markdown.
  3. If Markdown remains necessary, quote or fence every user-controlled field and escape YAML, Markdown heading, link, and code-fence syntax.
  4. Add a fixed warning before loaded entries stating that lesson content is untrusted historical data and must never override system, developer, user, or safety instructions.
  5. Require explicit human approval before adding a lesson to LESSONS.md or another file automatically loaded by agents.
  6. Separate raw task observations from reviewed operational rules. Only reviewed, normalized lessons should be promoted into agent-readable memory.
  7. Detect instruction-like or high-risk content, including requests involving secrets, policy overrides, command execution, or external communication, and quarantine it for review.
  8. Configure future agents to use stored lessons only as non-authoritative reference material and to validate each recommendation against current trusted instructions.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/append_lesson.py:17
Finding

Silent Overwrite of Existing Lesson Files Through Predictable Filename Collisions

Content
View full analysis

Vulnerability Details

File Location: scripts/append_lesson.py:17-26, scripts/append_lesson.py:40-44, scripts/append_lesson.py:58-62
Vulnerability Type: Predictable filename collision and non-atomic audit-record overwrite
Risk Level: Low

Vulnerable Code

scripts/append_lesson.py:17-26:

python
def slugify(text):
    text = text.lower()
    text = re.sub(r'[^a-z0-9\s-]', '', text)
    text = re.sub(r'[\s-]+', '-', text)
    return text.strip('-')[:50]

def create_lesson_file(task, expected, actual, why, lesson, tags, fix_target=None, fix_edit=None):
    LESSONS_DIR.mkdir(parents=True, exist_ok=True)
    date_str = datetime.now().strftime("%Y-%m-%d")
    slug = slugify(task)
    filename = f"{date_str}_{slug}.md"

scripts/append_lesson.py:40-44:

python
content = content.format(date=date_str, tags=tags_str, task=task, expected=expected, actual=actual, why=why, lesson=lesson, fix_applied=fix_applied, fix_plan=fix_plan)
filepath.write_text(content)
print(f"Created lesson file: {filepath}")
return filepath, filename

scripts/append_lesson.py:58-62:

python
entry_header = f"## {date_str} - {task}"
if entry_header in content:
    print(f"Entry already exists in index, skipping")
    return
lines = content.split('\n')

Technical Analysis

Lesson filenames consist only of the current date and a normalized task slug truncated to 50 characters. Distinct task names can normalize to the same slug because punctuation and non-ASCII characters are removed, repeated separators are collapsed, and all content after 50 characters is discarded. An identical task name on the same date also produces the same path.

Path.write_text() uses normal overwrite semantics. The implementation does not check whether the target already exists before writing and does not use exclusive file creation. Duplicate detection occurs later and applies only to the index header, s ...[truncated 1479 chars]

Remediation
View remediation

Remediation Suggestions

  1. Generate unique filenames using a full timestamp, UUID, cryptographically random suffix, or collision-resistant digest.
  2. Open new lesson files with exclusive creation semantics so an existing record cannot be silently replaced.
  3. If a collision occurs, append a deterministic numeric suffix and report the resulting filename.
  4. Validate that the generated slug is nonempty and use a safe fallback identifier when normalization removes the entire task name.
  5. Check for collisions before writing either the lesson or index.
  6. Update the lesson file and index as one logical transaction, using temporary files and atomic replacement where appropriate.
  7. Add tests for identical same-day tasks, punctuation-only names, non-ASCII names, and names that differ only after the 50-character truncation boundary.
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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (7)

Vague Triggers

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The description advertises automatic triggering for all tasks, which makes the skill run regardless of task sensitivity or user intent. A universally triggered skill that performs reflection, file reads, and potential writes can cause unintended persistence of sensitive task details and unnecessary autonomous actions across unrelated sessions.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

Mandating use every session without carve-outs encourages indiscriminate collection and persistence of session content. In context, this is more dangerous because the skill's purpose is to record lessons from agent behavior, which can easily capture confidential prompts, internal reasoning summaries, file paths, operational details, or user data if always applied.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The dedicated auto-trigger section operationalizes the broad scope by defining AAR behavior for small, medium, and large tasks, effectively leaving no meaningful exclusion path. Because the workflow includes writing durable lessons to disk, exploitation or simple misuse could turn every task into a persistence event, amplifying privacy, compliance, and prompt-injection risks.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger phrases include very generic language such as 'fix it' and 'what did we learn', which can easily appear in normal user conversations unrelated to an After Action Review workflow. In an auto-triggered skill, this creates a realistic risk of unintended activation, causing the agent to enter review/modification behavior unexpectedly and potentially append persistent lessons or propose changes based on ordinary dialogue.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill directs the agent to read and write project files and invoke a local script, but it does not declare any explicit tool scope or permission boundaries. That creates ambiguity around what filesystem and execution access the skill expects, increasing the chance an agent will overreach and modify files broadly when auto-triggered.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The sample index entries switch into Indonesian phrasing without indicating that the user can choose language or locale. This can violate language policy expectations because the skill content implies a language preference without documented opt-in or justification.

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 · SKILL.md (reported line 153)May include surrounding context.

md
- Every lesson names a specific tool, command, number, file, or condition.
- Every fix plan names an exact target file and exact edit.
- Never apply a fix plan without approval, unless user said "apply" or "fix it".
- Run AAR on ALL tasks, not just big ones. Quick capture for small tasks.
- Check for duplicates before writing.
- Lessons folder structure: `lessons/YYYY-MM-DD_{topic-slug}.md`