shopsprint/decimal Go Module DNS Backdoor Typosquat
The Go module github.com/shopsprint/decimal typosquatted github.com/shopspring/decimal and used an init-time DNS TXT command loop in v1.3.3.
- Date:
- Severity:
- high
- Sources:
- 1
Executive Summary
Socket reported that github.com/shopsprint/decimal is a long-running one-character typosquat of the legitimate github.com/shopspring/decimal Go module. The malicious v1.3.3 release added an init() goroutine that queried DNS TXT records and executed returned commands, giving attackers a stealthy command channel inside any application importing the typoed module Socket.
The source repository and owner were removed by disclosure time, but Go’s public module proxy continued to serve the cached module artifact. Defenders must search source, go.mod, go.sum, vendored code, build caches, and released binaries for the typoed module path, then replace it with the canonical github.com/shopspring/decimal path and rotate secrets on systems that built or ran affected code Socket.
Key Facts
threat_type: "Go module typosquat with DNS TXT backdoor"
ecosystem: "Go modules"
registry: "proxy.golang.org and pkg.go.dev"
affected_packages:
- "github.com/shopsprint/decimal"
malicious_versions:
- "v1.3.3"
known_good_versions:
- "github.com/shopspring/decimal legitimate module path"
fixed_or_safe_versions:
- "replace typoed path with github.com/shopspring/decimal and rebuild from clean caches"
execution_trigger: "Go package init() when imported by a program"
primary_impact: "remote command execution through DNS TXT command channel"
campaign_context: "Long-lived typosquat disclosed during the May 2026 supply-chain incident wave."
confidence: "high"
canonical_source: "https://socket.dev/blog/popular-go-decimal-library-typosquat-dns-backdoor"
last_verified: "2026-05-24"
Source Confidence & Evidence Mapping
- confirmed: Socket identifies
github.com/shopsprint/decimal@v1.3.3as the malicious Go module version and contrasts it with the legitimategithub.com/shopspring/decimalpackage Socket. - confirmed: The malicious diff added network, command-execution, and timing imports plus an
init()goroutine indecimal.goSocket. - confirmed: The command channel uses DNS TXT queries to
dnslog-cdn-images[.]freemyip[.]comand executes returned content Socket. - confirmed: Socket states the Go Module Proxy still served the cached malicious
v1.3.3artifact after the GitHub source disappeared Socket. - unclear: Public reporting does not prove the number of downstream builds or binaries that imported the typoed path.
Attack Execution Flow
sequenceDiagram
autonumber
actor Attacker
participant Proxy as Go Module Proxy
participant Build as Go Build / Test
participant App as Compiled Application
participant DNS as DNS TXT C2
Attacker->>Proxy: Publish typoed module github.com/shopsprint/decimal v1.3.3
Proxy->>Build: Developer resolves typoed module path
Build->>App: Application imports decimal package
App->>App: init() goroutine starts automatically
App->>DNS: Query TXT command record
DNS->>App: Return command content
Timeline
- 2017-11-08 Socket reports the typoed module existed as a long-running package name before weaponization Socket.
- 2023-08-19T09:27:21Z Socket reports
github.com/shopsprint/decimal@v1.3.3as the malicious version publication time Socket. - 2026-05-19 Socket publishes public analysis of the typosquat and DNS backdoor Socket.
- 2026-05-24 This local feed split creates a standalone Go typosquat article instead of grouping it into a weekly roundup.
What Happened
The attacker relied on one-character package-name confusion: shopsprint instead of shopspring. That typo is easy to miss in go.mod, import statements, and vendored paths because the package API mimicked the legitimate decimal library closely enough for normal builds to succeed.
The malicious v1.3.3 release added a Go init() function. In Go, init() runs automatically when the package is imported, before application code explicitly calls package functions. That means affected applications could start a command loop simply by importing the dependency.
Technical Analysis
Initial Access
No upstream compromise of the legitimate shopspring/decimal project is reported. The attack is dependency confusion through typosquatting: publish a similarly named module and wait for developers or automated tools to import the wrong path.
Package or Artifact Tampering
Socket’s diff analysis shows a small malicious change in decimal.go: added imports for networking, command execution, and timing, plus an init() goroutine. This is effective because the rest of the package remains close to the legitimate API surface Socket.
Execution Trigger
The trigger is Go package initialization. Any application, test, or tool that imports github.com/shopsprint/decimal can execute the malicious init() path.
Payload Behavior
The payload performs periodic DNS TXT lookups and executes command content returned through DNS. This design can bypass simple HTTP egress controls if DNS logging and TXT-query policy are weak.
Exfiltration / C2
The primary C2 channel is DNS TXT for dnslog-cdn-images[.]freemyip[.]com. The use of a dynamic DNS domain and TXT records makes DNS query-type telemetry important for hunting Socket.
Propagation
No autonomous propagation is reported. Persistence comes from build reproducibility infrastructure: Go Module Proxy can continue serving cached module zips even after the source repository is removed.
Obfuscation or Evasion
The main evasion is name similarity plus minimal diff size. Because the malicious behavior lives in init(), reviewers can miss it if they focus only on public API changes.
MITRE ATT&CK Mapping
| Tactic | Technique ID | Technique Name | Observed Behavior |
|---|---|---|---|
| Initial Access | T1195.002 | Compromise Software Supply Chain | Typoed Go module path delivered malicious dependency. |
| Execution | T1059 | Command and Scripting Interpreter | DNS-returned commands were executed by the payload. |
| Command and Control | T1071.004 | Application Layer Protocol: DNS | Payload used DNS TXT records as a command channel. |
| Defense Evasion | T1036 | Masquerading | Module name impersonated the legitimate shopspring/decimal project. |
Affected Assets and Blast Radius
affected_assets:
ecosystems:
- "Go modules"
packages:
- "github.com/shopsprint/decimal"
versions:
- "v1.3.3"
repositories:
- "github.com/shopsprint/decimal"
ci_cd_systems:
- "Go build/test pipelines"
container_images:
- "images built from applications importing the typoed path"
developer_tools:
- "go command"
- "Go module proxy/cache"
credentials_at_risk:
- "secrets available to affected build hosts or applications, depending on executed commands"
not_currently_known_to_affect:
- "github.com/shopspring/decimal when spelled correctly."
Indicators of Compromise
package_versions:
- "github.com/shopsprint/decimal v1.3.3"
files:
- "go.mod"
- "go.sum"
- "decimal.go"
hashes:
- "f31bdd069fe7966ae11be1f78ee5dd44445938856dd1df12379e0e84a6851f5c"
domains:
- "dnslog-cdn-images[.]freemyip[.]com"
- "freemyip[.]com"
urls: []
ips: []
process_patterns:
- "Go application importing github.com/shopsprint/decimal"
network_patterns:
- "TXT query to dnslog-cdn-images[.]freemyip[.]com every five minutes"
provenance_signals:
- "module path differs from github.com/shopspring/decimal by one character"
- "Go Module Proxy serves cached module after source repository removal"
Detection and Hunting
lockfiles:
- "Search go.mod and go.sum for github.com/shopsprint/decimal."
- "Search SBOMs and dependency inventories for shopsprint."
filesystem:
- "Search vendored source and GOMODCACHE for github.com/shopsprint/decimal and dnslog-cdn-images."
process:
- "Review applications importing the typoed module for unexpected child process execution."
network:
- "Search DNS logs for TXT queries to dnslog-cdn-images[.]freemyip[.]com and other freemyip[.]com subdomains."
github_audit:
- "Review commits that introduced shopsprint imports."
ci_cd:
- "Review Go builds that downloaded github.com/shopsprint/decimal@v1.3.3."
registry:
- "Block github.com/shopsprint/decimal and alert on future imports."
sigma_candidates:
- "DNS TXT Query To freemyip Dynamic DNS From Build Or Application Host"
yara_candidates:
- "Go source containing package decimal with net.LookupTXT and os/exec.Command in init()"
Remediation Workflow
- Immediate: Replace
github.com/shopsprint/decimalwithgithub.com/shopspring/decimal, block the DNS C2 domain, and identify binaries built with the typoed module. - Short-term: Purge Go module caches, rebuild affected applications from clean dependencies, redeploy containers, and rotate secrets available to build and runtime systems that executed the affected code.
- Long-term: Enforce dependency spelling allowlists for critical packages, monitor new imports with typosquat detection, and log DNS query types from developer and production networks.
Defensive Lessons
- prevent: Critical Go dependencies should be allowlisted by exact module path.
- detect: DNS TXT telemetry is required to catch command channels that avoid HTTP.
- respond: Removing source from GitHub does not remove cached malicious module versions from Go proxy infrastructure.
Open Questions
- How many real-world builds imported
github.com/shopsprint/decimal@v1.3.3? - What commands were served through the DNS TXT channel during active operation?
- Which downstream binaries still contain the malicious module?
Sources
- Socket: Popular Go Decimal Library Targeted by Long-Running Typosquat with DNS Backdoor - Role: PRIMARY_RESEARCH - Impact: Documents the typoed module path, malicious version, artifact diff, DNS TXT C2, proxy persistence, hash, and remediation.
Machine-Readable Event Profile
{
"schema_version": "2.0",
"event_id": "shopsprint-decimal-go-typosquat-2026-05-19",
"event_name": "shopsprint/decimal Go Module DNS Backdoor Typosquat",
"publication_state": "publish_ready",
"confidence": "high",
"attack_types": ["typosquatting", "Go init malware", "DNS command and control", "remote command execution"],
"sources": {
"direct": [],
"primary_research": ["https://socket.dev/blog/popular-go-decimal-library-typosquat-dns-backdoor"],
"correlated": []
},
"affected_assets": {
"ecosystems": ["Go modules"],
"packages": ["github.com/shopsprint/decimal"],
"versions": ["v1.3.3"],
"repositories": ["github.com/shopsprint/decimal"],
"ci_cd_systems": ["Go build/test pipelines"],
"container_images": ["images built from applications importing the typoed path"],
"developer_tools": ["go command", "Go module proxy/cache"],
"credentials_at_risk": ["secrets available to affected build hosts or applications"]
},
"timeline": {
"first_seen": "2017-11-08",
"malicious_publish_time": "2023-08-19T09:27:21Z",
"discovery_time": "2026-05-19",
"removal_time": "mixed",
"disclosure_time": "2026-05-19",
"patch_or_fix_time": "unknown"
},
"artifact_analysis": {
"malicious_artifacts": ["decimal.go init() DNS TXT loop"],
"execution_trigger": "Go package init()",
"payload_behavior": ["DNS TXT command polling", "command execution"]
},
"iocs": {
"package_versions": ["github.com/shopsprint/decimal@v1.3.3"],
"files": ["go.mod", "go.sum", "decimal.go"],
"hashes": ["f31bdd069fe7966ae11be1f78ee5dd44445938856dd1df12379e0e84a6851f5c"],
"domains": ["dnslog-cdn-images.freemyip.com", "freemyip.com"],
"urls": [],
"ips": [],
"process_patterns": ["Go application importing github.com/shopsprint/decimal"],
"network_patterns": ["TXT dnslog-cdn-images.freemyip.com"]
},
"detection": {
"lockfile_hunts": ["go.mod and go.sum github.com/shopsprint/decimal"],
"filesystem_hunts": ["GOMODCACHE and vendor shopsprint decimal"],
"process_hunts": ["unexpected child processes from affected Go applications"],
"network_hunts": ["TXT queries to dnslog-cdn-images.freemyip.com"],
"ci_cd_hunts": ["Go builds downloading shopsprint/decimal v1.3.3"],
"registry_hunts": ["block shopsprint/decimal"]
},
"open_questions": ["victim count", "commands served over DNS", "downstream binary exposure"],
"defender_takeaways": {
"detection": "Search exact module paths and DNS TXT telemetry.",
"hunting": "Find typoed module references in source, caches, SBOMs, and built binaries.",
"remediation": "Replace with shopspring/decimal, rebuild, purge caches, and rotate exposed secrets.",
"prevention": "Allowlist critical Go module paths and monitor for typosquats."
}
}