T09 · Insecure Skill Coding Practices
Warning
- Location
- index.js:13
- Finding
- Plaintext Persistence of Sensitive Shipment Data with Implicit File Permissions## Vulnerability Details **File Location**: `index.js`, lines 13-15, 27-28, and 105-121 **Vulnerability Type**: Plaintext sensitive-data storage and insufficiently explicit filesystem permissions **Risk Level**: Medium ### Vulnerable Code ```js const baseDir = path.join(os.homedir(), '.openclaw', 'data', namespace); fs.mkdirSync(baseDir, { recursive: true }); this.file = path.join(baseDir, 'store.json'); ``` ```js writeAll(data) { fs.writeFileSync(this.file, JSON.stringify(data, null, 2)); } ``` ```js const newItem = { trackingNo, courier, name: options.name || '未命名包裹', addedAt: new Date().toISOString(), lastCheckAt: null, status: 'pending', history: [], alerts: [], alertRules: options.alertRules || [ { type: 'stuck', hours: 48, enabled: true }, { type: 'abnormal', enabled: true } ] }; items[trackingNo] = newItem; this.store.set(this.STORAGE_KEY, items); ``` ### Technical Analysis The fallback storage implementation serializes package records directly to `~/.openclaw/data/logistics-watcher/store.json`. Full tracking numbers are retained both inside each record and as object keys. Package names, tracking history, alerts, and related logistics details may also be persisted as records evolve. The data is not encrypted, and neither the storage directory nor the file is created with explicit owner-only permissions. Consequently, access control depends on the runtime environment's umask and existing parent-directory permissions. Although common configurations may restrict access adequately, the implementation does not enforce that guarantee. Tracking numbers and shipment histories can be sensitive because they may reveal delivery activity, timing, routes, locations, and associations between users and orders. The storage behavior also conflicts with the skill documentation's privacy emphasis on redacting full tracking numbers when information leaves the user's private context. ### Attack Path 1. A user invokes `addTracking()` w ...[truncated 1433 chars]
- Remediation
- ## Remediation Suggestions 1. Create the storage directory with explicit owner-only permissions: ```js fs.mkdirSync(baseDir, { recursive: true, mode: 0o700 }); fs.chmodSync(baseDir, 0o700); ``` 2. Write the storage file with mode `0600`, including when replacing an existing file: ```js fs.writeFileSync( this.file, JSON.stringify(data, null, 2), { encoding: 'utf8', mode: 0o600 } ); fs.chmodSync(this.file, 0o600); ``` 3. Use authenticated encryption for full tracking numbers and shipment histories if they must remain recoverable. Keep encryption keys outside the data file and use an operating-system credential store or a securely provisioned secret. 4. Minimize retained information. Store a masked identifier for display and avoid duplicating the full tracking number as both an object key and a record property. If exact lookup is required, consider using a keyed hash as the index. 5. Add deletion and retention controls so stale shipment records do not remain indefinitely. 6. Redact tracking numbers in reports and returned objects by default, exposing full identifiers only when explicitly required in an authorized private context. 7. Use atomic writes to an owner-only temporary file in the same protected directory, then rename it into place. This reduces corruption and avoids introducing an insecure shared temporary-file workflow.
