T09 · Insecure Skill Coding Practices
- Location
src/vector-store.js:211- Finding
LanceDB Predicate Injection Through Unsanitized Memory IDs
- Content
View full analysis
Vulnerability Details
File Location:
src/vector-store.js:211-218andsrc/vector-store.js:228-234
Vulnerability Type: SQL-like predicate injection
Risk Level: MediumVulnerable Code
javascript async getMemory(id) { if (!this.initialized) { await this.initialize(); } const results = await this.collection .filter(`id = '${id}'`) .execute(); return results.length > 0 ? results[0] : null; }javascript async deleteMemory(id) { if (!this.initialized) { await this.initialize(); } await this.collection.delete(`id = '${id}'`); this.emit('memory-deleted', { id }); }Technical Analysis
The
getMemory(id)anddeleteMemory(id)methods interpolate a caller-controlled memory identifier directly into LanceDB SQL-like predicate strings. The identifier is enclosed in single quotes but is neither escaped nor validated.A crafted identifier containing a quote followed by supported predicate syntax can terminate the intended string literal and modify the filter condition. Consequently, the database may evaluate a predicate broader than the intended exact-ID comparison.
Both vulnerable methods are reachable through the public
MemorySystem.getMemory(id)andMemorySystem.deleteMemory(id)interfaces. The exact payload syntax depends on the predicate grammar supported by the deployed LanceDB version, but direct interpolation creates the exploitable injection boundary.Attack Path
- An attacker obtains access to an application operation that forwards a memory ID to
MemorySystem.getMemory()orMemorySystem.deleteMemory(). - The attacker supplies an ID containing a quote and additional LanceDB predicate syntax.
MemorySystemforwards the identifier toVectorStorewithout validation.VectorStoreconstructs a predicate such asid = '${id}'using direct string interpolation.- LanceDB parses the injected characters as part of the predicate rather than as a literal identifier. ...[truncated 1015 chars]
- An attacker obtains access to an application operation that forwards a memory ID to
- Remediation
View remediation
Remediation Suggestions
-
Use LanceDB parameterized predicates or a typed query API if the deployed version supports them. Keep untrusted values separate from predicate syntax.
-
If parameter binding is unavailable, enforce a strict identifier format before every database operation. For example:
javascript function validateMemoryId(id) { if (typeof id !== 'string' || !/^[A-Za-z0-9_.:-]{1,128}$/.test(id)) { throw new TypeError('Invalid memory ID'); } return id; }Apply this validation consistently in
addMemory,getMemory,deleteMemory,updateMemory, and batch operations so that invalid identifiers cannot enter or query the database.-
Do not rely solely on manual quote escaping. If escaping is unavoidable, use a LanceDB-documented literal-escaping routine and centralize predicate construction in one helper.
-
Add authorization checks in the integrating application so a caller can access or delete only memories belonging to its user, tenant, or session.
-
Add regression tests covering identifiers containing single quotes, backslashes, comment markers, boolean operators, Unicode control characters, oversized values, and malformed predicate fragments. Verify that such values are rejected before reaching LanceDB.
-
For destructive operations, consider transactional safeguards, deletion limits, audit logging, and backups to reduce the impact of an unexpectedly broad predicate.
-
