BufferZoneCorp: 10 Go modules and 7 knot-* Ruby gems stole CI secrets, planted SSH keys and rewired GitHub Actions
BufferZoneCorp Go modules and knot-* gems stole SSH, cloud, npm, gh and kube credentials and tampered with GitHub Actions. Check go.mod and Gemfile.lock.
- Published
- Updated
- Ecosystem
- GitHub ActionsCI/CDOpen source
- Fixed in
- No clean versions. Remove every github.com/BufferZoneCorp module and every knot-* gem listed here
- Exploitation
- Yes. Live payloads on RubyGems and the Go module proxy from April 2026; source repositories stayed public until at least 2 October 2026
What happened
On 1 May 2026, Socket reported 17 malicious packages from the GitHub account BufferZoneCorp and the RubyGems account knot-theory (Socket). The account was created at 12:06 UTC on 20 April 2026 and published 15 repositories within the next hour (CyberXYZ). GBHackers describes the names as mimicking trusted developer utilities (GBHackers).
Go modules, all under github.com/BufferZoneCorp/ (OSV MAL-2026-3620 to 3629):
| Module | Behaviour |
|---|---|
go-stdlib-ext | Stealer, plants SSH key, disables checksum checks, fake go wrapper |
go-retryablehttp | Routes Actions traffic through the collector; fake go leaks GH_TOKEN |
go-metrics-sdk | Rewrites GOPROXY and strips logrus from go.sum |
go-weather-sdk | Same logrus swap as go-metrics-sdk |
grpc-client | Stealer, post-commit hook, fake kubectl |
net-helper | Stealer, post-commit hook |
config-loader | Stealer, post-commit hook |
go-stdlog | Reconnaissance: tokens, Docker socket, Kubernetes, cloud metadata |
log-core | Stealer in its first commit only, then cleaned |
go-envconfig | Clean at its latest commit |
Behaviour column from CyberXYZ. Socket names v0.4.0 for go-metrics-sdk, go-retryablehttp and go-stdlib-ext, and says go-stdlog had not been published as a module when it wrote; OSV now lists it (OSV MAL-2026-3625).
Ruby gems, with the versions OSV records (OSV MAL-2026-3630 to 3636):
knot-activesupport-logger7.1.6knot-devise-jwt-helper1.0.7knot-rack-session-store1.0.2knot-rails-assets-pipeline6.1.11knot-rspec-formatter-json3.13.5knot-date-utils-rb1.0.0 (decoy, no payload yet)knot-simple-formatter1.0.0 (decoy, no payload yet)
The Go security team blocked the modules after Socket’s report (Socket). On 2 October 2026, CyberXYZ found proxy.golang.org returned no versions and all seven gems were gone from rubygems.org, but all 17 source repositories were still public with payloads intact. Anyone using GOPROXY=direct or GOPRIVATE, or copying the code, could still pull them (CyberXYZ). As of 2 November 2026, the GitHub API returns “not found” for the BufferZoneCorp account.
How the payloads work
Details from Socket and CyberXYZ:
- Go: a package-level
init()starts a goroutine, so importing the package is enough. It runs ingo test, during code generation and in any binary that links it. Strings are XOR-encoded with the keysysutil1. - Ruby:
knot-activesupport-loggerandknot-devise-jwt-helperrun fromext/extconf.rbduringgem install, as part of the native extension build. The other payload gems run when required. - Stolen files:
~/.ssh/id_rsa,~/.ssh/id_ed25519,~/.aws/credentials,~/.npmrc,~/.netrc,~/.config/gh/hosts.yml, plus~/.docker/config.jsonand~/.kube/config(Go) and~/.gem/credentialsand~/.gitconfig(Ruby). Environment variables are filtered by keywords such as token, secret, pass, aws and github; CyberXYZ notes the Go filter matches almost everything. - Exfiltration:
hxxps://webhook[.]site/49c21843-c27c-4a1b-b1f6-037c3998055f, overridable withPKG_ANALYTICS_URL. - SSH backdoor: after a successful upload,
go-stdlib-extappendsssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBp9VZGMxqFpTwKbKJi7dS2mNrX3LqEoHcYsWfAkZvUt deploy@buildserverto~/.ssh/authorized_keys.knot-rack-session-storeappends a different key with the commentdeploy@rack-session. - GitHub Actions tampering:
go-metrics-sdkandgo-weather-sdkwriteGOPROXY=<collector>|direct,GOSUMDB=off,GONOSUMDB=*,GOFLAGS=-mod=modand a newGOMODCACHEto$GITHUB_ENV.go-stdlib-extwritesGONOSUMCHECK=*andGONOSUMDB=*and puts a fakegofirst on$GITHUB_PATH.go-retryablehttpsetsHTTP_PROXYandHTTPS_PROXYto the collector and its fakegosendsGH_TOKENin anX-Tokenheader. - Ruby in Actions: the five payload gems write a
monitor.rbto~/.activesupport/lib,~/.devise-jwt/lib,~/.rack-session/bin,~/.rails-assets/libor~/.rspec-fmt/lib, and appendRUBYOPT=-r<path>/monitor.rbto$GITHUB_ENV, so every later Ruby step loads it. - Git hook beacon:
grpc-client,net-helper,config-loaderandknot-rails-assets-pipelineadd a line containinggc?r=to.git/hooks/post-commit. It sends the repository’soriginURL after every commit, and survives removing the package.
Am I affected?
# Go: module files, vendored code and the module cache
grep -rn 'BufferZoneCorp' go.mod go.sum vendor/modules.txt 2>/dev/null
ls "$(go env GOMODCACHE)/github.com/" 2>/dev/null | grep -i bufferzonecorp
# Ruby: lockfile and installed gems
grep -nE '^ +knot-(activesupport-logger|devise-jwt-helper|rack-session-store|rails-assets-pipeline|rspec-formatter-json|date-utils-rb|simple-formatter) ' Gemfile.lock 2>/dev/null
gem list 2>/dev/null | grep -E '^knot-'
# Planted SSH keys
grep -nE 'deploy@(buildserver|rack-session)' ~/.ssh/authorized_keys 2>/dev/null
# Git hook beacon in every repository under your home directory
grep -l 'gc?r=' $(find ~ -path '*/.git/hooks/post-commit' 2>/dev/null) 2>/dev/null
# Ruby monitor.rb drop directories
ls -la ~/.activesupport/lib ~/.devise-jwt/lib ~/.rack-session/bin ~/.rails-assets/lib ~/.rspec-fmt/lib 2>/dev/nullOn self-hosted runners, check ~/.ssh/authorized_keys for the runner user too. In GitHub Actions logs, search for GONOSUMDB, GONOSUMCHECK, GOSUMDB=off, RUBYOPT=-r, and GOPROXY or HTTPS_PROXY values your workflows did not set (CyberXYZ). In network logs, look for webhook.site/49c21843-c27c-4a1b-b1f6-037c3998055f.
What to do now
- Remove the packages from
go.mod,go.sum,vendor/andGemfile.lock, thengo clean -modcacheand reinstall gems. There is no clean version to move to. - Remove persistence: delete the
deploy@buildserveranddeploy@rack-sessionlines fromauthorized_keys, thegc?r=lines from.git/hooks/post-commitin every clone, and themonitor.rbdirectories above. - Rotate SSH keys, AWS credentials, npm and Docker tokens, RubyGems credentials,
ghtokens and Kubernetes credentials on every machine and self-hosted runner that imported or installed these packages (CyberXYZ). Rotate any GitHub token that was inGH_TOKENduring a CI run withgo-retryablehttp. - Rebuild self-hosted runners. An attacker-held key in
authorized_keysmeans anyone with the private key could log in after the job ended. - Pin Go environment in CI. Set
GOPROXY,GOSUMDBandGONOSUMDBexplicitly in each job, and fail a job if a step changes them. Treat any dependency that writes to$GITHUB_ENVor$GITHUB_PATHas hostile.
Why this matters
$GITHUB_ENV and $GITHUB_PATH carry changes from one step into every later step in the job. A dependency that runs once during go test or bundle install can switch off checksum verification, put a fake go first on the path, or preload Ruby code for the rest of the workflow. Your workflow file does not change, so a diff review will not catch it.
Sources
- Socket: Malicious Ruby gems and Go modules steal secrets and poison CI
- CyberXYZ: BufferZoneCorp Go and RubyGems CI stealer (2 October 2026)
- GBHackers: Ruby gems and Go modules used in campaign targeting GitHub
- OSV MAL-2026-3622: github.com/BufferZoneCorp/go-metrics-sdk
- OSV MAL-2026-3630: knot-activesupport-logger