From 77af0720aff1e3c8063749352c8ab34affc70a59 Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Tue, 15 Sep 2026 15:19:02 -0400 Subject: [PATCH 1/2] Document installing without the install script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only documented install was `curl … | sh`, which plenty of employers forbid outright. Nothing new has to be published for the alternative to work: `manifest.json` already lists every target with its checksum, the archives are plain HTTP, and each one holds a single `mapbox` executable. So this writes down what was already true. Every command in the new section was run verbatim before being committed, including the versioned URL: `cli.mapbox.com/v0.2.1/…` and `cli.mapbox.com/latest/…` both serve, `0.2.1/…` without the `v` is a 403, and `grep "$file" SHA256SUMS | shasum -a 256 -c -` is what checks one archive without the other four reporting as missing. Also drops "signed" from the sentence above it, because the builds are not. `codesign -dv` on the published macOS artifact reports `Signature=adhoc`, `TeamIdentifier=not set` — a linker signature, which arm64 requires to run at all, not a Mapbox one. There is no signing or notarization step anywhere in the publish pipeline, and none for Authenticode either. What the install script checks is the SHA-256 checksum, which the sentence already said. That has a consequence a manual installer meets and a `curl … | sh` user never does, so the section ends with it: `curl` attaches no quarantine flag, a browser download does, and Gatekeeper refuses an unsigned binary carrying one. 596 tests, fmt clean, no broken in-page anchors. --- CHANGELOG.md | 18 ++++++++++++++++++ README.md | 44 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bcbbd7..99e0875 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,24 @@ that may never merge. They are not releases and are not listed here. ## Unreleased +### Added + +- The README now documents installing without the install script: the + archives are plain HTTP downloads, `manifest.json` lists every target with + its checksum, and the commands to verify and extract one are written out. + Nothing new is published — this is the same channel the install script + reads, for anyone whose employer does not allow piping a script into a + shell. + +### Fixed + +- The README described the published builds as signed. They are not + code-signed with a Developer ID or an Authenticode certificate; what the + install script checks is a SHA-256 checksum. The claim is gone, and the new + section says what a macOS user hits because of it: Gatekeeper refuses an + unsigned binary carrying a quarantine flag, which a browser download sets + and `curl` does not. + ## 0.2.2 - 2026-09-15 ### Changed diff --git a/README.md b/README.md index e3d9ceb..afa49e2 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ time from OpenAPI specs, so they always match the specs. - [Build from source](#build-from-source) - [Install a released binary](#install-a-released-binary) + - [Download the archive yourself](#download-the-archive-yourself) - [Commands](#commands) - [Auth](#auth) - [Named profiles](#named-profiles) @@ -42,9 +43,9 @@ The OpenAPI specs the commands are generated from are vendored in ## Install a released binary -Mapbox publishes signed builds for macOS, Linux and Windows from a separate -repository. The install script detects your platform, checks a SHA-256 -checksum, and installs `mapbox`. No `sudo`, no admin rights: +Mapbox publishes builds for macOS, Linux and Windows. The install script +detects your platform, checks a SHA-256 checksum, and installs `mapbox`. +No `sudo`, no admin rights: ```sh curl -fsSL https://cli.mapbox.com/install.sh | sh @@ -60,6 +61,43 @@ them end to end without touching the network. Run `mapbox --help` once it's on your `PATH`. +### Download the archive yourself + +Nothing about the install script is required. If piping one into a shell is +not allowed where you work, the archives are ordinary HTTP downloads, and +`manifest.json` lists every target with its checksum: + +```sh +curl -fsSL https://cli.mapbox.com/latest/manifest.json +``` + +Five targets are published: `aarch64-apple-darwin`, `x86_64-apple-darwin`, +`aarch64-unknown-linux-musl`, `x86_64-unknown-linux-musl` and +`x86_64-pc-windows-msvc`. Pick yours, check it, then extract: + +```sh +version=v0.2.1 +file=mapbox-${version}-aarch64-apple-darwin.tar.gz + +curl -fsSLO "https://cli.mapbox.com/${version}/${file}" +curl -fsSL "https://cli.mapbox.com/${version}/SHA256SUMS" | + grep "$file" | shasum -a 256 -c - + +tar -xzf "$file" +mv mapbox ~/.local/bin/ +``` + +Use `latest` in place of the version for whatever is current. Each archive +holds one file, the `mapbox` executable, so there is no directory to step +into and nothing else to place. `~/.local/bin` is where the install script +puts it too, and `MAPBOX_INSTALL_DIR` is the variable it reads if you prefer +somewhere else. + +The macOS builds are not code-signed with a Developer ID. `curl` attaches no +quarantine flag, which is why the commands above run, but a download through +a browser does, and Gatekeeper will refuse an unsigned binary that carries +one. Clear it with `xattr -d com.apple.quarantine mapbox`. + ## Commands ### Auth From 597b988eb8aabbd1c8615d1623a7d79a980884d5 Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Wed, 16 Sep 2026 00:53:30 -0400 Subject: [PATCH 2/2] Give Windows a way to follow this section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The section named `x86_64-pc-windows-msvc` as one of five published targets and then offered only a `sh` block: `curl`, `grep`, `shasum`, `tar` and a `mv` into `~/.local/bin`. A Windows reader was told their build exists and given no way to fetch or check it, in the one section that exists for people who cannot run the install script. PowerShell takes a shorter route than the POSIX one rather than a translated version of it. `manifest.json` is structured and `Invoke-RestMethod` parses it, so there is no `SHA256SUMS` line to pick apart — the sha256 arrives as a field beside the filename. `Invoke-WebRequest` and `Get-FileHash` rather than `curl` and `sha256sum`: `curl` is an alias for `Invoke-WebRequest` in Windows PowerShell and the real thing in pwsh, and neither `sha256sum` nor `shasum` is guaranteed to be present at all. Run before committing, against the real published artifact, on pwsh 7.6: verified and extracted: mapbox-v0.2.1-x86_64-pc-windows-msvc.zip mapbox.exe My first version parsed `SHA256SUMS` with `Select-String` and threw "checksum mismatch" on a correct download, because the match returned null and the comparison was against an empty string. It would have told a reader their download was corrupt. That is the version this replaces. --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index afa49e2..23ae69e 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,28 @@ tar -xzf "$file" mv mapbox ~/.local/bin/ ``` +On Windows the archive is a `.zip` and PowerShell can read the manifest +directly, so there is no text file to parse: + +```powershell +$version = 'v0.2.1' +$target = 'x86_64-pc-windows-msvc' + +$manifest = Invoke-RestMethod "https://cli.mapbox.com/$version/manifest.json" +$artifact = $manifest.artifacts.$target + +Invoke-WebRequest "https://cli.mapbox.com/$version/$($artifact.file)" -OutFile $artifact.file +if ((Get-FileHash -Algorithm SHA256 $artifact.file).Hash -ine $artifact.sha256) { + throw 'checksum mismatch' +} + +Expand-Archive $artifact.file -DestinationPath . +``` + +`Invoke-WebRequest` and `Get-FileHash` rather than `curl` and `sha256sum`: +the first is an alias for something else in Windows PowerShell and neither of +the others is guaranteed to be present. + Use `latest` in place of the version for whatever is current. Each archive holds one file, the `mapbox` executable, so there is no directory to step into and nothing else to place. `~/.local/bin` is where the install script