DEV Community

Cover image for Building CyberRef: A Single-Binary Offline Reference for Cybersecurity Practitioners
Elijah Abolaji M.N.C.S
Elijah Abolaji M.N.C.S

Posted on

Building CyberRef: A Single-Binary Offline Reference for Cybersecurity Practitioners

I built CyberRef to solve a problem I kept seeing in labs and on engagements: nobody remembers the exact syntax of a command under pressure.

You know the command exists. You know roughly what it does. But it's 2 AM during an incident, or you're mid-engagement with a client watching, and the exact flags slip away. So you open twelve tabs of cheatsheets, dig through your notes app, ask Slack — and twenty minutes disappear on something you knew cold last week.

CyberRef is my attempt to fix that. This article is a walkthrough of what it does, the design decisions behind it, and what I learned building it.

What It Is

A single binary you download and run. It opens a local web UI at http://localhost:8787 with a searchable command reference and a set of guided lab scenarios.

No install. No server. No internet required. Everything is embedded — the UI, the datasets, the assets.

Written in Go for the backend, Alpine.js + vanilla CSS for the frontend, all served from one binary via embed.FS.

Why Offline-First

Most cheat-sheet tools are websites. That's fine until you're in an air-gapped lab, an isolated client environment, or a VM with no network egress. In those settings, an online tool is dead on arrival.

Offline-first isn't a limitation — it's a constraint that shaped every decision:

Data is embedded at build time. YAML files are compiled into the binary via go:embed. No external file reads at runtime.

No network calls at startup. The binary doesn't phone home, doesn't check for updates, doesn't do telemetry.

Stateless by default. Nothing is written to disk unless the user explicitly exports something.

Single binary distribution. One .exe on Windows. Copy it to a USB stick, run it on any machine.
Enter fullscreen mode Exit fullscreen mode

This means the tool works in the environments where cyber work actually happens — not just where developers are comfortable.

Why Not React

The obvious frontend choice would have been React with Vite and a build pipeline. I went with vanilla HTML/CSS/JS + Alpine.js instead. Here's why:

go build must be the only build command. A React pipeline adds Node, npm, a bundler, and version drift. Two toolchains for a lookup tool is overkill.

Alpine.js gives 80% of React's ergonomics in one <script> tag. Declarative bindings, reactivity, x-for, x-if — everything a searchable list needs.

No dist/ folder to embed. The HTML, CSS, and JS files are the final artifacts. go:embed picks them up directly.

Zero framework churn. Alpine v3 will keep working in five years. React 18 will be replaced by React 21 by then.
Enter fullscreen mode Exit fullscreen mode

For a searchable, filterable, well-formatted reference tool, this is the right tradeoff. React would have been solving a problem I didn't have.
The Placeholder Substitution Feature

This is the feature that turned CyberRef from a nice-to-have into a tool people actually use.

Commands like nmap -A -p- {TARGET} aren't directly paste-ready. {TARGET} is a placeholder that must be replaced. CyberRef scans each command for {TOKEN} patterns and renders an inline input for each one:
A few things make this work well:

Values persist across sessions. Type your lab IP once, and every command using {TARGET} reuses it.

YAML defaults pre-fill inputs. When a scenario specifies placeholders: { TARGET: "10.10.10.5" }, the input starts populated.

Copy gives you the substituted version. Not the template. The ready-to-paste command.

Values are shared across commands and scenarios. Configure once for an engagement, use everywhere.
Enter fullscreen mode Exit fullscreen mode

Twenty lines of Alpine state plus a localStorage wrapper. Small feature, huge UX impact.
The Scenario Layer

A command reference is table stakes. The real problem in cyber training isn't "what's the command" — it's "what's the sequence, and why."

In v0.3 I added a scenario layer. Each scenario is a guided workflow with:

Narrative overview — what the technique is, why it matters

Prerequisites — what you need before starting

Steps — ordered commands with rationale, expected output, and notes

Defense — hardening, detection, and response guidance

References — MITRE ATT&CK, OWASP, vendor docs
Enter fullscreen mode Exit fullscreen mode

The scenarios are mapped to the Cyber Kill Chain, MITRE ATT&CK, and the CIA triad. This is important — it turns a command list into a curriculum.

Blue-Team Content

In v0.4 I added the first blue-team scenario — Log Analysis & Detection Engineering — plus purple-team notes on every attack scenario.

Purple team notes are the connective tissue. They answer the question: "How do I run this attack and watch it get detected at the same time?"

For example, on the Kerberoasting scenario:

Detection is easiest when 4769 events are forwarded to a SIEM. Filter for RC4 (0x17) ticket encryptions — modern AD should only see AES in normal operations. Any RC4 TGS is worth investigating.
Enter fullscreen mode Exit fullscreen mode

This is different from the Defense panel. The Defense panel lists what to monitor. The Purple Team Notes explain how to actually run the exercise.

Blue-team content also includes ready-to-run SIEM queries for Splunk, Elastic, and Wazuh. Copy, paste, run. No translation needed.

What I Learned

  1. Constraints make the product better. Offline-first, single-binary, no-build-step — these weren't compromises. They were features. Every one of them made the tool faster, simpler, and more usable in the environments where it matters.

  2. Ship small, ship often. The progression was:

  • v0.2 — command reference with placeholders
  • v0.3 — scenarios + export
  • v0.3.1 — favorites & recents
  • v0.3.2 — filters & command palette
  • v0.4 — attack lifecycle depth + blue-team content

Each release solved one thing well. Nobody had to wait six months for a "big update."

  1. Users tell you what to build next. The favorites feature came from watching how I used the tool myself. The command palette came from friends who said "We want to jump to a command without leaving the keyboard." Real friction beats planned roadmaps.

  2. Some things don't need to be fancy. embed.FS + net/http + Alpine.js. No ORM, no state management library, no container. Just three external Go dependencies and one vendored JS file. The simplicity is the point.

What's Next

Planned for v0.5:

  • Windows / Active Directory — native commands and AD-focused scenarios
  • CLI companion — cyberref search "kerb" from the terminal, reusing the same data
  • PowerShell export — for scenarios, alongside the current bash export
  • Light theme — for bright environments
  • Signed binaries — to remove the Windows SmartScreen warning
    

    **
    Longer term:**

  • Community scenario contribution format
    
  • Documentation site
    
  • Multi-platform binaries (macOS, Linux)
    

Try It

Download: https://github.com/toyosee/cyberref-releases/releases

Run: Double-click cyberref.exe. Browser opens. That's the whole setup.

Note on Windows SmartScreen: You'll likely see a "Windows protected your PC" warning. This is normal for unsigned binaries. Click More info → Run anyway. Code signing is on the roadmap.
Feedback Welcome

If you're a practitioner — red, blue, or somewhere in between — I'd love to hear:

  • What commands or scenarios are missing that you'd use?
  • What friction points does the tool not solve yet?
  • What would make it part of your daily workflow?

Open an issue on the releases repo, or find me on LinkedIn. - https://linkedin.com/in/elijahabolaji

CyberRef is written in Go, uses Alpine.js for the frontend, and ships as a single binary for Windows with macOS and Linux builds planned. Source is maintained privately; binaries are released publicly.

Top comments (0)