Wheelhouse docs

What a read hides#

A viewer can read the whole configuration tree, and the configuration tree contains WireGuard private keys, IPsec pre-shared secrets and password hashes. So nine read endpoints are wrapped in redactSecrets, which replaces the value of any known secret leaf with the literal string [redacted] for a principal below a stated role. It is a wrapper on the route table rather than a line inside each handler, because /api/config, /api/config/commands, /api/wireguard and /api/vpn/ipsec all reach the same secrets by different code paths and the next read endpoint somebody adds would have missed the check.

json
{
  "interfaces": {
    "wireguard": {
      "wg0": {
        "address": "10.0.0.1/24",
        "private-key": "[redacted]",
        "peer": {"laptop": {"public-key": "kZ…="}}
      }
    }
  }
}

public-key is left alone. The match is on whole field names, not substrings.

The endpoints that wear it#

EndpointRedacted below
GET /api/configadmin
GET /api/config/commandsadmin
GET /api/vpn/ipsecadmin
GET /api/vpn/openvpnadmin
GET /api/wireguardadmin
GET /api/driftadmin
GET /api/history/diffadmin
GET /api/fleet/{id}/configadmin
GET /api/stagedoperator

/api/staged is the odd one, deliberately: the operator who staged a key typed it a moment ago, and a Commit Bar that shows them [redacted] for their own change is not a preview. A viewer has no such claim on it.

GET /api/config/raw is not in this list. It is the whole-configuration download, secrets included — the backup export — so instead of being redacted it is admin-only.

The leaf names#

Fifteen names, matched case-insensitively and with surrounding quotes stripped:

private-key          pre-shared-key       pre-shared-secret
preshared-key        psk                  plaintext-password
encrypted-password   password             passphrase
shared-secret-key    secret               key
api-key              auth-key             authentication-key

Redaction keys on the leaf name, not on a path, because these names are stable wherever they appear in the tree — a new VyOS feature that stores a pre-shared-key under a node nobody has documented yet is still covered.

Four of them are also ordinary English words#

key, secret, password and psk are unambiguous as leaf names in a tree, and ambiguous loose in a line of text. Matching them anywhere turned the router's message no key found into no key [redacted]. So in text they are honoured only on a line that is plainly configuration: one that starts with set or delete, or whose last field is quoted, which is what a configuration line looks like and what a sentence does not.

Two ways it is applied#

The wrapper buffers the handler's response body — headers still go straight out — and then rewrites it.

The body isWhat happens
Valid JSONDecoded, walked, and re-encoded. Every map key that is a secret leaf has its value replaced, at any depth, inside arrays too. Every string value is additionally passed through the text rule below.
Anything elseTreated as text: line by line, field by field.

The text rule replaces everything from the field after the secret name to the end of the line, preserving the line's indentation:

set interfaces wireguard wg0 private-key [redacted]

What it does not do#

The one place the agent blanks a secret outside this wrapper is the settings endpoint: GET /api/admin/settings clears the stored licence key before answering, and PUT /api/admin/settings preserves it across a write rather than letting a settings save drop it.

Checking it on your own router#

bash
# As a viewer:
curl -sk "$R/api/config?path=interfaces/wireguard" -H "Authorization: Bearer $VIEWER_TOKEN" \
  | grep -o '"private-key":"[^"]*"'
# "private-key":"[redacted]"

# As an admin, the same call returns the key.

See also#

Checked against#

agent/security.go (redactSecrets, secretLeaves, bareSecretLeaves, redactAny, redactText, isQuoted, captureWriter), agent/main.go (routes), agent/admin.go (handleGetSettings, handleUpdateSettings), agent/security_test.go, docs/security.md.

Updated 2026-09-02 api secrets redaction