T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/repost_post.py:35
- Finding
- Attacker-controlled URLs are opened in an authenticated browser with Chromium sandboxing disabled<![CDATA[ ## Vulnerability Details **File Location**: `scripts/session_lib.py:28-41`; `scripts/repost_post.py:35-38, 51-54, 112`; `scripts/like_post.py:31-34, 62`; `scripts/bookmark_post.py:31-34, 66` **Vulnerability Type**: Insufficient URL validation combined with disabled browser sandboxing **Risk Level**: High ### Vulnerable Code `scripts/session_lib.py:28-41`: ```python CHROMIUM_ARGS = [ "--no-sandbox", "--disable-dev-shm-usage", "--disable-gpu", "--disable-software-rasterizer", "--disable-setuid-sandbox", "--disable-background-networking", "--disable-default-apps", "--disable-sync", "--no-first-run", "--no-zygote", "--disable-features=TranslateUI", "--disable-blink-features=AutomationControlled", ] ``` `scripts/repost_post.py:35-38`: ```python def open_tweet_and_repost(page, tweet_url: str, tweet_id: str, timeout_ms: int) -> None: target = tweet_url if "/status/" in tweet_url else f"https://x.com/i/status/{tweet_id}" page.goto(target, wait_until="domcontentloaded", timeout=timeout_ms) page.wait_for_timeout(3000) ``` `scripts/repost_post.py:51-54`: ```python def open_tweet_and_quote(page, tweet_url: str, tweet_id: str, text: str, timeout_ms: int) -> None: target = tweet_url if "/status/" in tweet_url else f"https://x.com/i/status/{tweet_id}" page.goto(target, wait_until="domcontentloaded", timeout=timeout_ms) page.wait_for_timeout(3000) ``` `scripts/like_post.py:31-34`: ```python def open_tweet_and_like(page, tweet_url: str, tweet_id: str, undo: bool, timeout_ms: int) -> None: target = tweet_url if "/status/" in tweet_url else f"https://x.com/i/status/{tweet_id}" page.goto(target, wait_until="domcontentloaded", timeout=timeout_ms) page.wait_for_timeout(3000) ``` `scripts/bookmark_post.py:31-34`: ```python def open_tweet_and_bookmark(page, tweet_url: str, tweet_id: str, undo: bool, timeout_ms: int) -> None: target = tweet_url if "/status/" in tweet_url else f"h ...[truncated 2929 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Never navigate to the original user-supplied URL. After extracting and validating the numeric tweet ID, always construct a canonical destination: ```python tweet_id = extract_tweet_id(tweet_input) target = f"https://x.com/i/status/{tweet_id}" page.goto(target, wait_until="domcontentloaded", timeout=timeout_ms) ``` 2. If preserving supplied URLs is necessary, parse them with `urllib.parse.urlsplit()` and enforce all of the following: - Scheme is exactly `https`. - Hostname is exactly `x.com` or another explicitly approved X hostname. - No embedded credentials are present. - The path matches a strict tweet-status path pattern. - The normalized destination is reconstructed rather than using the raw input. 3. Remove `--no-sandbox` and `--disable-setuid-sandbox`. If the deployment environment cannot run Chromium with sandboxing enabled, execute the browser inside a separately isolated, non-privileged container or VM with: - No host filesystem access except narrowly required files. - A read-only project directory. - Restricted network egress. - No Linux capabilities. - A dedicated unprivileged account. 4. Separate unauthenticated navigation from the authenticated X context. The authenticated context should only be permitted to visit allowlisted X origins. 5. Add regression tests covering malicious inputs such as: - `https://attacker.example/status/123` - `http://x.com/status/123` - `https://x.com.attacker.example/status/123` - `file:///tmp/status/123` ]]>
