Back to skill

Security audit

cs-autoresponder

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent and not malicious, but it stores raw customer conversations and identifiers by default and has an unsafe log-cleanup path that users should review before installing.

Review privacy and retention requirements before use. Disable or minimize raw transcript logging unless you have consent and a business need, keep logs in a dedicated restricted directory, avoid running the monitor under a privileged account, and verify logDir before enabling cleanup or PM2 background operation.

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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
lib/logger.js:20
Finding
Raw Customer Data Stored and Printed Without Adequate Protection<![CDATA[ ## Vulnerability Details **File Location**: `lib/logger.js:20-39`; related defaults and output paths in `config/template.json:41-45`, `scripts/monitor.js:96-97`, `scripts/respond.js:26-29`, and `scripts/escalate.js:22-25` **Vulnerability Type**: Plaintext storage and disclosure of sensitive customer data **Risk Level**: Medium ### Vulnerable Code ```javascript log(entry) { if (!this.config.logging.enabled) return; const date = new Date().toISOString().split('T')[0]; // YYYY-MM-DD const dayDir = path.join(this.logDir, date); const logFile = path.join(dayDir, `${this.clientId}.jsonl`); // Create directory if (!fs.existsSync(dayDir)) { fs.mkdirSync(dayDir, { recursive: true }); } // Write log entry const logEntry = { timestamp: new Date().toISOString(), ...entry }; fs.appendFileSync(logFile, JSON.stringify(logEntry) + '\n', 'utf-8'); } ``` Logging is enabled for 90 days by default: ```json "logging": { "enabled": true, "logDir": "./logs", "retentionDays": 90 } ``` Raw identifiers and message contents are also printed: ```javascript console.log(`\n📨 New message from ${msg.user} (${channelName})`); console.log(` "${msg.message}"`); ``` ### Technical Analysis The logger writes the complete entry object to an unencrypted JSONL file. Callers populate that object with raw customer identifiers, message contents, generated responses, channel names, and escalation details. The implementation does not redact sensitive values, pseudonymize identifiers, detect secrets, encrypt transcripts, or explicitly create files with restrictive permissions. The same customer data is emitted to standard output in the monitor, manual response, and escalation paths. The documented PM2 deployment model may retain this output in process-manager logs independently of the application's configured retention period. Although the documentation tells operators not to store sensitive information, the implementation cannot guarantee th ...[truncated 1352 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable full-message logging by default and log only operational metadata necessary for aggregate reporting. 2. Apply centralized redaction before both file logging and console output. Cover payment-card data, credentials, tokens, email addresses, telephone numbers, and government identifiers. 3. Pseudonymize customer identifiers using a keyed hash when correlation is necessary. 4. Create the log directory and files with restrictive permissions, such as owner-only directory and file access. 5. Encrypt full transcripts at rest when a documented business requirement requires their retention. 6. Reduce the default retention period and make full transcript retention explicitly opt-in. 7. Ensure PM2 and other process-manager logs have equivalent access controls, redaction, rotation, and retention limits. 8. Separate aggregate analytics from raw transcript storage so the dashboard does not require retaining message bodies. 9. Document incident-response and deletion procedures for customer data. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
lib/logger.js:57
Finding
Unconstrained Recursive Log Cleanup Can Delete Unrelated Directories<![CDATA[ ## Vulnerability Details **File Location**: `lib/logger.js:57-88`; configured path initialization at `lib/logger.js:12-15` **Vulnerability Type**: Unsafe recursive deletion using an unconstrained configurable path **Risk Level**: Medium ### Vulnerable Code ```javascript cleanOldLogs() { const retentionDays = this.config.logging.retentionDays || 90; const now = new Date(); if (!fs.existsSync(this.logDir)) return; const dirs = fs.readdirSync(this.logDir); dirs.forEach(dir => { const dirPath = path.join(this.logDir, dir); const stat = fs.statSync(dirPath); if (!stat.isDirectory()) return; // Parse date const parts = dir.split('-'); if (parts.length !== 3) return; const logDate = new Date(dir); const daysDiff = Math.floor((now - logDate) / (1000 * 60 * 60 * 24)); if (daysDiff > retentionDays) { console.log(`🗑️ Deleting old logs: ${dir} (${daysDiff} days old)`); fs.rmSync(dirPath, { recursive: true, force: true }); } }); } ``` The deletion root is taken directly from configuration: ```javascript constructor(config) { this.config = config; this.logDir = path.resolve(config.logging.logDir); this.clientId = config.clientId; } ``` ### Technical Analysis The configured `logging.logDir` is resolved to an absolute path but is not constrained to a dedicated, application-owned root. The cleanup routine enumerates every direct child directory and recursively deletes a child when its name can be interpreted as an old date. The date check only verifies that splitting the name on `-` produces three components. It does not strictly verify a valid `YYYY-MM-DD` date, confirm that the directory was created by this Skill, or verify that it contains only expected client log files. Because `fs.rmSync()` is called with both `recursive: true` and `force: true`, all content under a matching directory is removed. The process performs this operation with all filesystem permiss ...[truncated 1338 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define a fixed application-owned log root and require the configured path to remain beneath it. 2. Resolve and normalize both paths, then reject configurations where the candidate path escapes the approved root. 3. Place an application-specific marker file in managed directories and verify it before any recursive deletion. 4. Validate child names with a strict `YYYY-MM-DD` expression and confirm that parsing produces the same valid calendar date. 5. Delete only expected files, such as the configured client's `.jsonl` file, rather than recursively deleting an entire date directory. 6. Remove a date directory only after confirming it is empty and contains no symlinks or unexpected entries. 7. Refuse dangerous roots such as `/`, a user home directory, the project root, or other broad shared locations. 8. Run the Skill under a dedicated, unprivileged operating-system account with filesystem access limited to its own logs. 9. Log deletion decisions and provide a dry-run mode so operators can verify the cleanup scope before enabling it. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description presents a broader customer service automation skill centered on responding to messages across channels, matching FAQs, and handling escalations, with daily summaries as one component. The supplied code chunk only implements the daily summary/reporting portion: it parses CLI arguments, loads configuration from disk, calls a logger to generate stats, and prints a dashboard for a given date. It does not ingest or respond to customer messages, perform FAQ matching, route/escalate tickets, or interact with any communication channels. Because the implemented behavior is limited to reporting and lacks the core responder capabilities claimed in the description, this is a material description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description presents a broader customer service automation skill with auto-response, FAQ matching, escalation, and daily summaries. The supplied code only implements the escalation portion, specifically formatting and sending/mocking escalation alerts to Discord or Kakao based on CLI inputs and a config file. There is no evidence of automatic responding, FAQ retrieval/matching, or daily summary functionality in this chunk. While escalation is part of the declared purpose, the actual behavior here is materially narrower than the description, so this code chunk does not accurately represent the full declared functionality.

Ae1

High
Category
analysis-evasion
Content
`lib/matcher.js`는 간단한 키워드 매칭을 사용:
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The README explicitly documents persistent daily JSONL logging of channel, user, message, response, FAQ ID, and score with 90-day retention, which creates a real privacy and data-protection risk for customer service conversations. In this skill context, the data includes customer identifiers and free-form messages that may contain personal or sensitive information, so retaining it without clear minimization, consent, access controls, or deletion safeguards increases the likelihood of privacy violations and secondary exposure if logs are accessed or exfiltrated.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The natural-language description and operational guidance are presented in Korean, but the file does not state that the skill is intended only for Korean-speaking users or offer an opt-in language choice. This can violate language/locale policy by implicitly forcing a specific language for use and maintenance.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill explicitly states that all customer conversations are logged daily and later shows logs containing message content and user identifiers such as usernames and phone numbers. In a customer-service context, this creates meaningful privacy and compliance risk because sensitive personal data may be stored, retained, or exposed without clear minimization, consent, retention, access-control, or redaction guidance.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This JSON config contains multiple natural-language values exclusively in Korean, including the customer name, tone description, escalation mention, and keyword lists. Because the file provides no indication that language selection is optional or region-specific, it appears to enforce a specific locale without user opt-in, which matches the policy-violation criteria.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This logger persistently writes full conversation entries to disk as JSONL without any evidence of consent flow, data minimization, masking, or encryption. In a customer-service autoresponder context, chat content commonly contains personal data, account details, or complaint history, so silent local retention increases privacy, compliance, and unauthorized-access risk.

Natural-Language Policy Violations

Medium
Confidence
84% confidence
Finding
The file’s natural-language comments describe the skill entirely in Korean, including core behavior descriptions such as FAQ matching and response generation. Under the policy, forcing a specific language without user opt-in or a documented locale-specific justification is a language/locale policy concern.

Vague Triggers

Medium
Confidence
89% confidence
Finding
This is a manifest file, so vague-trigger checks apply. The description presents a broad capability set for a customer service auto-responder but gives no specific invocation phrases, channel constraints, or exclusion conditions, which could lead to overly broad matching or unintended activation in tooling that relies on manifest descriptions.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This JavaScript file contains multiple user-facing strings entirely in Korean, including the file description, dashboard output, warnings, and CLI help text. Because the skill does not offer any user language selection or explain that it is intentionally limited to a Korean-speaking context, it creates a language/locale policy concern under the natural-language policy rules.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The file’s natural-language description and user-facing help/output are written exclusively in Korean, indicating an assumed language/locale with no opt-in or alternative. Under the policy, forcing a specific language without user choice is a natural-language policy violation unless clearly justified as region-specific.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
This code file contains user-facing and maintainer-facing natural-language content primarily in Korean, including operational comments and CLI option descriptions. Under the policy rule for language/locale, forcing a specific language without opt-in can be a violation when no alternative language choice or justification is provided.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
This code contains user-facing and instructional natural language in Korean, including the file description, help text, and escalation reason strings, but does not offer any language selection or state that the skill is intentionally limited to Korean users. Under the policy, forcing a specific language without user opt-in is a locale/language policy violation.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
This manifest/config file contains user-facing natural-language content entirely in Korean, with only a few embedded English keywords, and does not indicate that the skill is Korea-specific or that users can choose another language. That can violate a language/locale policy if the organization expects language choice or explicit locale scoping.

Natural-Language Policy Violations

Low
Confidence
85% confidence
Finding
The file’s natural-language comments and descriptions are written in Korean, and the sample user-facing message content is also exclusively Korean. Under the stated policy, forcing a specific language without user opt-in can be a locale/language policy issue when no alternative or opt-in is provided.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
Natural-language strings and comments indicate a Korean-only presentation, and the visible runtime message also mixes localized output without offering language selection. Under the policy, forcing a specific language without user opt-in can be a locale-policy issue unless the regional scope is explicitly documented.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
The script example contains the literal message '영업시간?' while the manifest does not document any locale limitation or user opt-in for Korean. This can indicate an implicit language preference in natural-language examples without clarifying whether the skill is multilingual or region-specific.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/escalate.js:55

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
lib/channels.js:129