T09 · Insecure Skill Coding Practices
Error
- Location
- src/config.ts:71
- Finding
- Tool arguments are exported by default with incomplete secret redaction<![CDATA[ ## Vulnerability Details **File Location**: `src/config.ts:71`, `src/hooks/before-tool-call.ts:59-69`, `src/util.ts:6-11`, `src/util.ts:59-70` **Vulnerability Type**: Sensitive data exposure through telemetry **Risk Level**: High ### Vulnerable Code `src/config.ts:71`: ```ts captureToolInput: true, ``` `src/hooks/before-tool-call.ts:59-69`: ```ts // Opt-in: capture tool arguments if (config.captureToolInput && event.tool?.args !== undefined) { attributes['gen_ai.tool.call.arguments'] = prepareForCapture( event.tool.args, config.toolInputMaxLength, config.redactSecrets, ); attributes['openclaw.tool.input_size'] = typeof event.tool.args === 'string' ? event.tool.args.length : JSON.stringify(event.tool.args ?? '').length; } ``` `src/util.ts:6-11`: ```ts /** Patterns that likely indicate secret values. */ const SECRET_PATTERNS = [ /(?:api[_-]?key|token|secret|password|auth|credential|bearer)\s*[:=]\s*["']?[^\s"',}{]{8,}/gi, /(?:sk|pk|rk|pat|ghp|gho|glpat|xox[bpras])[_-][A-Za-z0-9_-]{10,}/g, /eyJ[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}/g, // JWT ]; ``` `src/util.ts:59-70`: ```ts export function prepareForCapture( value: unknown, maxLength: number, redact: boolean, ): string { let str = typeof value === 'string' ? value : safeJsonStringify(value); if (redact) { str = redactSecrets(str); } return truncate(str, maxLength); } ``` ### Technical Analysis Tool-input capture is enabled by default, despite the source comment describing it as opt-in. Every tool invocation can therefore place serialized arguments in the `gen_ai.tool.call.arguments` span attribute. The OpenTelemetry exporter subsequently transmits that attribute to Pydantic Logfire. The redaction mechanism operates on the serialized string using a limited set of regular expressions. It is not a structural redactor and does not reliably match normal JSON property syntax. For example, a serialized value such as: ```json {"password":"sen ...[truncated 2524 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Change `captureToolInput` to `false` by default so argument collection requires explicit administrator consent. 2. Redact structured values before serialization: - Recursively traverse objects and arrays. - Replace values whose keys match names such as `password`, `token`, `secret`, `authorization`, `cookie`, `credential`, `privateKey`, or `connectionString`. - Perform key matching case-insensitively and normalize separators. 3. Prefer an allowlist of telemetry-safe fields over a denylist of secret formats. 4. Add detection for private keys, cookies, database URLs, cloud credentials, and common vendor-token formats as defense in depth. 5. Never treat regular-expression redaction as a guarantee that arbitrary tool input is safe to export. 6. Add regression tests covering: ```json {"password":"sensitive-value-123"} {"apiKey":"sensitive-value-123"} {"Authorization":"Bearer sensitive-value-123"} {"nested":{"credentials":{"secret":"sensitive-value-123"}}} ``` 7. Provide per-tool capture policies so security-sensitive tools such as shell execution, file reading, HTTP requests, and secret-management operations can always be excluded. 8. Update documentation to state that redaction is best-effort unless structural redaction and comprehensive tests are implemented. 9. Review and purge previously collected traces that may contain credentials, then rotate any potentially exposed secrets. ]]>
