T09 · Insecure Skill Coding Practices
- Location
scripts/router.py:217- Finding
Unredacted Prompt Content Is Logged by Default
- Content
View full analysis
Vulnerability Details
File Location:
scripts/router.py:217-225
Related Configuration:scripts/config.yaml:157-162
Vulnerability Type: Sensitive information exposure through application logs
Risk Level: MediumVulnerable Code
python log_config = self.config.get("logging", {}) preview_len = log_config.get("prompt_preview_length", 200) preview = prompt[:preview_len] + "..." if len(prompt) > preview_len else prompt logger.info( f"ROUTE | model={route.model} | think={route.think} | " f"task={route.task_type.value} | confidence={route.confidence:.2f} | " f"ctx_override={route.context_overridden} | context={context_size} | " f"prompt=\"{preview}\"" )The corresponding default configuration is:
yaml logging: enabled: true path: routing.log level: INFO include_prompt_preview: true prompt_preview_length: 200Technical Analysis
Routing logs are enabled by default, and
_log_route()places up to 200 characters of the user-controlled prompt into anINFOlog message without redaction. Prompts can contain API keys, passwords, personal information, proprietary source code, confidential business data, or security-sensitive instructions.Although the configuration defines
include_prompt_preview, the implementation never checks that setting. Consequently, changinginclude_prompt_previewtofalsedoes not suppress prompt content as long as routing logging remains enabled.The prompt is also inserted without escaping carriage returns, line feeds, or other control characters. An attacker can therefore supply a multiline prompt that creates misleading or forged entries in text-based log viewers. This log-injection aspect can impede investigations, although it does not grant code execution.
The configured
pathis not used by this implementation; output is sent through alogging.StreamHandler. The exposure scope therefore depends on the embedding application's standard-error capture, proces ...[truncated 1449 chars]- Remediation
View remediation
Remediation Suggestions
- Disable prompt-content logging by default and log only non-sensitive routing metadata.
- Enforce the existing configuration flag before constructing a preview:
python include_preview = log_config.get("include_prompt_preview", False) preview = "" if include_preview: preview_len = max(0, min(int(log_config.get("prompt_preview_length", 0)), 200)) preview = redact_sensitive_data(prompt[:preview_len]) preview = preview.replace("\r", "\\r").replace("\n", "\\n")- Omit the
promptfield entirely wheninclude_prompt_previewis false rather than logging an empty or placeholder value. - Apply tested redaction for authorization headers, API keys, access tokens, passwords, private keys, email addresses, and other organization-specific sensitive values.
- Escape or remove control characters to prevent multiline log injection and forged records.
- Prefer structured logging with separate fields and ensure the logging backend safely serializes untrusted text.
- Restrict log access, encrypt logs in transit and at rest, define short retention periods, and prevent unnecessary forwarding to third-party analytics systems.
- Add regression tests verifying that prompts are absent when preview logging is disabled, common secret formats are redacted, and CR/LF characters cannot create additional log records.
