T09 · Insecure Skill Coding Practices
- Location
- scripts/check-claude-oauth.sh:72
- Finding
- OAuth Callback Content Injection into Tcl/Expect Program<![CDATA[ ## Vulnerability Details **File Location**: `scripts/check-claude-oauth.sh`, lines 72-91 and 124-150 **Vulnerability Type**: Improper neutralization of externally sourced data in dynamically generated Tcl/Expect code **Risk Level**: High ### Vulnerable Code ```bash extract_code_from_chrome() { osascript -l JavaScript -e ' function run() { const chrome = Application("Google Chrome"); const windows = chrome.windows(); for (const w of windows) { const tabs = w.tabs(); for (let i = 0; i < tabs.length; i++) { const url = tabs[i].url(); if (url.includes("platform.claude.com/oauth/code/callback")) { try { const code = tabs[i].execute({javascript: "(() => { const el = document.querySelector(\".font-mono, [class*=code], code, pre\"); return el ? el.textContent.trim() : \"no_element\"; })()" }); return code || "no_code"; } catch(e) { return "js_error:" + e.message; } } } } return "no_tab"; } ' 2>/dev/null || echo "osascript_error" } ``` ```bash auth_code="" for attempt in $(seq 1 10); do auth_code=$(extract_code_from_chrome) case "$auth_code" in no_tab|no_element|no_code|js_error:*|osascript_error) sleep 1 ;; *) break ;; esac done if [ -z "$auth_code" ] || [[ "$auth_code" == no_* ]] || [[ "$auth_code" == *error* ]]; then kill "$login_pid" 2>/dev/null || true return 1 fi # 5. Kill PTY process, feed code to fresh auth login via expect kill "$login_pid" 2>/dev/null || true sleep 1 expect -c " set timeout 30 spawn claude auth login expect { timeout { exit 1 } -re {visit:|browser} { sleep 6 } } send \"$auth_code\r\" expect { timeout { exit 1 } -re {successful|success|Login} { exit 0 } } " &>/tmp/claude-auth-expect.log ``` ### Technical Analysis The script extracts text from a browser page and int ...[truncated 2756 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Never interpolate `auth_code` into dynamically generated Tcl source. 2. Pass the value through an environment variable or a positional argument and read it as data from a static Expect program. For example: ```bash export CLAUDE_AUTH_CODE="$auth_code" expect <<'EXPECT_EOF' set timeout 30 set auth_code $env(CLAUDE_AUTH_CODE) spawn claude auth login expect { timeout { exit 1 } -re {visit:|browser} { sleep 6 } } send -- "$auth_code\r" expect { timeout { exit 1 } -re {successful|success|Login} { exit 0 } } EXPECT_EOF unset CLAUDE_AUTH_CODE ``` 3. Use `send --` so values beginning with hyphens cannot be interpreted as options. 4. Validate the authorization code before passing it to Expect. Enforce the exact format documented by the authentication provider, including: - An allowlisted character set. - A reasonable minimum and maximum length. - Any required prefix or structural delimiters. 5. Replace the broad DOM selector with a precise selector tied to the expected callback-page element. 6. Reject values containing control characters, line breaks, Tcl metacharacters, or unexpected whitespace even when the value otherwise appears plausible. 7. Prefer a CLI-supported noninteractive OAuth flow or a documented callback mechanism over scraping browser-rendered content. ]]>
