Typosquatted Go Decimal Library Hid a DNS Command-Execution Backdoor

Summary
A malicious release of the typosquatted Go module github.com/shopsprint/decimal used an init() function to poll DNS TXT records and execute commands. The Go security team has withdrawn the module from its proxy.
Key points
- The module impersonated the legitimate github.com/shopspring/decimal package, differing by one letter; its first seven releases were non-malicious copies.
- Version v1.3.3, published on August 19, 2023, added an init() function that starts a background command-and-control loop when the package is imported.
- The loop queried dnslog-cdn-images[.]freemyip[.]com for DNS TXT records every five minutes and passed returned values to os/exec.Command.
- The backdoor could run commands with the privileges of the importing process, potentially exposing developer, CI, or production credentials and secrets.
- The article reports roughly 33 months between weaponization and disclosure; the GitHub repository and owner account were removed, but the Go module proxy had continued serving the release.
- After coordinated disclosure, the Go security team withdrew the module, and the proxy now returns a 403 SECURITY ERROR for version fetches.
- The article advises checking dependency files and module caches for the typosquat, replacing it with the canonical package, and treating systems that ran v1.3.3 as potentially compromised.
Article Details
- Attack Vectors
- A typosquatted Go module, github.com/shopsprint/decimal, impersonated github.com/shopspring/decimal; importing version v1.3.3 started a background goroutine without opt-in.
- The goroutine polled a threat-actor-controlled DNS TXT record every five minutes and passed each returned value to os/exec.Command for execution.
- The malicious release remained available through the Go Module Proxy after the source repository and owner account were removed; the article reports that the Go security team later withdrew the module.
- Defensive Notes
- Audit go.mod, go.sum, dependency trees, module caches, and vendored code for github.com/shopsprint/decimal; remove it and use the canonical github.com/shopspring/decimal path.
- If v1.3.3 was built or run, treat the host as compromised, rotate credentials accessible to it, and rebuild from a clean toolchain.
- Monitor DNS for dnslog-cdn-images[.]freemyip[.]com and suspicious TXT queries from developer or CI hosts; consider restricting egress to free dynamic DNS providers where there is no business need.
- Review libraries for unexpected DNS resolution and process-execution imports, and scan Go binaries for the combined symbol and hostname indicators described in the article.
Indicators of compromise
| Type | Indicator | Context |
|---|---|---|
| DOMAIN | dnslog-cdn-images[.]freemyip[.]com | Threat-actor-controlled DNS TXT C2 subdomain hardcoded in the malicious module. |
| MD5 | e3c6ce0440d9acd0f1cef1f0da3cdb5d | MD5 hash of the malicious decimal.go file. |
| SHA1 | fd26f4ca4746ee390e22043a5e19ebf2b7fcd1f9 | SHA-1 hash of the malicious decimal.go file. |
| SHA256 | 387d7ea5ca733b1e7219c943f4b461877a8df0148adfef42b1538b6c398fbb41 | SHA-256 hash of the malicious decimal.go file. |
| SHA256 | dd9c0268c8944e6ddf90d4d0c81aa843785b7a9ee965faa635841ed9fc0ba086 | SHA-256 hash of the malicious v1.3.3 module zip. |
MITRE ATT&CK
T1071.004 · DNSThe backdoor polled a threat-actor-controlled DNS TXT record for commands.T1195.002 · Compromise Software Supply ChainThe attacker weaponized a typosquatted Go module release by adding a malicious init() function.T1568 · Dynamic ResolutionThe operator could change the TXT value through the dynamic DNS account, and victims received the updated command on a later poll.T1572 · Protocol TunnelingThe article characterizes the DNS TXT command channel as a covert channel used for C2.T1583.001 · DomainsThe article describes the operator using a subdomain on a free dynamic DNS provider for C2.
Products
GitHubSocket's Threat Research Team identified a malicious Go module published as github.com/shopsprint/decimal, a typosquat of the widely used github.com/shopspring/decimal arbitrary precision arithmetic library.GoSocket's Threat Research Team identified a malicious Go module published as github.com/shopsprint/decimal, a typosquat of the widely used github.com/shopspring/decimal arbitrary precision arithmetic library.Go Module ProxyGitHub source repository deleted, owner account deleted, but the Go Module Proxy cache continues to serve the malicious version on demand to any developer who fetches the module pathpkg.go.devThe GitHub repository and the shopsprint owner account have since been removed, but the malicious release remains permanently served by proxy.golang.org and listed on pkg.go.dev.Socket browser extensionin CI pipelines. Socket Firewall blocks known malicious packages before they are fetched. The Socket browser extension surfaces risk signals while browsing public Go module pages. Socket MCP prevents AI-assistedSocket CLIpull request dependency changes and flags init-time network or process execution before merge. The Socket CLI enforces allow and deny rules in CI pipelines. Socket Firewall blocks known malicious packages beforeSocket Firewallor process execution before merge. The Socket CLI enforces allow and deny rules in CI pipelines. Socket Firewall blocks known malicious packages before they are fetched. The Socket browser extension surfaces riskSocket GitHub AppDNS C2, and typosquatted forks of popular libraries, before they reach developer environments. The Socket GitHub App scans pull request dependency changes and flags init-time network or process execution before merge.Socket MCPare fetched. The Socket browser extension surfaces risk signals while browsing public Go module pages. Socket MCP prevents AI-assisted coding workflows from introducing suspicious dependencies into your codebase.
Industries
Analyticsdecimal library, depended on across the Go ecosystem in financial, billing, cryptocurrency, and analytics codebases because Go's native float64 cannot represent monetary values without rounding error. PublicCryptocurrencyprecision fixed-point decimal library, depended on across the Go ecosystem in financial, billing, cryptocurrency, and analytics codebases because Go's native float64 cannot represent monetary values withoutfinancialis a Go arbitrary precision fixed-point decimal library, depended on across the Go ecosystem in financial, billing, cryptocurrency, and analytics codebases because Go's native float64 cannot represent monetary