T09 · Insecure Skill Coding Practices
Warning
- Location
- legacy-import.js:14
- Finding
- Long-term memory data can be transmitted to an unrestricted plaintext endpoint<![CDATA[ ## Vulnerability Details **File Location**: `legacy-import.js:14-19, 25-31, 34-55`; `tools/stdb_store.js:7-16, 28`; `tools/stdb_search.js:8-21`; `tools/stdb_edit.js:8-16, 34`; `tools/stdb_forget.js:8-16, 29` **Vulnerability Type**: Unrestricted external endpoint and plaintext transmission of sensitive memory **Risk Level**: Medium ### Relevant Code ```js const filesToImport = [ 'MEMORY.md', 'IDENTITY.md', 'USER.md', 'SOUL.md', 'HEARTBEAT.md', 'AGENTS.md', 'TOOLS.md' ]; const URL = process.env.SPACETIMEDB_URL || 'http://127.0.0.1:3001'; const DB_NAME = process.env.SPACETIMEDB_NAME || 'stdb-memory-1vgys'; async function main() { console.log(`Starting legacy import for workspace: ${workspace}`); let db; await new Promise((resolve, reject) => { const builder = sdk_1.DbConnection.builder() .withUri(URL) .withDatabaseName(DB_NAME) .onConnect(() => resolve()) .onConnectError((ctx, err) => reject(err)); db = builder.build(); }); for (const file of filesToImport) { const fullPath = path.join(workspace, file); if (fs.existsSync(fullPath)) { const content = fs.readFileSync(fullPath, 'utf8'); if (content.includes("migrated to SpacetimeDB")) { console.log(`Skipping ${file} - already migrated`); continue; } console.log(`Importing ${file}...`); const backupPath = `${fullPath}.bak`; fs.copyFileSync(fullPath, backupPath); const id = Date.now().toString() + Math.floor(Math.random() * 1000).toString(); const timestamp = BigInt(Date.now()) * 1000n; const tags = ['legacy', 'import', file.replace('.md', '').toLowerCase()]; try { db.reducers.storeMemory({ id, content: content.trim(), timestamp, tags }); ``` The ordinary storage tool uses the same unrestricted endpoint: ```js const content = args.c ...[truncated 2966 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Enforce loopback-only operation by default: - Resolve the configured hostname and reject non-loopback IPv4 and IPv6 addresses. - Reject redirects or alternate resolved addresses that bypass the restriction. 2. Introduce an explicit remote-storage mode requiring separate, informed user consent. 3. Require TLS-protected transport for every non-loopback endpoint; reject plaintext remote URLs. 4. Authenticate the database server and validate its certificate and expected identity. 5. Display the resolved destination and the categories of data being transferred before legacy migration. 6. Avoid relying solely on inherited environment variables for security-sensitive routing. Prefer a protected configuration file or explicit invocation argument with restrictive permissions. 7. Consider client-side encryption for long-term memory and legacy file contents before transmission. 8. Document clearly that setting a remote endpoint causes memory and imported workspace content to leave the local machine. ]]>
