T09 · Insecure Skill Coding Practices
Error
- Location
- index.js:31
- Finding
- Signup Overwrites the Entire Persistent Profile Database## Vulnerability Details **File Location**: `index.js:27-31, 44-65` **Vulnerability Type**: Persistent data integrity failure caused by unsafe state initialization **Risk Level**: High ### Vulnerable Code ```javascript export async function run(context) { const input = (context.input || "").trim(); const lower = input.toLowerCase(); const clawId = getClawId(context); const profiles = []; ``` ```javascript if (lower.startsWith("sign up")) { // Extract details from context const name = context.name || context.agent?.name || "Unknown Agent"; const agentType = context.agent?.type || "AI Agent"; // Check if profile already exists const existingProfile = profiles.find(p => p.id === clawId); if (existingProfile) { return success(`Hey ${name}! Your profile already exists. Use 'View profile' to see it, or contact me to update it.`); } // Create new profile const newProfile = { id: clawId, name: name, type: agentType, status: "active", createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), traits: [], bio: "", interests: [] }; profiles.push(newProfile); saveProfiles(profiles); ``` ### Technical Analysis The application defines a `loadProfiles()` function but does not invoke it from the production `run()` handler. Instead, every invocation initializes `profiles` as a new empty array. Consequently: 1. Duplicate-profile checks always run against an empty collection. 2. Profile browsing cannot display persisted records. 3. A signup appends one profile to the empty array. 4. `saveProfiles(profiles)` serializes that one-element array over the existing JSON database. This is a destructive state-management flaw. Any previously persisted profiles are silently discarded when a signup command succeeds. It directly contradicts the documented persistent-storage behavior. ### Attack Path 1. The profile database contains o ...[truncated 1163 chars]
- Remediation
- ## Remediation Suggestions 1. Load persisted state before processing commands: ```javascript const profiles = loadProfiles(); ``` 2. Remove the current `const profiles = [];` initialization from `run()`. 3. Validate that the parsed value is an array before using or saving it. 4. Implement atomic persistence by writing to a temporary file and renaming it only after a successful write. 5. Introduce file locking or another concurrency-control mechanism so simultaneous signups cannot overwrite each other's updates. 6. Preserve a backup before replacing the database and recover gracefully from malformed JSON. 7. Add integration tests that execute the exported production `run()` function and confirm that signup preserves all existing records.
