T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/security_audit.py:947
- Finding
- Shell Credentials Are Copied into Persistent Audit Reports<![CDATA[ ## Vulnerability Details **File Location**: `scripts/security_audit.py:947-961` **Vulnerability Type**: Plaintext sensitive-data exposure **Risk Level**: High ### Vulnerable Code ```python with open(rc_file, 'r', encoding='utf-8', errors='ignore') as f: content = f.read() matches = export_secret_pattern.findall(content) if matches: sanitized = [m[:50] + "..." if len(m) > 50 else m for m in matches[:3]] results.append(AuditResult( category="密钥与凭据安全", name=f"Shell 配置明文密钥: {rc_file.name}", status="fail", severity="high", description=f"发现 {len(matches)} 处明文导出密钥: {'; '.join(sanitized)}", impact=str(rc_file), fix="将密钥移至 .env 文件或密钥管理服务,不在 shell 配置中硬编码", )) ``` ### Technical Analysis The shell-security check reads files such as `.bashrc`, `.zshrc`, `.bash_profile`, and `.profile`, then searches for exported variables whose names suggest that they contain keys, tokens, secrets, or passwords. The code treats truncation to 50 characters as sanitization. This is not effective redaction: - Values shorter than or equal to 50 characters are included in full. - The first 50 characters of longer credentials are disclosed. - Many API keys, passwords, and access tokens are short enough to be exposed completely. - Even a credential prefix can disclose sensitive operational information or be sufficient for abuse in formats where the meaningful secret appears near the beginning. The resulting description is passed to both Markdown and JSON report generators. Reports are saved to disk, and the Markdown report is also printed to standard output unless quiet mode is enabled. The separate Feishu sender can subsequently process and transmit report-derived content, increasing the number of locations through which the data may be exposed. ### Attack Path 1. A legitimate user or attacker-controlled setup places a credential in a shell initialization file, for example as an exported token. 2. The user ...[truncated 1323 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Never include a matched assignment or any substring of its value in an audit result. 2. Parse and report only non-secret metadata: - Variable name - Source file - Line number - Credential classification 3. Replace values with a fixed marker such as `[REDACTED]`; do not use prefix-preserving truncation. 4. Avoid retaining the full file content longer than necessary and ensure it is not included in exception messages. 5. Create report files atomically with mode `0600`, rather than relying on the process `umask`. 6. Keep detailed security reports out of terminal and CI output by default; require an explicit option to print them. 7. Apply a final centralized redaction pass to all report fields before serialization or network transmission. 8. Add tests using short and long synthetic credentials to verify that no part of a credential value appears in Markdown, JSON, console output, or Feishu-formatted content. A safer result would resemble: ```python results.append(AuditResult( category="Credential Security", name=f"Plaintext shell credential: {rc_file.name}", status="fail", severity="high", description=( f"Found a plaintext exported credential variable " f"named {variable_name}; value=[REDACTED]" ), impact=f"{rc_file}:{line_number}", fix="Move the credential to an approved secret-management service.", )) ``` ]]>
