DEV Community

Cover image for Go Undercover: Code Obfuscation with Garble
Athreya aka Maneshwar
Athreya aka Maneshwar

Posted on

Go Undercover: Code Obfuscation with Garble

Hi there! I'm Maneshwar. Right now, I’m building LiveAPI, a first-of-its-kind tool that helps you automatically index API endpoints across all your repositories. LiveAPI makes it easier to discover, understand, and interact with APIs in large infrastructures.


Garble, by burrowers, is an open-source tool that wraps the Go compiler to produce obfuscated Go binaries. Its key features include:

  • Renaming identifiers, package paths, and removing metadata ⚙️
  • Optional string literal obfuscation with -literals
  • Support for tiny binaries via -tiny (removes filenames, line numbers, panic info)
  • Deterministic builds with reproducible obfuscation (via -seed)
  • Stack trace reverse mapping using garble reverse when seeds are known (go.libhunt.com, github.com)

Installation

go install mvdan.cc/garble@latest
# or: go install github.com/burrowers/garble@latest
Enter fullscreen mode Exit fullscreen mode

Obfuscating a Simple Program

Consider this manager app:

// main.go
package main

import "fmt"

func main() {
    secret := "Hello, Obfuscation!"
    fmt.Println(process(secret))
}

func process(s string) string {
    return s + " 🚀"
}
Enter fullscreen mode Exit fullscreen mode

Build normally:

go build -o normal_app main.go
strings normal_app | grep process
# >> process
Enter fullscreen mode Exit fullscreen mode

Now obfuscate with Garble:

garble build -o garbled_app main.go
strings garbled_app | grep process
# >> no "process" found
Enter fullscreen mode Exit fullscreen mode

Adding Literal Obfuscation

Encrypt every string literal:

garble build -literals -o garbled_lit main.go
strings garbled_lit | grep Hello
# >> (nothing – strings scrambled at runtime)
Enter fullscreen mode Exit fullscreen mode

Under the hood, Garble’s compiler rewrite wraps string literals in a runtime decryptor (cloud.google.com, go.libhunt.com).

Deterministic Builds & Reverse

To maintain reproducible builds and enable stacktrace deobfuscation:

garble build -seed=42 -o deterministic_app main.go
Enter fullscreen mode Exit fullscreen mode

If your app panics, you can reverse it to map obfuscated symbols back with:

garble reverse -seed=42 deterministic_app
Enter fullscreen mode Exit fullscreen mode

⚠ Limitations

  • Exported symbols (used in reflection/interfaces) are preserved (go.libhunt.com)
  • Plugins unsupported; control-flow obfuscation experimental via GARBLE_EXPERIMENTAL_CONTROLFLOW=1 (github.com)
  • Source paths and metadata are cleared, but the Go runtime still leaves some traces (go.libhunt.com)

Why Use Garble?

  • Raises the bar for reverse-engineers by removing public-type info, strings, file names
  • Maintains full Go compatibility with module support, caches, stack-unwindable builds (github.com, go.libhunt.com)
  • Fast—about 2× slower than go build, thanks to caching (github.com)

Next Steps

  1. Integrate in CI pipelines (build both plain and garbled variants)
  2. Use -tiny mode for smaller executables
  3. Combine with linker flags (-ldflags="-s -w") and -trimpath for tighter security (go.libhunt.com, xnacly.me)
  4. Consider additional control-flow obfuscation if you’re in adversary-resistant scenarios

Final Thoughts

Garble significantly complicates metadata and symbol recovery, but obfuscation is not bulletproof. Tools like GoStringUngarbler can reverse literal obfuscation (github.com, cloud.google.com), and determined attackers with runtime analysis can still break logic. Use Garble as part of a broader protection strategy, not your only defense.


LiveAPI helps you get all your backend APIs documented in a few minutes.

With LiveAPI, you can generate interactive API docs that allow users to search and execute endpoints directly from the browser.

LiveAPI Demo

If you're tired of updating Swagger manually or syncing Postman collections, give it a shot.

Top comments (0)