T09 · Insecure Skill Coding Practices
- Location
src/index.ts:116- Finding
Plaintext Retention of User Destination Queries Contrary to Security Disclosure
- Content
View full analysis
{ const cacheKey = `geo:${query.toLowerCase().trim()}`; const cached = cache.get(cacheKey); if (cached) return cached; const results = await nominatim.search(query, 1); if (!results.length) { throw new Error(`Could not find "${query}". Try a more specific name, e.g. "Tokyo, Japan".`); } const dest = results[0]; cache.set(cacheKey, dest, TTL.GEOCODING); return dest; } ``` ```typescript // src/utils/cache.ts:7-10 export const TTL = { GEOCODING: 30 * 24 * 60 * 60 * 1000, // 30 days WIKIVOYAGE: 7 * 24 * 60 * 60 * 1000, // 7 days WEATHER: 60 * 60 * 1000, // 1 hour SHORT: 5 * 60 * 1000, // 5 minutes } as const; ``` ```typescript // src/utils/cache.ts:65-75 set(key: string, data: T, ttlMs: number): void { const now = Date.now(); this.db .prepare(` INSERT OR REPLACE INTO cache (key, data, expires_at, created_at) VALUES (?, ?, ?, ?) `) .run(key, JSON.stringify(data), now + ttlMs, now); } ``` ### Technical Analysis The original normalized destination query is embedded directly in the SQLite cache key. It is therefore stored in plaintext for the 30-day geocoding cache lifetime. Although ordinary queries may contain only city names, the public API accepts arbitrary strings. A caller may submit a home address, workplace, medical facility, religious location, or another sensitive destination. TypeScript types do not prevent such values at runtime. This behavior also conflicts with `SECURITY.md`, which states that the Skill does not store user queries or personal data. The database stores both the ...[truncated 1494 chars]- Remediation
View remediation
