Golang Nugget - Feb 10, 2025

A supply chain attack in the Go ecosystem where a fake BoltDB package introduced a backdoor, allowing remote system control.

  1. PostgreSQL Client-side connection pooling in Golang using pgxpool — When you work with databases, creating a connection can be an expensive operation. That’s when a connection pool can help reuse already established connections. The pgxpool library can help manage PostgreSQL connection pooling in Go.

  2. JSON - The Fine Print: Part 2 - Emitting JSON — The encoding/json package has two main APIs: Marshal and NewEncoder. The Marshal function returns a []byte, while the NewEncoder function writes to an io.Writer. The question is: When should you use one API over the other, and how do you stream JSON over HTTP?

  3. Go Data Structures — This is an old article (2009) from Russ Cox about Go data structures. He talks about the memory layouts of slices, strings, structs, and pointers, and the differences between make and new. Until recently, Russ used to be a core member of the Go development team, and he played a significant role in shaping the language.

  4. proposal: sync/v2: new package — There’s a new proposal about adding a new sync package. The existing sync package was designed before generics were introduced, and therefore the current Map and Pool types use any instead of generics. sync/v2 (if accepted) aims to address this issue by introducing more type-safe Map and Pool types by utilising generic types.

  5. Go's map does not shrink — In Go, maps don’t shrink. So if you build a very large map and then remove everything, the memory footprint stays the same, even in 1.24 with Swiss Table. You can use pointers (or let the language handle it for values larger than 128B), but the underlying structure doesn’t change with deletion.

  6. Go's Concurrency Decoded: Goroutine Scheduling — Go concurrency is based on the GPM model, where G represents a goroutine, M represents a kernel-level thread, and P is the logical processor. This article provides a high-level overview of how Golang manages concurrency. I’d suggest watching "Queues, Fairness, and The Go Scheduler" from GopherCon afterward if you are interested in understanding the scheduler.

Here’s Why Over 4 Million Professionals Read Morning Brew

  • Business news explained in plain English

  • Straight facts, zero fluff, & plenty of puns

  • 100% free

Tool Time

  1. github.com/bytedance/sonic — Sonic is a blazingly fast JSON serializing & deserializing library, accelerated by JIT (just-in-time compiling) and SIMD (single-instruction, multiple-data). It’s developed by Bytedance (TikTok), and more than 50% of the codebase is Assembly. You need Go 1.17+ and ARM64/AMD64 to use it.

  2. github.com/magefile/mage — Mage is a make-like build tool using Go. You write plain-old Go functions, and Mage automatically uses them as Makefile-like runnable targets.

  3. github.com/asdf-vm/asdf — asdf is a CLI tool that can manage multiple language runtime versions on a per-project basis. It is like gvm, nvm, rbenv, & pyenv (and more) all in one! The latest version is now rewritten in Go. What’s cool?

  4. github.com/micro/micro — Micro is an open‐source, API‐first development platform designed to simplify building and managing cloud services. In essence, Micro provides a collection of tools and services that abstract much of the complexity involved in developing distributed systems.

Deep Dive

A supply chain attack happens when hackers mess with software by going after its dependencies. Instead of directly targeting a specific project, they go for the tools and libraries that the project depends on.

In the Go ecosystem, there was a recent attack where someone created a fake package pretending to be the real BoltDB module. They made a malicious package called boltdb-go/bolt (removed by Github now), which looked a lot like the legit boltdb/bolt package. This fake package had a backdoor that let attackers remotely control infected systems using a command-and-control (C2) server. They uploaded it to the Go Module Proxy, which caches and serves Go packages to developers, making module retrieval faster and more reliable.

The attacker took advantage of the proxy’s caching system to keep the malicious package available. After it was cached, they changed the Git tags in the source repo to point to a clean, harmless version. That way, a manual check of the GitHub repo wouldn’t show anything sketchy. But because Go’s caching system locks in the first fetched version, developers who installed the package using the go CLI kept downloading the bad version instead of the fixed one.

To hide the backdoor, the attacker used several sneaky tricks:

  • They spread the malicious code across different files in the boltdb-go/bolt package to avoid detection.

  • The db.go file started the backdoor connection, while cursor.go quietly set up fake constants that turned into an obfuscated IP address.

  • A function called _r() dynamically rebuilt the hacker’s C2 address, making it harder for static analysis tools to spot.

  • The backdoor kicked in when a developer called Open(), creating a persistent TCP connection to 49.12.198[.]231:20022, where it waited to execute commands from the hacker.

  • If the backdoor crashed or stopped, it had a built-in restart routine to keep itself running and maintain access to the system.

How did you like this edition?

Or hit reply and share your thoughts!

Login or Subscribe to participate in polls.

Reply

or to participate.