From ecd1c1ab6dea1766eda5c5722c34142f25d0996a Mon Sep 17 00:00:00 2001 From: Sunny Sethi Date: Tue, 26 May 2026 14:29:26 +0530 Subject: [PATCH 1/2] fix(security): remove insecure self-update from cli.sh scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit F-003 / DEVA11Y-475 — script_self_update() fetched the script from a mutable branch head with no integrity verification (CWE-494). The ^#! regex check is trivially bypassed. Remove self-update entirely; users should update via git pull or package manager. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/bash/cli.sh | 10 ---------- scripts/fish/cli.sh | 10 ---------- scripts/zsh/cli.sh | 10 ---------- 3 files changed, 30 deletions(-) diff --git a/scripts/bash/cli.sh b/scripts/bash/cli.sh index d39f524..29a17d1 100644 --- a/scripts/bash/cli.sh +++ b/scripts/bash/cli.sh @@ -78,21 +78,11 @@ a11y_scan() { $BINARY_PATH a11y $EXTRA_ARGS } -script_self_update() { - local remote_url="https://raw.githubusercontent.com/browserstack/AccessibilityDevTools/refs/heads/main/scripts/bash/cli.sh" - - updated_script=$(curl -R -z "$SCRIPT_PATH" "$remote_url") - if [[ $updated_script =~ ^#! ]]; then - echo "$updated_script" > "$SCRIPT_PATH" - fi -} - download_binary() { curl -R -z "$BINARY_ZIP_PATH" -L "http://api.browserstack.com/sdk/v1/download_cli?os=${OS}&os_arch=${ARCH}" -o "$BINARY_ZIP_PATH" bsdtar -xvf "$BINARY_ZIP_PATH" -O > "$BINARY_PATH" && chmod 0775 "$BINARY_PATH" } -script_self_update if [[ $SUBCOMMAND == "register-pre-commit-hook" ]]; then register_git_hook exit 0 diff --git a/scripts/fish/cli.sh b/scripts/fish/cli.sh index 6bf3d8b..cc411dd 100644 --- a/scripts/fish/cli.sh +++ b/scripts/fish/cli.sh @@ -90,21 +90,11 @@ a11y_scan() { $BINARY_PATH a11y $EXTRA_ARGS } -script_self_update() { - local remote_url="https://raw.githubusercontent.com/browserstack/AccessibilityDevTools/refs/heads/main/scripts/fish/cli.sh" - - updated_script=$(curl -R -z "$SCRIPT_PATH" "$remote_url") - if [[ $updated_script =~ ^#! ]]; then - echo "$updated_script" > "$SCRIPT_PATH" - fi -} - download_binary() { curl -R -z "$BINARY_ZIP_PATH" -L "http://api.browserstack.com/sdk/v1/download_cli?os=${OS}&os_arch=${ARCH}" -o "$BINARY_ZIP_PATH" bsdtar -xvf "$BINARY_ZIP_PATH" -O > "$BINARY_PATH" && chmod 0775 "$BINARY_PATH" } -script_self_update if [[ $SUBCOMMAND == "register-pre-commit-hook" ]]; then register_git_hook exit 0 diff --git a/scripts/zsh/cli.sh b/scripts/zsh/cli.sh index 697ad4e..80c957b 100644 --- a/scripts/zsh/cli.sh +++ b/scripts/zsh/cli.sh @@ -89,21 +89,11 @@ a11y_scan() { $BINARY_PATH a11y $EXTRA_ARGS } -script_self_update() { - local remote_url="https://raw.githubusercontent.com/browserstack/AccessibilityDevTools/refs/heads/main/scripts/zsh/cli.sh" - - updated_script=$(curl -R -z "$SCRIPT_PATH" "$remote_url") - if [[ $updated_script =~ ^#! ]]; then - echo "$updated_script" > "$SCRIPT_PATH" - fi -} - download_binary() { curl -R -z "$BINARY_ZIP_PATH" -L "http://api.browserstack.com/sdk/v1/download_cli?os=${OS}&os_arch=${ARCH}" -o "$BINARY_ZIP_PATH" bsdtar -xvf "$BINARY_ZIP_PATH" -O > "$BINARY_PATH" && chmod 0775 "$BINARY_PATH" } -script_self_update if [[ $SUBCOMMAND == "register-pre-commit-hook" ]]; then register_git_hook exit 0 From e098f6e2ac4ece5e19c45086fcd51935cf744dbf Mon Sep 17 00:00:00 2001 From: Sunny Sethi Date: Wed, 27 May 2026 15:55:53 +0530 Subject: [PATCH 2/2] Preserve self-update with SHA-256 integrity verification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of removing script_self_update() entirely, restore it with hardening: HTTPS-only fetch (pairs with PR #13) + SHA-256 checksum verification against a .sha256 sidecar file. Silently skips update if checksum fetch fails or hash mismatch — never overwrites with unverified content. Requires publishing .sha256 sidecar files alongside each script. DEVA11Y-475 Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/bash/cli.sh | 18 ++++++++++++++++++ scripts/fish/cli.sh | 18 ++++++++++++++++++ scripts/zsh/cli.sh | 18 ++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/scripts/bash/cli.sh b/scripts/bash/cli.sh index 29a17d1..0573505 100644 --- a/scripts/bash/cli.sh +++ b/scripts/bash/cli.sh @@ -78,11 +78,29 @@ a11y_scan() { $BINARY_PATH a11y $EXTRA_ARGS } +script_self_update() { + local remote_url="https://raw.githubusercontent.com/browserstack/AccessibilityDevTools/refs/heads/main/scripts/bash/cli.sh" + local checksum_url="${remote_url}.sha256" + + local updated_script + updated_script=$(curl -sfSL "$remote_url") || return 0 + local expected_hash + expected_hash=$(curl -sfSL "$checksum_url" | awk '{print $1}') || return 0 + + local actual_hash + actual_hash=$(printf '%s' "$updated_script" | shasum -a 256 | awk '{print $1}') + + if [[ -n "$expected_hash" ]] && [[ "$actual_hash" == "$expected_hash" ]] && [[ $updated_script =~ ^#! ]]; then + echo "$updated_script" > "$SCRIPT_PATH" + fi +} + download_binary() { curl -R -z "$BINARY_ZIP_PATH" -L "http://api.browserstack.com/sdk/v1/download_cli?os=${OS}&os_arch=${ARCH}" -o "$BINARY_ZIP_PATH" bsdtar -xvf "$BINARY_ZIP_PATH" -O > "$BINARY_PATH" && chmod 0775 "$BINARY_PATH" } +script_self_update if [[ $SUBCOMMAND == "register-pre-commit-hook" ]]; then register_git_hook exit 0 diff --git a/scripts/fish/cli.sh b/scripts/fish/cli.sh index cc411dd..9de11a7 100644 --- a/scripts/fish/cli.sh +++ b/scripts/fish/cli.sh @@ -90,11 +90,29 @@ a11y_scan() { $BINARY_PATH a11y $EXTRA_ARGS } +script_self_update() { + local remote_url="https://raw.githubusercontent.com/browserstack/AccessibilityDevTools/refs/heads/main/scripts/fish/cli.sh" + local checksum_url="${remote_url}.sha256" + + local updated_script + updated_script=$(curl -sfSL "$remote_url") || return 0 + local expected_hash + expected_hash=$(curl -sfSL "$checksum_url" | awk '{print $1}') || return 0 + + local actual_hash + actual_hash=$(printf '%s' "$updated_script" | shasum -a 256 | awk '{print $1}') + + if [[ -n "$expected_hash" ]] && [[ "$actual_hash" == "$expected_hash" ]] && [[ $updated_script =~ ^#! ]]; then + echo "$updated_script" > "$SCRIPT_PATH" + fi +} + download_binary() { curl -R -z "$BINARY_ZIP_PATH" -L "http://api.browserstack.com/sdk/v1/download_cli?os=${OS}&os_arch=${ARCH}" -o "$BINARY_ZIP_PATH" bsdtar -xvf "$BINARY_ZIP_PATH" -O > "$BINARY_PATH" && chmod 0775 "$BINARY_PATH" } +script_self_update if [[ $SUBCOMMAND == "register-pre-commit-hook" ]]; then register_git_hook exit 0 diff --git a/scripts/zsh/cli.sh b/scripts/zsh/cli.sh index 80c957b..ff4bb6e 100644 --- a/scripts/zsh/cli.sh +++ b/scripts/zsh/cli.sh @@ -89,11 +89,29 @@ a11y_scan() { $BINARY_PATH a11y $EXTRA_ARGS } +script_self_update() { + local remote_url="https://raw.githubusercontent.com/browserstack/AccessibilityDevTools/refs/heads/main/scripts/zsh/cli.sh" + local checksum_url="${remote_url}.sha256" + + local updated_script + updated_script=$(curl -sfSL "$remote_url") || return 0 + local expected_hash + expected_hash=$(curl -sfSL "$checksum_url" | awk '{print $1}') || return 0 + + local actual_hash + actual_hash=$(printf '%s' "$updated_script" | shasum -a 256 | awk '{print $1}') + + if [[ -n "$expected_hash" ]] && [[ "$actual_hash" == "$expected_hash" ]] && [[ $updated_script =~ ^#! ]]; then + echo "$updated_script" > "$SCRIPT_PATH" + fi +} + download_binary() { curl -R -z "$BINARY_ZIP_PATH" -L "http://api.browserstack.com/sdk/v1/download_cli?os=${OS}&os_arch=${ARCH}" -o "$BINARY_ZIP_PATH" bsdtar -xvf "$BINARY_ZIP_PATH" -O > "$BINARY_PATH" && chmod 0775 "$BINARY_PATH" } +script_self_update if [[ $SUBCOMMAND == "register-pre-commit-hook" ]]; then register_git_hook exit 0