routeros-extract is a native Go command-line tool for inspecting RouterOS
.npk packages and the payloads nested inside them. It has no non-Go external
dependencies.
Available for macOS, Linux, Windows, FreeBSD, NetBSD, and OpenBSD on AMD64 (Intel/AMD) and ARM64 (including Apple silicon). These commands detect your computer's platform and download the latest release.
macOS, Linux, and BSD — downloads directly to /usr/local/bin and makes
the binary executable:
sudo curl -fL --create-dirs "https://github.com/naterator/routeros-extract/releases/latest/download/routeros-extract-$(uname -sm | tr 'A-Z ' 'a-z-' | sed 's/x86_64/amd64/;s/aarch64/arm64/')" -o /usr/local/bin/routeros-extract && sudo chmod 755 /usr/local/bin/routeros-extractWindows (64-bit PowerShell) — downloads to the current directory:
curl.exe -fL "https://github.com/naterator/routeros-extract/releases/latest/download/routeros-extract-windows-$($env:PROCESSOR_ARCHITECTURE.ToLower()).exe" -o routeros-extract.exeThen run routeros-extract --help or
routeros-extract extract /path/to/package.npk -o extracted.
On Windows, use .\routeros-extract.exe as the command.
The extract command also accepts all_packages*.zip archives.
You can also download a release manually
or build from source if no release is available yet.
Each binary has a matching .sha256 file. README.md, LICENSE, and AUTHORS
are separate release assets. All licenses are also included in the binary;
run routeros-extract license to read them.
Run routeros-extract update to install a newer stable release, or
routeros-extract update --check to check without installing. The updater
verifies SHA-256, checks the binary's platform, and replaces the executable
you ran. For a root-owned Unix installation, use sudo routeros-extract update.
Windows may keep the previous executable as .old until a later update;
you can delete that backup after the command exits.
Go 1.25 or newer is required. Clone
github.com/naterator/routeros-extract
and build from the checkout; the project uses local copies of two Go modules
under third_party/.
Run make or make help to list every target and build option:
make
make build
make test
make vetThe binary is written to bin/routeros-extract. Set VERSION when producing
a release build, for example make build VERSION=0.1.0. Go's normal
GOOS/GOARCH variables can be used for cross-compilation; the analyzer does
not depend on the host operating system or CPU architecture.
For a Windows binary, set the output filename explicitly:
GOOS=windows GOARCH=amd64 make build BINARY=bin/routeros-extract.exeThe build workflow runs tests and vet for all
three modules on Linux, macOS, and Windows on pushes, pull requests, and
published releases. Releases also build and upload the binaries listed above.
Use semantic version tags such as
v0.1.0; the release tag supplies --version and the updater's version
comparison. A local dev build can also update to the latest stable release.
Binaries are uploaded directly, with an .exe extension for Windows;
documentation and license files are uploaded separately.
The vulnerability workflow runs
govulncheck for the project and both bundled Go modules on pull requests.
It retains the source workflow's advisory behavior: findings appear as
annotations and in the workflow summary, rather than failing the job solely
because vulnerabilities were found.
Run routeros-extract --help or a command's --help for all flags.
inspect NPK...reads the NPK header and lists every section without creating an extraction.--jsonproduces machine-readable metadata.extract INPUT... -o DIRECTORYaccepts NPKs andall_packages*.ziparchives, creates one new directory per input, and runs the complete extraction: raw sections, file-container records, SquashFS, kernel streams, RouterBOOT FWFs, console definitions, WebFig data, ELF/module inventories, manifests, andintegrity.json.kernel IMAGE -o DIRECTORYscans a boot object for valid XZ or gzip streams, recursively follows decoded ELF and CPIO payloads, and writes stream hashes, decoded files, and CPIO metadata.firmware FWF -o DIRECTORYextracts one RouterBOOT.fwfenvelope. Modern NRV2B images have CRC32 and output-length checks; recognized legacy images retain their uncompressed payload and explicitly report that format.squashfs IMAGE -o DIRECTORYexports a SquashFS image, a metadata-preservingrootfs.tar.gz, a portable browse tree, and manifests.console INPUT... --parser ELF -o DIRECTORYdecodes console.memfiles or searches an extracted rootfs. It writes command paths, parameter and help records, strings, and an integrity ledger. The parser must match the firmware. Layout detection supports all 7.24.2 architectures and tested earlier RouterOS 7 releases without a per-release allowlist.analyze DIRECTORY...adds nested payload reports to an extraction that was created with--no-derived. Thederived/directory must not already exist.compare BEFORE AFTER -o DIRECTORYcompares original archive paths, regular-file hashes, node types, symlink targets, modes, file containers, and RouterBOOT families. It writes JSON, CSV, and Markdown reports.verify DIRECTORY [--source INPUT]checks the integrity ledger, output hashes, and retained sections. ZIP collections verify every contained NPK.--sourcealso checks the original NPK or ZIP hash.update [--check]checks GitHub for a newer stable release and installs it, unless--checkis given. It never downgrades a versioned release.licenseprints the project license and all third-party notices.
The Cobra root command also supplies --version and shell completion. For
example:
routeros-extract inspect --json routeros-7.24.2-arm64.npk
routeros-extract extract routeros-7.24.2-arm64.npk -o extracted
routeros-extract extract all_packages-arm64-7.24.2.zip -o extracted
routeros-extract verify extracted/routeros-7.24.2-arm64 \
--source routeros-7.24.2-arm64.npk
routeros-extract console rootfs --parser rootfs/nova/bin/parser \
-o console-output
routeros-extract completion zsh > _routeros-extractOutput directories must be new. This avoids silently mixing artifacts from
different package versions. --max-bytes defaults to 512 MiB per input,
filesystem, file container, or recursive kernel scan. ZIP members share an
input-expansion limit, then each contained NPK is extracted independently.
It is not a total output-size or memory quota. --no-symlinks preserves link
metadata without creating host links, and is the default on Windows.
Use extract --no-derived to stop after filesystem extraction, or
extract --sections-only to preserve just the NPK sections and metadata.
NPK framing and file-container records are architecture agnostic. The parser preserves unknown and repeated section IDs by index, so an add-on package can be inspected even when it has no main-system SquashFS, boot kernel, or RouterBOOT update. A package without one of those layers is reported with the layers it contains rather than being treated as a malformed main package.
The current validation corpus includes package labels for arm, arm64,
x86, mipsbe, mmips, smips, ppc, and tile. The package label does
not imply that every file has the same CPU type: RouterOS packages can contain
32-bit userland, 64-bit modules, boot helpers, and raw device firmware
together. ELF headers and the extracted manifests are the authority for an
individual file's architecture.
All 99 NPKs in the supplied test set passed, including 90 add-ons delivered in eight ZIP archives. See docs/VALIDATION.md for versions, per-architecture counts, reference comparisons, and build checks.
The package reader also preserves PPC file-container variants. If the same
original path occurs with different four-byte variant tags, later records are
stored with a deterministic .__variant_<tag> suffix while archive_path and
variant_tag_hex retain the original relationship.
Supported console images are also decoded automatically into
derived/console/ when their matching parser is present. Unsupported layouts
and add-ons without a parser keep their source images and receive a note.
For add-ons, pass --console-parser FILE to extract or analyze, or use
console --parser FILE, with the corresponding main package executable.
See the console format documentation
for tested layouts, output files, and the recovered layout.
For an all_packages.zip, extract preserves each NPK under npk/ and
extracts it under packages/<package-name>/. zip-metadata.json lists every
archive member, including ignored non-NPK files. Each add-on is processed
independently, including feature packages and hardware drivers.
The tool is intended for firmware research and package comparison. It writes raw input sections beside decoded copies, records Linux metadata in JSON, and keeps SHA-256 hashes so an extraction can be checked later. It never executes an extracted install script, ELF, kernel, or firmware image. RouterOS package and firmware signatures are retained as bytes; they are not authenticated.
Archive paths are validated before writing. Absolute paths, parent traversal,
backslashes, NUL bytes, duplicate paths, and non-directory ancestors are
rejected. Colliding Linux names receive a stable .__case_<hash> browse
suffix; names unsupported by common host filesystems receive deterministic
aliases. Original names and Linux metadata remain in the manifests and
retained raw containers; SquashFS also produces a tar archive.
Special device nodes are metadata-only in the browse tree.
The original SquashFS remains authoritative for inode identity, extended
attributes, and other metadata not represented by the browse copy or tar.
The package's install and uninstall script sections are saved as raw bytes and
shown as text where appropriate. They are never run. The same rule applies to
ELF files, kernels, CPIO init, FWF output, and WebFig definitions.
The detailed byte layout, boot-object formats, and known architecture matrix are in docs/FORMAT.md; console memory images are documented in docs/CONSOLE-MEM.md. The bundled XZ changes and attribution are in third_party/xz/LOCAL_CHANGES.md, and dependency notices are in LICENSE.
Use a directory containing NPK samples, or a single NPK:
go run ./tools/corpus -corpus /path/to/samples -output /path/to/new-results
ROUTEROS_TEST_CORPUS=/path/to/samples go test ./internal/extract -run TestCorpus -vThe corpus helper writes a JSON report and continues after individual failures.
Set ROUTEROS_PYTHON_REFERENCE to the earlier Python extraction parent to also
compare those manifests and derived payload hashes. Normal make test uses
small synthetic fixtures and requires no RouterOS downloads or external tools.
The project's original code is licensed under BSD-3-Clause. Bundled and linked components retain their MIT, BSD, 0BSD, or Apache-2.0 licenses. All license texts, attribution, and third-party notices are consolidated in LICENSE, which is also included in every binary. Include that file when redistributing source or binaries.
After editing LICENSE, run go generate ./internal/license to refresh
the copy compiled into the CLI.
The license covers the tool's code, not RouterOS firmware or extracted payloads. The NRV2B and LZO implementations use permissively licensed sources; their provenance is recorded in the third-party notices.