T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/redact_helpers.sh:4
- Finding
- Broad Local Evidence Collection Uses Incomplete Redaction and Does Not Enforce Secure Output Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/redact_helpers.sh:4-41`; related collection behavior in `SKILL.md:12-22` and `scripts/collect_verified.sh:7,68-74,157-199,321-356` **Vulnerability Type**: Sensitive information exposure through incomplete redaction and insecure evidence-file handling **Risk Level**: Medium ### Vulnerable Code The redaction implementation only recognizes a limited set of secret formats and preserves the last four characters of matched values: ```bash redact_value() { local val="$1" local len=${#val} if [ "$len" -le 4 ]; then printf '****' else printf '****%s' "${val: -4}" fi } redact_line() { local line="$1" local key val red if [[ "$line" =~ ([Bb]earer)[[:space:]]+([A-Za-z0-9._~+/=-]{8,}) ]]; then val="${BASH_REMATCH[2]}" red=$(redact_value "$val") line="${line/$val/$red}" fi if [[ "$line" =~ ([Tt]oken|[Pp]assword|[Ss]ecret|api[_-]?[Kk]ey|[Cc]ookie|[Aa]uth)[^=:\"]*[:=][[:space:]]*([A-Za-z0-9._~+/=-]{6,}) ]]; then val="${BASH_REMATCH[2]}" red=$(redact_value "$val") line="${line/$val/$red}" fi if [[ "$line" =~ \"([^\"]*(token|password|secret|api[_-]?key|cookie|auth)[^\"]*)\"[[:space:]]*:[[:space:]]*\"([^\"]{6,})\" ]]; then val="${BASH_REMATCH[3]}" red=$(redact_value "$val") line="${line/$val/$red}" fi printf '%s' "$line" } ``` The collector writes the resulting data to a caller-controlled or default path without explicitly creating the file with restrictive permissions: ```bash OUT_PATH=${OPENCLAW_AUDIT_OUT:-verified-bundle.json} ``` ```bash emit_header() { cat > "$OUT_PATH" <<EOF_HEADER { "meta": { "generated_at": "$(json_escape "$GENERATED_AT_UTC")", "script": "collect_verified.sh", "deep_requested": "${DEEP}", "state_dir": "$(json_escape "$STATE_DIR")", "config_path": "$(json_escape "$CONFIG_PATH")", "workspace_dir": "$(json_escape "$WORKSPACE_DIR")" }, "commands": { EOF_HEADER } ``` Captured command o ...[truncated 5202 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Enforce restrictive output permissions before collection** - Set `umask 077` near the beginning of the collector. - Create the output atomically with mode `0600`. - Reject output paths that resolve through unsafe symbolic links. - Consider using a private temporary directory owned by the invoking user. Example: ```bash umask 077 : > "$OUT_PATH" chmod 600 "$OUT_PATH" ``` A production implementation should additionally use exclusive creation and verify file ownership and type to mitigate symlink and replacement races. 2. **Replace denylist redaction with structured allowlisting** - Parse JSON outputs where available and retain only fields explicitly required by the audit. - Avoid storing full command responses when a boolean, count, status, or normalized endpoint is sufficient. - Treat unknown fields as sensitive by default. 3. **Do not preserve credential suffixes** - Replace secret values completely with a constant marker such as `[REDACTED]`. - If correlation is required, use a non-reversible keyed identifier rather than exposing credential characters. 4. **Reduce pattern-scan output** - Record only file path, line number, and matched rule identifier. - Do not store the complete matching source line. - Add an explicit opt-in before scanning directories outside the standard state or workspace skill roots. 5. **Constrain configured extra directories** - Canonicalize each path. - Reject symlinks and paths outside explicitly approved roots. - Require user confirmation before scanning externally configured directories. - Maintain strict depth, file-size, and file-type limits. 6. **Expand secret-detection testing as defense in depth** - Add tests for PEM private keys, URL credentials, JWTs, webhook URLs, single-quoted values, multiline values, multiple secrets per line, Unicode, and provider-specific credentials. - Treat regex redaction only as a ...[truncated 348 chars]
