T09 · Insecure Skill Coding Practices
- Location
index.js:31- Finding
Signup Overwrites the Entire Persistent Profile Database
- Content
View full analysis
Vulnerability Details
File Location:
index.js:27-31, 44-65
Vulnerability Type: Persistent data integrity failure caused by unsafe state initialization
Risk Level: HighVulnerable 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 productionrun()handler. Instead, every invocation initializesprofilesas a new empty array.Consequently:
- Duplicate-profile checks always run against an empty collection.
- Profile browsing cannot display persisted records.
- A signup appends one profile to the empty array.
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
- The profile database contains o ...[truncated 1163 chars]
- Remediation
View remediation
Remediation Suggestions
- Load persisted state before processing commands:
javascript const profiles = loadProfiles();- Remove the current
const profiles = [];initialization fromrun(). - Validate that the parsed value is an array before using or saving it.
- Implement atomic persistence by writing to a temporary file and renaming it only after a successful write.
- Introduce file locking or another concurrency-control mechanism so simultaneous signups cannot overwrite each other's updates.
- Preserve a backup before replacing the database and recover gracefully from malformed JSON.
- Add integration tests that execute the exported production
run()function and confirm that signup preserves all existing records.
