Repository navigation
fix(security): allowlist browserstack.com for the CLI download URL override [DEVA11Y-479][DEVA11Y-488] - #50
Open
nmnishant-browserstack wants to merge 4 commits into
Conversation
…de [DEVA11Y-479][DEVA11Y-488] parseOverride() now rejects any --download-url / BROWSERSTACK_A11Y_CLI_DOWNLOAD_URL whose host is not browserstack.com or a subdomain, using the same policy PR #46 applies to redirect hops. The file:// branches in resolveOverrideArtifact() and download() are removed, and download() refuses any URL outside the policy. Adds tests/download-url-policy, which lifts parseOverride verbatim and checks off-domain, userinfo, look-alike, IP, non-https, file:// and bare-path inputs. Wired into spm-smoke-test.yml. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
extractVersion() accepted a redirect filename ending in '-..zip' as version '.', which resolves to the cache root itself. Reject it, and cover the version parser in tests/download-url-policy. 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 |
nmnishant-browserstack
marked this pull request as ready for review
October 22, 2026 10:35
…-479] Keeps the PR to the scope of the Security retest. The suite stays in tests/download-url-policy and runs locally. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Restores the download-url-policy job so the override allowlist is checked on every PR. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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-479 and DEVA11Y-488 at
806f98cbfound that the--download-url/BROWSERSTACK_A11Y_CLI_DOWNLOAD_URLoverride still accepted any HTTPS host. Anyone who can set that env var (CI env injection, a malicious PR workflow, a poisoned.env) could point the plugin at their own server. #46 closed the redirect and integrity gaps; this closes the remaining ones:file://copy branch indownload().What
54eba31– override host allowlistparseOverride()now requireshttpsand a host ofbrowserstack.comor a subdomain. It reusesisAllowedRedirectTarget()from fix(security): fail-closed CLI signature verification + https/browserstack.com redirect allowlist [DEVA11Y-473] #46, so the override and every redirect hop follow one policy.url.isFileURLbranches inresolveOverrideArtifact()anddownload().download()now refuses any URL outside the policy before fetching, so a file URL can never be copied, however it was produced.github.comis not allowlisted, departing from the ticket's suggestion: GitHub release downloads redirect tocodeload.github.com/objects.githubusercontent.com, which the fix(security): fail-closed CLI signature verification + https/browserstack.com redirect allowlist [DEVA11Y-473] #46 redirect policy rejects, so allowing it here would only produce a confusing failure later. Rationale in this comment on 479.0126efa– reject.as a cache versionextractVersion()accepted a filename ending in-..zipas version., which resolves to the cache root itself. Found while replaying the C-002 chain for DEVA11Y-486; it doesn't reopen that chain.Tests
tests/download-url-policy/run_tests.shliftsparseOverride,isAllowedRedirectTargetandextractVersionverbatim from the plugin source and checks them against a case table. It needs no network and no credentials, and runs as a newdownload-url-policyjob inspm-smoke-test.yml.Testing
Policy suite: 30/30 pass. Against
mainbefore this change, 11 of the 23 URL cases fail, so the suite detects the gap.https://api.browserstack.com/sdk/v1/download_cli?…https://evil.example/cli.ziphttps://sdk-assets.browserstack.com/…https://api.browserstack.com@evil.example/…(userinfo trick)https://browserstack.com/…https://evilbrowserstack.com/…,https://browserstack.com.evil.example/…HTTPS://API.BROWSERSTACK.COM/…(case)https://127.0.0.1/…,https://169.254.169.254/…https://api.browserstack.com:443/…https://github.com/…,http://…,ftp://…,file://…,/tmp/cli.zip,https:///cli.zipEnd to end: the plugin was built and run via
tests/spmon macOS:The default download (no override) is unchanged: it downloads CLI 1.63.0 and passes the signature check.
Authenticated sanity scan (macOS, Xcode 26.3 / Swift 6.2.4, production BrowserStack account). The plugin was rebuilt from this branch with a clean
tests/spm/.build, thentests/spm/scripts/run-a11y-scan.shran against the harness:BROWSERSTACK_A11Y_CLI_FORCE_DOWNLOAD=1) through the changed pathTeamIdentifier=YQ5FZQ855D--non-strictscanSampleViews.swift(imageview-element-content-label,interactable-element-content-label,switch-element-content-label)Note for local runs:
RUN_A11Y_SCAN=1 swift testhung here (~10 min, no scan process started), most likely because the test's innerswift package pluginwaits on the.buildlock held by the outerswift testunder SwiftPM 6.2. The two scans above are the same assertionstestA11yScanPluginRunsmakes, run directly. CI (macos-14) is unaffected, and this PR doesn't touch that test.After merge
Request a Security retest of DEVA11Y-479. DEVA11Y-488 closes on that result.
🤖 Generated with Claude Code