T09 · Insecure Skill Coding Practices
- Location
SKILL.md:455- Finding
Batch pruning silently discards retained memory records from earlier batches
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 455–469
Vulnerability Type: Logic error causing destructive data loss
Risk Level: HighVulnerable Code:
python for i in range(0, len(memories), batch_size): batch = memories[i:i + batch_size] for memory in batch: memory['relevance_score'] = calculate_relevance_score(memory, "") kept, pruned = prune_low_value_memories(batch) pruned_count += len(pruned) log(f"Batch {i // batch_size + 1}: pruned {len(pruned)} memories") log(f"Total pruned: {pruned_count} memories") return keptTechnical Analysis
The
keptvariable is overwritten during every loop iteration. Consequently, the function returns only the retained records from the final batch rather than all retained records across all batches.This defect becomes active whenever the number of memory records exceeds
batch_size, which defaults to 50. Records that pass the relevance threshold in earlier batches are omitted from the returned collection. The usage examples elsewhere in the document save returned memory collections, so passing this incomplete result to the documented save operation can overwrite the active memory store and permanently remove valid records.This is an integrity and availability vulnerability in the Skill's memory-management logic. Exploitation does not grant operating-system privileges, but it can destroy Agent state, safety context, decisions, and audit history within the affected workspace.
Attack Path
- An attacker or untrusted workload causes the active memory collection to exceed the configured batch size.
- Important target records are positioned in any batch other than the final batch.
- Batch pruning evaluates those records and correctly places retained records into the local
keptvariable. - A later loop iteration overwrites
keptwith the retained records from the next batch. - The function retu ...[truncated 791 chars]
- Remediation
View remediation
Remediation Suggestions
Accumulate retained records across every batch instead of returning the final batch's local result:
python def batch_prune_memories(memories, batch_size=50): all_kept = [] pruned_count = 0 for i in range(0, len(memories), batch_size): batch = memories[i:i + batch_size] for memory in batch: memory['relevance_score'] = calculate_relevance_score(memory, "") batch_kept, batch_pruned = prune_low_value_memories(batch) all_kept.extend(batch_kept) pruned_count += len(batch_pruned) if len(all_kept) + pruned_count != len(memories): raise RuntimeError("Memory-count invariant failed") return all_keptAdditional hardening should include:
- Add tests covering zero, one, and multiple batches.
- Verify that
retained_count + pruned_count == input_countbefore saving. - Reject duplicate or missing memory identifiers.
- Save changes atomically to a temporary file and replace the original only after validation.
- Keep a recoverable backup or transaction journal before overwriting active memory.
