T09 · Insecure Skill Coding Practices
- Location
SKILL.md:141- Finding
Declared Dry-Run and Backup Controls Are Not Enforced Before Destructive Forgetting Operations
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 141–216; destructive strategy implementations at lines 239–265
Vulnerability Type: Missing enforcement of destructive-operation safeguards
Risk Level: MediumThe skill declares
dryRunandbackupBeforeForgettingconfiguration options:javascript const forgettingConfig = { strategies: [ { type: "time-based", days: 30, enabled: true }, { type: "relevance-based", threshold: 0.3, enabled: true }, { type: "frequency-based", minAccessCount: 2, enabled: true } ], runInterval: "daily", dryRun: false, backupBeforeForgetting: true };However, the scheduled execution path applies every enabled strategy without checking either safeguard:
javascript setupScheduler() { const interval = this.config.runInterval || "daily"; const cronExpression = this.getCronExpression(interval); this.agent.scheduler.addJob({ name: "forgetting-mechanism", cron: cronExpression, task: () => this.runForgetting() }); }, async runForgetting() { this.agent.logger.info("Running forgetting mechanism..."); const originalCount = this.memoryStore.size; this.config.strategies?.forEach(strategy => { if (strategy.enabled) { this.applyStrategy(strategy); } }); const finalCount = this.memoryStore.size; const removedCount = originalCount - finalCount; this.agent.logger.info(`Forgetting mechanism completed: Removed ${removedCount} memories`); return { originalCount, finalCount, removedCount }; },The invoked strategy methods directly request filtering or clearing of the memory store:
javascript forgetTimeBased(days = 30) { const cutoffTime = Date.now() - (days * 24 * 60 * 60 * 1000); this.memoryStore.filter(memory => memory.timestamp > ...[truncated 3191 chars]- Remediation
View remediation
Remediation Suggestions
- Enforce dry-run behavior centrally in
runForgetting(). Compute an immutable deletion plan and return the candidate record identifiers and counts without modifying the memory store. - When
backupBeforeForgettingis enabled, create a complete backup before applying any strategy. Verify that the backup is readable, complete, and durably stored before proceeding. - Abort the operation if backup creation or verification fails. Do not silently continue with deletion.
- Execute deletion transactionally where the storage backend permits it. Roll back all changes if any strategy fails.
- Require explicit authorization and interactive confirmation for
forgetAll()and other broad deletion operations. Scheduled jobs should not be permitted to invoke unrestricted clearing by default. - Validate strategy parameters, including finite non-negative retention periods, bounded relevance thresholds, valid access counts, and non-null context structures.
- Record an audit event containing the initiating identity, configuration, dry-run status, backup identifier, affected-record count, and final outcome. Avoid logging sensitive memory content.
- Add tests proving that dry-run mode performs no mutation, backups are created before deletion, backup failures prevent deletion, scheduled execution honors all safeguards, and
forgetAll()cannot run without the required authorization. - Ensure the documentation describes only implemented controls and clearly states the storage adapter semantics expected from
memoryStore.filter().
- Enforce dry-run behavior centrally in
