T09 · Insecure Skill Coding Practices
Error
- Location
- src/env-guard.js:98
- Finding
- Programmatic Scan Results Retain Unredacted Secret-Bearing Source Lines<![CDATA[ ## Vulnerability Details **File Location**: `src/env-guard.js:98-106` **Vulnerability Type**: Plaintext sensitive-data exposure **Risk Level**: High ### Vulnerable Code ```js const finding = { file: filePath, line: i + 1, type: pat.name, severity: pat.severity, snippet: this._redact(match[0]), raw: line.trim().substring(0, 120) }; // Check allowlist const key = `${filePath}:${i + 1}:${pat.name}`; if (!this.allowlist.includes(key)) { this.findings.push(finding); } ``` ### Technical Analysis The detected match is redacted before being assigned to `snippet`, but the same finding also retains up to 120 characters of the original source line in `raw`. That source line can contain the complete credential, connection string, webhook URL, password, token, or neighboring sensitive values. The `EnvGuard` class is exported for programmatic use, and `report()` returns `this.findings` without removing `raw`. Therefore, callers that serialize, log, upload, or archive the returned report can unintentionally disclose the exact secrets that the scanner was intended to protect. The current CLI output only prints `snippet`, so direct CLI output does not expose `raw`. The vulnerability affects API consumers and any future output path that processes the complete report object. ### Attack Path 1. A scanned file contains a credential matching one of the configured patterns. 2. `_scanFile()` detects the credential and creates a finding. 3. `_redact()` protects only the `snippet` property. 4. The original line, including the credential, is copied into `finding.raw`. 5. `report()` returns the finding to the API consumer. 6. A CI integration, logging framework, report serializer, or other downstream consumer records the report. 7. Anyone with access to that downstream destination can recover the plaintext credential. ### Impact Assessment An attacker who can access generated reports, logs, telemetry, or CI artifacts may obtain credentials present in scan ...[truncated 421 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove the `raw` property from findings by default. 2. If source context is required, replace every detected sensitive span with a fixed placeholder before storing it. 3. Apply redaction to the complete line rather than only to the first matched value. 4. Consider reporting only the file path, line number, pattern type, severity, and redacted match. 5. If plaintext evidence is operationally necessary, require an explicit opt-in option with prominent documentation warning that the report contains secrets. 6. Add automated tests confirming that serialized findings never contain the original credential or adjacent sensitive values. 7. Review downstream CI and logging integrations and delete previously generated artifacts that may contain `raw` findings. A safer implementation should resemble: ```js const redactedLine = line.replace(pat.pattern, matchValue => this._redact(matchValue) ); const finding = { file: filePath, line: i + 1, type: pat.name, severity: pat.severity, snippet: this._redact(match[0]), context: redactedLine.trim().substring(0, 120) }; ``` For global or overlapping patterns, perform comprehensive redaction across all configured secret patterns before retaining context. ]]>
