Back to skill

Security audit

Client Tracker

Security checks for vulnerabilities and agentic risk

Overview

This is a simple local freelancer CRM whose main risk is that client and invoice data is saved as plain text on the user's machine.

Install only if you are comfortable keeping CRM records in a local plain text JSON file. Treat ./clients/clients.json as sensitive, keep it out of source control, avoid using it in shared workspaces unless permissions are controlled, and consider stronger storage protections for confidential client or financial data.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
src/client-tracker.js:10
Finding
Plaintext Storage of Sensitive CRM Data with Uncontrolled Filesystem Permissions## Vulnerability Details **File Location**: `src/client-tracker.js:10-13, 17-19, 38-40, 83` **Vulnerability Type**: Plaintext sensitive-data storage and insufficient file-permission hardening **Risk Level**: Medium ### Vulnerable Code ```js constructor(options = {}) { this.dataDir = options.dataDir || './clients'; this.dbFile = path.join(this.dataDir, 'clients.json'); if (!fs.existsSync(this.dataDir)) fs.mkdirSync(this.dataDir, { recursive: true }); this.clients = this._load(); } addClient(name, email, company, notes) { const id = Date.now().toString(36) + Math.random().toString(36).slice(2, 5); const client = { id, name, email, company, notes, projects: [], invoices: [], pipeline: 'lead', created: new Date().toISOString() }; this.clients.push(client); this._save(); return client; } addInvoice(clientId, amount, description) { const client = this.clients.find(c => c.id === clientId || c.name.toLowerCase() === clientId.toLowerCase()); if (!client) return null; const inv = { id: 'INV-' + Date.now().toString(36).toUpperCase(), amount, description, status: 'sent', date: new Date().toISOString().split('T')[0] }; client.invoices.push(inv); this._save(); return inv; } _save() { fs.writeFileSync(this.dbFile, JSON.stringify(this.clients, null, 2)); } ``` ### Technical Analysis The application serializes client names, email addresses, company information, free-form notes, project budgets, and invoice details directly into `./clients/clients.json` as human-readable plaintext. Neither `fs.mkdirSync` nor `fs.writeFileSync` requests restrictive permissions. Consequently, access to this sensitive database depends on the process umask, permissions inherited from the deployment environment, and protections on parent directories. In shared, containerized, backed-up, or accidentally published workspaces, those defaults may permit unintended disclosure. The storage is also not encrypted at rest. Any process or user capable of reading the file ...[truncated 1446 chars]
Remediation
## Remediation Suggestions 1. Create the data directory with owner-only access: ```js fs.mkdirSync(this.dataDir, { recursive: true, mode: 0o700 }); ``` 2. Write the database with an explicit owner-only mode: ```js fs.writeFileSync( this.dbFile, JSON.stringify(this.clients, null, 2), { encoding: 'utf8', mode: 0o600 } ); ``` 3. Check and correct permissions on existing directories and database files, because specifying a mode during creation does not necessarily repair an existing permissive file: ```js fs.chmodSync(this.dataDir, 0o700); if (fs.existsSync(this.dbFile)) { fs.chmodSync(this.dbFile, 0o600); } ``` 4. Use atomic persistence: write to a protected temporary file in the same directory, flush it as appropriate, set mode `0600`, and rename it over the database. This reduces corruption risk and avoids exposing partially written data. 5. For deployments with stronger confidentiality requirements, encrypt sensitive fields or the complete database at rest. Store encryption keys outside the project directory and do not hardcode them in source code. 6. Resolve the default data directory to a documented, private application-data location rather than a relative workspace path that may be synchronized, committed, or published accidentally. 7. Document that the database contains PII and financial information, identify its exact location, and instruct users to exclude it from source control and protect backups.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The skill persists client names, emails, company details, notes, projects, and invoices to a local JSON file without any consent flow, disclosure, access controls, or encryption. In a conversational CRM context, users may provide sensitive personal and business data expecting agent-mediated handling, so silent plaintext storage increases privacy and data exposure risk if the host system is shared, compromised, or backed up insecurely.

Scope Creep

Low
Category
Excessive Agency
Content
**USE AT YOUR OWN RISK.**

- The author(s) are NOT liable for any damages, losses, or consequences arising from 
  the use or misuse of this software — including but not limited to financial loss, 
  data loss, security breaches, business interruption, or any indirect/consequential damages.
- This software does NOT constitute financial, legal, trading, or professional advice.
- Users are solely responsible for evaluating whether this software is suitable for
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Scope Creep

Low
Category
Excessive Agency
Content
**USE AT YOUR OWN RISK.**

- The author(s) are NOT liable for any damages, losses, or consequences arising from 
  the use or misuse of this software — including but not limited to financial loss, 
  data loss, security breaches, business interruption, or any indirect/consequential damages.
- This software does NOT constitute financial, legal, trading, or professional advice.
- Users are solely responsible for evaluating whether this software is suitable for
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Description-Behavior Mismatch

Low
Confidence
90% confidence
Finding
The README makes a concrete security/privacy assurance that data is stored locally and not transmitted externally unless explicitly configured, but the file provides no technical basis to verify that claim. In a conversational CRM that handles client names, emails, project details, and financial information, inaccurate data-handling claims can mislead users into exposing sensitive business and personal data under false privacy expectations.

Static analysis

No suspicious patterns detected.