This is the detailed support matrix for socket-patch: which package ecosystems work
with which patch mode, the per-ecosystem caveats, and
the platforms the binary ships for.
For what the three modes are and how to choose between them, see How Socket Patch works in the README.
The backticked slug in each row is the value -e/--ecosystems accepts (e.g.
--ecosystems npm,pypi,golang).
| Ecosystem | agent (--mode agent) |
vendored (--mode vendored) |
hosted (--mode hosted) |
|---|---|---|---|
npm (npm) — pnpm / yarn / berry / bun |
✅ any install layout; setup postinstall hook |
✅ six lockfile flavors: package-lock, yarn classic, yarn berry (node-modules linker; PnP refused), pnpm v9, pnpm legacy v5.4/v6.0 (pnpm 7/8 — frozen installs are path-bound because those majors absolutize file: override specifiers; moved checkouts run one pnpm install --offline --no-frozen-lockfile, surfaced as vendor_pnpm_legacy_absolute_specifier), bun text bun.lock lockfileVersion 0/1/2 and native binary bun.lockb revisions 1/2/3 (binary locks stay binary; text workspace vendoring requires lockfileVersion 2 — see Bun compatibility). Rush monorepos refused (vendor_rush_unsupported) — see Rush notes |
✅ package-lock / npm-shrinkwrap, pnpm-lock.yaml and legacy shrinkwrap.yaml (pnpm majors 1–12; block and flow resolutions), yarn classic, yarn berry, bun — pnpm, berry, and bun carry constraints, see npm hosted-mode notes |
PyPI (pypi) — uv / poetry / pdm / pipenv / pip |
✅ .pth startup hook via setup |
✅ uv project/script locks, PEP 751 pylock.toml / pylock.<name>.toml, poetry, pdm, pipenv (Pipenv 2018 or later — every Pipfile.lock category is rewired, lock-only checkouts included; Pipenv 2023+ does not hash-check local wheels — vendor_integrity_unverified; a venv still holding the upstream release is reported as pypi_pipenv_stale_install; see Pipenv compatibility), and requirements.txt. Native uv vendoring requires uv ≥ 0.2.35 (the [[package]] lock grammar); hosted mode covers native uv.lock from uv 0.1.45 (the first release whose uv lock writes one) and requirements from uv 0.0.5; see uv compatibility. |
✅ requirements.txt including hash continuations, uv project/script locks, and PEP 751 locks. Version/source ambiguity is refused; see uv compatibility. Poetry 1.x and 2.x locks are supported; Poetry 0.x ignores URL sources and is refused. See Poetry compatibility. Pipenv Pipfile.lock (pipfile-spec 6 — Pipenv 7 and later; path references for 7–11, file from 2018; lock-only checkouts and Pipenv's out-of-tree venv are discovered; a warm venv that Pipenv will not reinstall over warns redirect_pypi_stale_install; see Pipenv compatibility). pdm.lock is supported for the lock formats PDM 0.12–1.4 and 2.8.1+ write (lock_version 2 / 4.3–4.5.1); the identity-losing 3.1 / 4.0–4.2 formats (PDM 1.8–2.7) are refused. PDM 2.8.0 writes an indistinguishable 4.3 lock but shares that identity-loss bug, so a rewritten 2.8.0 lock crashes pdm sync — upgrade to ≥ 2.8.1. See PDM compatibility. |
Cargo (cargo) |
✅ in-place + .cargo-checksum.json rewrite (shared registry-cache caveat — see Cargo: shared registry cache) |
✅ [patch.crates-io] path entry in the root Cargo.toml (v5; per-version Socket keys; pre-v5 .cargo/config* wiring migrates on re-run) |
✅ per-patch sparse registry ([registries.socket-patch-<uuid>] + Cargo.lock source/checksum); direct dependencies only — a crate another dependency also pulls in is refused, use --mode vendored; with no Cargo.lock the graph is unknown, so only a project whose sole dependency is the patched crate is redirected |
RubyGems (gem) |
✅ Bundler plugin via setup — needs bundler ≥ 2.2 (1.x cannot load plugin ... path: directives; setup refuses below the floor and setup --check red-flags a wired 1.x project) |
✅ Gemfile + Gemfile.lock path pair (Gemfile spelling only — a gems.rb project cannot vendor yet) |
✅ per-dep source block — edits gems.rb + gems.locked when present (bundler prefers them over Gemfile; spellings that diverge beyond Socket's own edits fail closed with redirect_gem_gemfile_spellings_diverge); the CHECKSUMS pin needs bundler ≥ 2.6 (older locks get a redirect_gem_no_checksums_section warning); a stale pre-redirect materialization that bundle install would reuse instead of refetching is flagged redirect_gem_stale_install with a prescriptive remedy (see CLI_CONTRACT.md's "Gem stale-install guard") |
Go (golang) |
✅ go.mod replace → .socket/go-patches/ — see Go: directory replaces and go.sum |
✅ replace → the committed vendor tree |
✅ (free tier) fork-style replace → patch.socket.dev/gopatch/<uuid> + committed go.sum pin; see golang-hosted.md. Paid tier stays ❌ (golang-hosted-no-go.md); redirect_golang_unsupported names the vendored remedy |
Maven (maven) |
✅ apply-only (no setup hook — reports no_files); in-place jar patching leaves the ~/.m2 checksum sidecars stale — prefer vendored / hosted, see Maven & NuGet caveats |
✅ committed maven2 file:// repository. A root pom declaring <modules> (multi-module aggregator) is refused (vendor_maven_multimodule_unsupported), and a gradle-only project is refused (vendor_gradle_unsupported) |
✅ pom projects only, fail-closed — the patched jar is pinned at a Socket-only <version>-socket.<hex8> suffix; ${property} versions are refused; Gradle gets a manual exclusiveContent snippet — see Maven & NuGet caveats |
NuGet (nuget) |
✅ apply-only (no setup hook — reports no_files); in-place patching deletes .nupkg.metadata and advises on the .nupkg.sha512 tamper-evidence sidecar — prefer vendored / hosted, see Maven & NuGet caveats |
✅ committed folder feed + packageSourceMapping + packages.lock.json contentHash pin |
✅ nuget.config source + source-mapping, packages.lock.json contentHash rewrite. See the locked-mode note in Maven & NuGet caveats |
Composer (composer) |
✅ post-install script events | ✅ composer.lock dist: path rewrite |
✅ composer.lock dist url + shasum rewrite |
Deno (deno) |
✅ apply-only — no install hook (setup reports no_files); declare in setup.manual for VEX coverage |
❌ refused (vendor_unsupported_ecosystem) |
❌ not supported |
Maven / NuGet sidecar caveat: Maven and NuGet are fully enabled in every mode (the old
SOCKET_EXPERIMENTAL_MAVEN/SOCKET_EXPERIMENTAL_NUGETopt-ins are retired). In-place (agent-mode) patching leaves the caches' own checksum sidecars stale: NuGet's post-apply fixup deletes.nupkg.metadataand raises an advisory for the signed-package.nupkg.sha512tamper marker it cannot honestly rewrite; Maven's.jar.sha1/.jar.md5are left as-is. The copy-out modes —vendor,scan --mode vendored,scan --mode hosted— never write into the caches and avoid the issue entirely.
- npm (package-lock.json / npm-shrinkwrap.json) — every present npm lock is
rewritten (npm 12 installs from the package-lock.json twin it keeps beside a
committed shrinkwrap). npm 12 defaults
allow-remote=noneand refuses the redirected tarballs (EALLOWREMOTE) unless the project.npmrcsetsallow-remote=all, so the hosted run writes it (new file, or one appended line; ledger-recorded asredirect_npmrc_allow_remoteand removed again byrollback/remove/ the vendored takeover) and always warnsredirect_npm_allow_remotewith the tradeoff (any url-resolved dependency is then admitted; sha512 pins stay enforced). Commit.npmrcwith the lock. An explicit userallow-remote=none/rootis respected (never rewritten or overridden) — in the project.npmrc, the user / global / builtin npm config, or annpm_config_allow_remoteenvironment variable — and--no-npm-allow-remote-configopts out (install withnpm ci --allow-remote=all). Vendoredfile:tarballs are unaffected (npm gates them byallow-file, defaultall). npm 6 ignoresresolvedfor registry dependencies, so a redirected lockfileVersion 1 lock fails closed with EINTEGRITY under npm 6 (redirect_npm_legacy_client) and installs under npm= 7. Vendoring needs a lockfileVersion 2/3 lock (npm 6 still installs a vendored v2 lock from its legacy mirror) and rewires both locks in npm 12's dual-lock state. Majors 6–12 are measured in npm compatibility.
- pnpm — hosted rewriting supports legacy
shrinkwrap.yaml(pnpm 1/2), lockfileVersion 5.x (pnpm 3–7), 6.0 (pnpm 8), and 9.0 (pnpm 9–12). Early pnpm 1 locks with shrinkwrapVersion 3 and no positive minor version are refused because those installers discard hosted URLs; the tested pnpm 1 floor is 1.43.1. Upgrade and regenerate that lock, or use agent mode. Block and flow resolutions, scoped names, aliases, nested peer contexts, workspaces, nested Rush locks, and LF/CRLF line endings are handled. Every matching package instance is rewritten; an unsupported instance prevents confirming that dependency across the lockfile set. Rollback preserves the original resolution fragments. For root 9.0 locks, the CLI configurestrustLockfile: trueinpnpm-workspace.yamlunless opted out with--no-trust-lockfile-configor explicitly disabled by the project. pnpm >=11 needs this for hosted URLs. This skips registry re-verification for the whole lock; tarball integrity remains enforced. pnpm <=10 does not need the setting. Reinstall after redirecting: a successful warm-cache install can retain upstream bytes. Use a clean install tree and an empty store;--forceis not a reliable substitute. Runsocket-patch vexafter installation to verify the patched files. See the compatibility matrix and workflow. - yarn berry — the redirect edits the
yarn.lockentry only (cacheKey10c0/ yarn 4), and.yarnrc.yml'scompressionLevelmust stay 0. The node-modules linker is e2e-covered; PnP is untested for hosted — the lock rewrite fires, but PnP's.yarn/cacheresolution isn't exercised. CRLF locks — what yarn writes on Windows, and what acore.autocrlfcheckout produces anywhere — are rewritten in their own line ending (a BOM is kept); a lock mixing CRLF and LF is refused (redirect_yarn_berry_mixed_line_endings) untilyarn installnormalizes it. See yarn berry compatibility. - yarn
npm:aliases (classic & berry) — a lock entry that consumes the patched package only through an alias descriptor ("safe-pad@npm:left-pad@^1.3.0") is left untouched, with aredirect_yarn_classic_alias_skipped/redirect_yarn_berry_alias_skippedwarning naming the entry — that copy keeps the unpatched artifact. The reverse shape — an alias of the patched NAME pointing at a different package ("left-pad@npm:some-fork@^1.3.0", the fork-substitution idiom) — is never rewritten: it resolves a different package. - bun — text
bun.locklockfileVersion 0, 1 or 2: 0 is the--save-text-lockfileopt-in lock of Bun 1.1.39–1.1.45, 1 the 1.2–1.3 default, 2 the 1.4+ default; all three emit onepackagesgrammar, so registry entries rewrite identically. Any other or missing version, or apackagessection outside bun's single-line grammar, is refusedredirect_bun_lock_unsupported(a newer version means "update socket-patch" — re-locking would reproduce it). A version-0 lock holdingworkspace:packages is refusedredirect_bun_workspace_unsupported: frozen installs of that grammar cannot keep the hosted tuple; deletebun.lockand re-lock with Bun ≥ 1.2 (which writes lockfileVersion 1, accepted) — a plain in-placebun installbumps the version only when a workspace depends on another workspace (root → member), otherwise Bun 1.2.0 keeps version 0 and 1.2.23+ fail to resolve. Version-1 and version-2 workspace locks (nested versions included) are rewritten. Binarybun.lockbfiles are read and patched natively in hosted and vendored modes, including lockfile-only discovery. The CLI updates package resolutions, integrity records and Bun's metadata hash without spawning Bun or creating a text lock. Textbun.locktakes precedence when both exist; malformed binary locks fail closed before patching. Hosted → vendored and vendored → hosted conversions both work in place (mode takeover) — on a lock the vendored backend refuses (a pre-version-2workspace:lock)vendorreports the refusal before the hosted revert and leaves the purl hosted-patched — androllback <purl>/remove <purl>unwind one of several hosted bun redirects. Bun verifies the sha512 of URL and local-tarball tuples only from 1.3.10 (registry tuples from 1.2.0), so on 1.1.39–1.3.9 a hosted or vendored rewrite removes digest enforcement for the patched package. Every boundary here is measured against real Bun releases — see Bun compatibility.
A Rush repo has no root package.json/lockfile pair — its pnpm source-of-truth locks
live at common/config/rush/pnpm-lock.yaml (plus one per subspace under
common/config/subspaces/<name>/).
- Hosted ✅ —
scan --mode hosteddiscovers and repoints those locks in place (subspaces included). - Agent ✅ — works through the generated project symlink farm.
- Vendored ❌ — refused (
vendor_rush_unsupported):rush installcopies the lock intocommon/tempand runs pnpm there, so vendor's relativefile:specs can't survive the copy — the refusal routes you to hosted mode.
Editing a Rush lock outside rush update desyncs the pnpmShrinkwrapHash in
common/config/rush/repo-state.json, so when preventManualShrinkwrapChanges is enabled
rush install fails until rush update refreshes it (a redirect_rush_repo_state_stale
warning flags this; the redirect survives the refresh — pnpm keeps locked resolutions for
unchanged specifiers).
Honest limits of the Maven and NuGet flows — documented behavior, not bugs:
- Fail-closed by version suffixing (hosted Maven). Maven has no lockfile, so hosted
mode pins the patch a different way: the Socket patch server (
patch.socket.dev) exposes the patched jar under a globally-unique<version>-socket.<hex8>suffix that exists only on the injectedsocket-patch-<uuid>repository. The rewriter pins that suffixed version explicitly — it rewrites the literal<version>, or (for a transitive / managed dependency with no literal version in your pom) adds a<dependencyManagement>entry — so a resolver that can't reach the Socket repo, or is handed different bytes, has nowhere to fall through to: the build hard-fails instead of silently resolving the unpatched upstream artifact. The<repository>'schecksumPolicy=failstill verifies the transport-level.jar.sha1sidecar on top. A${property}version is refused (redirect_maven_dep_unpinned) — a literal edit would break the property reference and a depMgmt pin could strand sibling artifacts sharing the property. A literal version that matches neither the base nor the suffixed value is skipped (redirect_maven_dep_version_mismatch). - Trusted Checksums reinforcement (hosted Maven, 3.9+). When the patch server
supplies both the jar and pom sha256, the rewriter also emits Maven
Trusted Checksums files —
.mvn/maven.configresolver args plus.mvn/checksums/checksums.sha256entries pinning both artifacts under the suffixed version's local-repo path (merging into any pre-existing user config / checksum set; a conflicting value is never overridden and surfacesredirect_maven_trusted_checksums_conflict). This is an independent client-side content pin on top of the transport check. It requires Maven 3.9+ (the resolver post-processor and the${session.rootDirectory}basedir expression the config uses); on older Maven the.mvn/*files are silently inert — the version-suffixing above is still fail-closed on its own. On Maven 3.9.0–3.9.8 a mismatch is enforced but reported unclearly; the readability fix landed in 3.9.9 (MNG-8182). The args areoriginAware=falseandfailIfMissing=false, so one checksum matches the artifact from any repository and a dependency with no committed checksum still resolves — only a mismatch fails. - Warm
~/.m2shadowing (vendored Maven only). Maven consults the local repository before any configured<repository>, so with vendored mode a warm~/.m2copy of the same GAV silently wins over the committedfile://repository — the build succeeds with unpatched bytes. Purge it with:mvn dependency:purge-local-repository -DmanualInclude=<groupId>:<artifactId>(the always-onvendor_maven_local_cache_shadowwarning carries the same one-liner). Hosted mode is not affected: the patched jar lives at the suffixed version, which no warm~/.m2entry can hold. mirrorOfmirrors (hosted Maven). Asettings.xml<mirror>with<mirrorOf>*</mirrorOf>(common in corporate environments) reroutes all repositories — including the injectedsocket-patch-<uuid>repository — through the mirror. Because the patch resolves only at the suffixed version, the mirror (which does not carry it) can't serve it and the build fails loudly rather than silently going unpatched. Scope the mirror to exclude the Socket repos (e.g.<mirrorOf>*,!socket-patch-*</mirrorOf>) so the redirect resolves; theoriginAware=falseTrusted Checksums act as a backstop when present.- Gradle (hosted Maven). Gradle build scripts are never edited. A present
build.gradle*/settings.gradle*gets a paste-ableexclusiveContent { … }snippet (aredirect_gradle_manual_snippetwarning) that carries the suffixed version — and you must bump thegroupId:artifactIddependency declaration to that suffixed version yourself. It is fail-closed by repository exclusivity: theexclusiveContentfilter routes only the suffixed version to the Socket repo, which is the only place it exists. - NuGet locked mode (hosted + vendored). With a
packages.lock.jsonanddotnet restore --locked-mode, the rewrittencontentHashpins the patched.nupkg— a tampered or wrong package fails restore withNU1403. Without a lockfile there is no client-side content pin (vendored surfaces this as avendor_nuget_no_lockfilewarning; the feed + source mapping still force the patched copy).
Agent mode patches the crate in place wherever the crawler finds it. For a non-vendored
crate that means the shared $CARGO_HOME/registry cache: the patch affects every
project on the machine, and is silently reset by cargo clean or a cache prune. Use
--mode vendored for a project-local, committable patch.
Vendored mode (v5+) wires a patched crate with a [patch.crates-io] path
entry in the workspace-root Cargo.toml (the manifest beside the
Cargo.lock it detaches) plus the lock surgery that drops the crate's
source/checksum and records the copy's tagged version:
[patch.crates-io]
cfg-if-socket-9f6b2c4e = { package = "cfg-if", path = ".socket/vendor/cargo/<uuid>/cfg-if-1.0.4" }
# a second vendored version of the same crate (needs cargo 1.45+):
cfg-if-socket-0a1b2c3d = { package = "cfg-if", path = ".socket/vendor/cargo/<uuid2>/cfg-if-0.1.10" }# Cargo.lock
[[package]]
name = "cfg-if"
version = "1.0.4+socket.<uuid>"- Tagged versions. The vendored copy's own
Cargo.tomlversion is rewritten to<version>+socket.<uuid>(a version with build metadata keeps it:2.0.1+zstd.1.5.2→2.0.1+zstd.1.5.2.socket.<uuid>), and the detached lock entry carries the same tagged version — the lock cargo itself writes for the tagged copy. Cargo ignores build metadata when matching requirements, so1.0.4,=1.0.4,1,^1in any dependent still select the copy. The lock alone therefore names the patch uuid of the copy cargo builds (a[patch]override elsewhere changes the locked version), and stripping the tag gives the purl version. Every lock reference that spells the version ("cfg-if 1.0.4", v1's full ids) is rewritten with it, in lock formats v1–v4; a lock that cannot be kept consistent refuses withcargo_lock_untaggablebefore any write. The patched crate sees the tag inCARGO_PKG_VERSION— e.g. a vendored binary crate's--versionoutput shows it; requirement matching (semver::VersionReq) is unaffected, but string comparisons and equality / ordering on a parsedsemver::Version(which compares build metadata) see it. Revert restores the original lock byte for byte — including when you later lock your own same-version path crate beside the copy: that entry is left alone and the registry entry comes back under its full id, as cargo writes it. Copies and locks vendored before tagged versions are tagged by the next re-run orrepair(cargo_version_tagged; a dry run says "would tag"). For VEX, an untagged detached lock entry counts only beside an untagged (pre-tag) copy, and a copy whoseCargo.tomlis tagged for another uuid than its path is dead wiring. - Why the manifest. Socket's scanners already ingest
Cargo.toml, so the patch uuid in the path is recoverable for SBOM annotation without uploading.cargo/config*(which can hold registry tokens), and manifest[patch]builds on cargo older than 1.56, the floor of config-file[patch](proven by the old-toolchain e2e tests, which build and run the patched copy with no network on the cargo 1.41 and 1.56 docker images — the CIcargo-old-toolchainsleg; without the images a local run falls back to type-checking on rustup toolchains). Two vendored versions of ONE crate need cargo 1.45 or newer. Cargo before 1.45 resolves every source-lessCargo.lockentry for a crate through ONE[patch.crates-io]path — the entry whose KEY sorts last — so with two vendored versions one of the two lock entries is pinned to the other version's copy andcargo build --lockedfails closed withpatch for `<crate>` … did not resolve to any crates. A populated crates.io index in$CARGO_HOMEdoes not help; whether a given pair of patch uuids happens to build there is an accident of how their keys sort. The floor was measured on one two-version fixture in both key orders (cargo check --locked --offline, empty$CARGO_HOME): 1.41.1, 1.42, 1.43 and 1.44 refuse the adversarial order; 1.45, 1.49, 1.53, 1.56 and current stable resolve either order, each lock entry to its own copy. Vendoring a second version of a crate therefore warns (cargo_multi_version_old_cargo) unless the project'srust-versionorrust-toolchain[.toml]promises cargo 1.45+ — socket-patch never runscargo, so those files are the only signal it has. On an old cargo,cargo build --offlinefrom an empty$CARGO_HOMEis enough; without--offlineit loads the crates.io index first and fails when that is unreachable. Current stable needs neither. A SINGLE vendored version still builds on 1.41. Each clause is asserted by the old-toolchain e2e test, in both directions, with the adversarial key order. - Keys. Always the Socket-owned
<name>-socket-<first 8 hex of the uuid>withpackage = "<name>"(the full uuid hex if that key is taken), never the bare crate name: cargo lets a config-file[patch]item — the project's, an ancestor directory's, or$CARGO_HOME's — replace the manifest item with the same key whatever its version, so a crate-named key could be silently shadowed by your own config. Keys any of those config files already use are avoided. Every lookup (re-run, revert, VEX discovery) is key-agnostic: an entry belongs toname@versionwhen its crate (package, else the key) isnameand its path is.socket/vendor/cargo/<uuid>/<name>-<version>. The key is a function of the patch uuid, so the order two versions' keys sort in is arbitrary — which is why cargo below 1.45 cannot be relied on for a multi-version project (above). - Your entries. User-authored
[patch.crates-io]entries are never modified. One — inCargo.tomlor any cargo config file cargo merges (project, ancestors,$CARGO_HOME) — that patches the same crate and is not provably another version (a git/registry patch, or a path whoseCargo.tomlversion is unreadable or equal) refuses the vendor withuser_authored_patch_entry. - Refusals.
cargo_manifest_not_workspace_root: run from a workspace member (cargo ignores[patch]outside the workspace-root manifest) — run from the root.cargo_manifest_patch_source_alias: the manifest also has a[patch."https://github.com/rust-lang/crates.io-index"]table, which cargo lets replace[patch.crates-io]wholesale — move its entries under[patch.crates-io]. Alsocargo_manifest_unreadable,cargo_manifest_unparseable,cargo_manifest_symlink_unsupported. - Formatting. Comments, ordering, CRLF / mixed line endings, a UTF-8
BOM and the trailing-newline state are preserved; a revert with nothing
else changed restores
Cargo.tomlbyte for byte, and keeps your own[patch]/[patch.crates-io]headers (an explicit[patch], or a[patch.crates-io]that another table follows or that carries a comment). - Migration. Projects vendored by an older release carry the entry in
.cargo/config.toml(or.cargo/config). Re-runningvendor,scan/get --mode vendored, orrepairmoves it intoCargo.toml(cargo_wiring_migrated), updates the vendor ledger, and deletes a config file (and.cargo/) the move emptied; a legacy entry that cannot be removed fails the run with nothing changed (cargo_legacy_wiring_kept). A project hit by the old multi-version overwrite (a second vendored version repointed the crate-named config key, leaving the first version's lock entry detached and unwired) is healed the same way (cargo_wiring_restored). The same re-run orrepairalso tags an untagged copy and lock entry (cargo_version_tagged). Every revert removes both spellings.
Both Go modes work through a go.mod replace directive pointing at a committed
directory — .socket/go-patches/<module>@<version>/ in agent mode,
.socket/vendor/golang/<uuid>/<module>@<version>/ in vendored mode — because the module
cache is go.sum-verified, so patching it in place can't build. Go never verifies a
directory replace target against go.sum — that is by design (it's how local module
development works), and it means the committed patched tree itself is the protection:
commit it, and review it like any other vendored code. The wiring survives
go mod tidy, and apply --check gives CI a read-only audit that the committed
redirects still match the manifest.
Hosted mode uses Go's other native replace form — a fork-style
module-to-module directive onto a Socket-published, content-addressed module
(replace <mod> <ver> => patch.socket.dev/gopatch/<uuid> <ver>-socketpatch.<n>)
plus the module's two committed go.sum lines. Because go consults the
checksum database only for modules absent from go.sum, the committed pair
is the complete day-2 state: fresh clones and CI build the patched module with
no machine-local configuration, and a tampered hash still fails closed with
go's checksum SECURITY ERROR. Free tier only; the paid-tier analysis (and
the ephemeral-CI workaround) is in
golang-hosted-no-go.md, the full free-tier
design in golang-hosted.md.
Prebuilt binaries are published for:
| Platform | Architecture |
|---|---|
| macOS | ARM64 (Apple Silicon), x86_64 (Intel) |
| Linux | x86_64, ARM64, 32-bit ARM hard-float (arm-unknown-linux-gnueabihf / -musleabihf), i686 |
| Windows | x86_64, ARM64, i686 |
| Android | ARM64 |