Repository navigation
fix(security): fail-closed CLI checksum + https/browserstack.com redirect allowlist [DEVA11Y-473] - #46
Draft
Crash0v3rrid3 wants to merge 2 commits into
Draft
fix(security): fail-closed CLI checksum + https/browserstack.com redirect allowlist [DEVA11Y-473]#46Crash0v3rrid3 wants to merge 2 commits into
Crash0v3rrid3 wants to merge 2 commits into
Conversation
…VA11Y-473] followRedirects()/followWithGet() returned any Location target, and URLSession.shared auto-followed every hop, so an https -> http (or off-domain) redirect would fetch the CLI archive in cleartext or from an arbitrary host before our code saw the URL. Route the HEAD/GET resolution and the archive download through a session whose delegate vetoes any hop that is not https on browserstack.com or a subdomain, and re-check the vetoed Location / final response URL after each request as a backstop. The initial URL is still governed by parseOverride(), so an HTTPS override to a mirror keeps working as long as it does not redirect off-domain. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…[DEVA11Y-473] verifyArchiveChecksum aborted only on a digest mismatch. A sidecar that could not be derived, returned non-2xx, failed to fetch, or was not a 64-char hex digest let the archive be extracted and executed unverified, so blocking or corrupting the .sha256 bypassed the check entirely (Security retest of DEVA11Y-473 @806f98cb). Every one of those paths now throws before extraction. The sidecar fetch also goes through the redirect-guarded session. README updated to describe the plugin's fail-closed behaviour. MERGE GATE: sdk-assets.browserstack.com does not publish <asset>.sha256 yet (403 for all six platform binaries as of 2026-10-16), so this commit makes every plugin run fail until SDK assets ships the sidecars. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The Security retest of DEVA11Y-473 at
806f98cbreopened the ticket for two reasons:verifyArchiveChecksumaborted only on a mismatch. If the.sha256sidecar was missing, unreachable or malformed, the archive was extracted and executed unverified.followRedirects()/download()accepted any redirect target, so anhttp://(or off-domain) hop would be followed.URLSession.sharedalso auto-follows redirects, so the bad hop happened before our code saw the URL.What
Commit 1:
f882c50redirect allowlist (independent; can be cherry-picked and shipped on its own)downloadSessionwith aURLSessionTaskDelegatethat vetoes any redirect hop that isn'thttpsonbrowserstack.com/*.browserstack.com.followRedirects,followWithGetanddownload()use it, and they re-check the vetoedLocationand the finalresponse.urlas a backstop.parseOverride()(HTTPS only), so an HTTPS override to a mirror still works as long as it doesn't redirect off-domain.Commit 2:
2e23e29fail-closed checksumverifyArchiveChecksumthat used to log a warning and return now throws before extraction: sidecar can't be derived, non-2xx, fetch error, not a 64-char hex digest. The sidecar fetch also goes through the guarded session.As of 2026-10-16,
sdk-assets.browserstack.com/binary-{macos-arm64,macos-x64,linux-x64,linux-arm64,alpine-x64,win-x64}-1.62.0.zip.sha256all return 403. With commit 2 merged, every plugin run would fail until those files exist. Thespm-smoke-testjob will go red for exactly this reason.Testing (local, macOS arm64, real network)
api.browserstack.com→sdk-assets), after commit 1 onlycodeload.github.com)Refusing to follow redirect … only https:// URLs on browserstack.com are allowed.http://sdk-assets.browserstack.com/…No BrowserStack CLI checksum available … (HTTP 403); refusing to use the downloaded binary..sha256returns a 200 JSON bodyMalformed BrowserStack CLI checksum …raw.githubusercontent.com/…/scripts/bash/cli.sh(valid published sidecar)The mismatch path is unchanged. The plugin isn't unit-testable (private functions inside a command-plugin target), so these were exercised end-to-end via
swift package … scan.Out of scope / follow-ups
scripts/{bash,zsh,fish}/cli.sh→verify_binary_integrity) have the same fail-open behaviour. That code is tracked under DEVA11Y-474 and should get the same treatment once the sidecars exist.🤖 Generated with Claude Code