Wheelhouse docs

Reporting a vulnerability#

If you have found a security flaw in the agent, the web UI, the installer, the packaging or the release pipeline, this page is where it goes and what happens next. Two things first: the reporting address has not been published yet, and a security report does not go to support.

RouteStatus
EmailNone published. When there is one it will appear here and on the product site's security page
PGP keyThere is none. Until there is, keep anything that would be damaging in transit out of the report: say that you have it, and a way to send it will be arranged
Public issue trackerThere is none, and the source forge is private. Do not look for one

If you have had no acknowledgement in three business days, assume the mail went astray and send it again.

What to include#

You do not need all of this. Send what you have.

  • The version. dpkg-query -W -f='${Version}\n' wheelhouse-agent on the router, or the version on the console banner. If it matters which base you are on, cat /etc/os-release.
  • Which component: the agent, the web UI, the installer, the packaging, the ISO build, or the licence server.
  • What an attacker can do, and what they need first — network position, credentials, a role, physical access.
  • Steps to reproduce. A curl command against wheelhouse-agent --demo is ideal for anything in the authentication, authorization, session or licence layers, because those answer before the router is consulted. In demo mode the agent starts without router credentials and every router read fails, so a report about a router-touching route needs a real router behind it.
  • Whether you have told anyone else, and whether you have a disclosure date in mind.

What Wheelhouse commits to#

UndertakingWithin
Acknowledge your report3 business days
Say whether we agree it is a vulnerability, and its severity10 business days
Ship a fix, or give you a dated plan90 days from the acknowledgement
Credit you in the changelog, if you want itwith the fix

If something is being actively exploited, say so in the subject line.

Which versions get fixes#

VersionSupported
The most recent releaseYes
Anything olderNo

There is no long-term-support line and no backporting. Fixes go into the next release, so how quickly you plan to upgrade is part of your own risk position.

A fix reaches you as a new release on the download host, with the security-relevant changes in that version's Security section of the changelog. There is no advisory feed. The router reads the release channel on a timer and the System page says when a newer version exists, but that notice says only that a release is newer — nothing marks one as carrying a security fix, and nothing pushes an advisory to you. Reading the changelog section published beside a release is still how you learn what was in it, and the check can be switched off, in which case watching the download host is again the only route.

Scope#

In scope — the parts Wheelhouse writes:

  • agent/ — the Go control plane: authentication, authorisation, the API, TLS, the licence gate, the desired-state loop, the app catalogue handling.
  • ui/ — the web UI.
  • packaging/ — the .deb, the systemd units, the first-boot script, the console banner, the installer and its unattended path.
  • tools/ — the OPNsense importer and the seed builder.
  • The release pipeline and the published artefacts.

Out of scope here, but still worth telling us about:

  • VyOS, the Linux kernel, FRR, Kea, pdns-recursor, nftables, strongSwan, OpenVPN, Suricata, Podman and every other Debian package in the image. These are upstream and unmodified; report them to their own projects. If a Wheelhouse image ships a version with a known vulnerability, that is ours — tell us, and it becomes a question of when a new image goes out.
  • Anything that requires root on the router, or physical access to it. Both are outside the threat model.
  • A finding already on the known-gaps list below. Telling us how bad it actually is, with a working demonstration, is still useful.
  • Scanner output with nothing behind it: a header absent by design, a TLS suite you would prefer, a version number in a banner. It will be read, and the question will be what an attacker does with it.

Safe harbour#

Research done in good faith against your own installation is welcome and will not be pursued. That means your own hardware or VM, no access to anyone else's data, no denial of service against shared infrastructure, no social engineering of people, and the windows above before going public.

The licence server and the download host are live services other people depend on. Report what you find; do not test destructively against them.

What is not offered#

  • No bug bounty. There is no money. There is credit in the changelog, a reply from a person who read the report, and a fix.
  • No CVE assignment. Wheelhouse is not a CNA. If you want a CVE, request one and the details will be confirmed.
  • No embargo longer than 90 days without a specific reason you agree with.

The gaps already known#

The product's own list. Among them:

  • Releases are not signed. SHA256SUMS is signed only when a release key is configured in the build environment, and no key exists yet, so nothing published so far carries a signature. A checksum proves the download survived the network, nothing more.
  • Nothing signs the audit log, and the chain does not stop root. The file (/config/wheelhouse/audit.jsonl, mode 0600) now carries a sequence number and the hash of the previous entry on every line, and GET /api/audit/verify names the first entry that does not fit — but there is no secret in the digest, and there cannot be one that root cannot read, so root can re-chain the whole file. What defeats that is the copy that already left: the syslog export in Settings.AuditSyslog sends each entry as it is written, and a collector's copy is what a re-chained file no longer agrees with. That export is off until you configure a collector, so a router as shipped holds the only copy of its own log.
  • The agent binds every interface by default (0.0.0.0:8443), so out of the box the firewall is the only thing keeping the management UI off the WAN. Admin → Agent settings → Management address narrows it to one address and /config keeps that across an image upgrade. That is narrower, not safe: it decides where the port answers, not who may reach it. It also fails open on a downgrade — an agent that does not know the field drops it and the listener widens back to every interface.
  • No hardware-key second factor. Two-factor is TOTP. Enrolment issues ten single-use recovery codes and an administrator can clear another account's factor, so losing a device is no longer a console job — but a phishable shared secret is still the strongest factor available.
  • A factory reset is not a secure erase, and revokes nothing already taken. A factory reset, from the System page or wheelhouse-rescue factory-reset at the console, wipes the agent's data directory — accounts, hashes, second factors, API tokens, the audit log, the TLS key, the captures — and re-runs first boot, keeping the licence key by default. It unlinks files rather than overwriting them, so a disk that leaves your hands still needs destroying, and it revokes nothing another system already holds: an audit log a syslog collector has stays there, and the git export's deploy key stays authorised on the remote. Separately, a reset password on its own still leaves every API token on that account working.
  • Physical access is administrator access, and now visibly so. wheelhouse-rescue resets a web UI password without knowing one, and the install medium's rescue entry does the same to a disk it can mount. The check that replaces the password is presence at a console: it refuses unless its controlling terminal is a real console, refuses inside an SSH session whatever the terminal says, and there is no flag to turn that off. Physical access was already outside the threat model; the console port and the install medium now want the same care as a key to the rack.
  • Secrets are redacted by leaf name, so a value that is a secret because of where it sits — a container environment variable, an SNMP community string — is not matched below the admin role.

See also#

Updated 2026-09-03 security disclosure legal