Description
python/vyos/utils/strip_config.py redacts secrets from a configuration with a hand written list of paths. It is used by vyos-show-config --strip-private and by the running configuration part of the machine-readable tech-support data (src/op_mode/tech_support.py, _get_running_config(), used by show tech-support report machine-readable). The file was added in July 2024 (T6498) and has only had formatting and license changes since, so nodes added later are not in it, and many older ones never were.
Example, VyOS rolling 2026.10.16, one committed value:
set system proxy url http://192.0.2.1 set system proxy port 3128 set system proxy username proxyuser set system proxy password SECRETPROXYPW commit
$ vyos-show-config --strip-private # prints: password "SECRETPROXYPW" $ show configuration commands | strip-private # prints: set system proxy password xxxxxx
_get_running_config() of tech_support.py also returns SECRETPROXYPW in clear text. (On my image show tech-support report machine-readable itself stops with NotADirectoryError: /sys/module/compression in get_module_data(), so I called the function directly. That crash is a separate problem.)
How I looked at it
I expanded the interface definitions of rolling with their includes and took every leaf node whose name looks like a secret (secret, passw*, passphrase, psk, token, key, community, md5, ...): 171 candidates. After removing obvious non-secrets (key-name, secret-length, password-protected, public-key, key-exchange, GRE tunnel keys and similar) and two nodes that only name a PKI object or a file (protocols rpki cache ssh key, service dns dynamic name key) 80 remain, plus 8 copies below vrf name. For each of them I built a configuration tree with a marker value, ran strip_config_tree() and the strip-private.py filter on a VyOS VM and checked whether the marker is still readable. As a positive control five covered paths (SNMPv3 auth, WireGuard private key, IPsec PSK, BGP neighbour password, login password hash) were all redacted.
Result: strip_config.py leaves all 88 readable. The regex filter behind | strip-private removes most of them and leaves 22 readable, plus 4 of the VRF copies (column below, for example the OpenVPN keys, WPA and eapol passphrases, WireGuard preshared-key, IPsec x509 and RSA passphrases, SNMP trap community, and the MD5 keys of IS-IS and OpenFabric).
The list is based on node names, so it needs a review by someone who knows the nodes. Some entries may not be secrets in the sense of the filter (for example the SNMP community or the MaxMind license key), I included them because they work as a credential.
Documentation
The documentation tells users to use the filter before sharing a configuration: docs/cli.md: "Use the show configuration commands | strip-private command when you want to hide private data. You may want to do so if you want to share your configuration on the forum." and docs/configuration/system/syslog.md for logs. Nothing says which values are removed or that the list is incomplete. The human readable show tech-support report and the archive are not part of this: their help text says "(contains private information)" and their running configuration sections are not redacted by design (show_techsupport_report.py, measured in the archive). The tech-support documentation (docs/vpp/troubleshooting.md) does not mention redaction at all.
Affected nodes (not redacted by strip_config.py)
| Node | Definition file | Pipe filter `\ | strip-private` |
|---|---|---|---|
| container registry <name> authentication password | container.xml.in | stripped | |
| firewall global-options geoip maxmind-license-key | firewall.xml.in | not stripped | |
| interfaces bonding <name> eapol passphrase | interfaces_bonding.xml.in | not stripped | |
| interfaces ethernet <name> eapol passphrase | interfaces_ethernet.xml.in | not stripped | |
| interfaces macsec <name> security static key | interfaces_macsec.xml.in | stripped | |
| interfaces macsec <name> security static peer <name> key | interfaces_macsec.xml.in | stripped | |
| interfaces openvpn <name> authentication password | interfaces_openvpn.xml.in | stripped | |
| interfaces openvpn <name> shared-secret-key | interfaces_openvpn.xml.in | not stripped | |
| interfaces openvpn <name> tls auth-key | interfaces_openvpn.xml.in | not stripped | |
| interfaces openvpn <name> tls crypt-key | interfaces_openvpn.xml.in | not stripped | |
| interfaces pppoe <name> authentication password | interfaces_pppoe.xml.in | stripped | |
| interfaces sstpc <name> authentication password | interfaces_sstpc.xml.in | stripped | |
| interfaces wireguard <name> peer <name> preshared-key | interfaces_wireguard.xml.in | not stripped | |
| interfaces wireless <name> security wep key | interfaces_wireless.xml.in | stripped | |
| interfaces wireless <name> security wpa passphrase | interfaces_wireless.xml.in | not stripped | |
| interfaces wireless <name> security wpa radius server <name> key | interfaces_wireless.xml.in | stripped | |
| interfaces wwan <name> authentication password | interfaces_wwan.xml.in | stripped | |
| protocols isis area-password md5 | protocols_isis.xml.in | not stripped | |
| protocols isis domain-password md5 | protocols_isis.xml.in | not stripped | |
| protocols isis domain-password plaintext-password | protocols_isis.xml.in | not stripped | |
| protocols isis interface <name> password md5 | protocols_isis.xml.in | not stripped | |
| protocols mpls ldp neighbor <name> password | protocols_mpls.xml.in | stripped | |
| protocols openfabric domain <name> domain-password md5 | protocols_openfabric.xml.in | not stripped | |
| protocols openfabric domain <name> domain-password plaintext-password | protocols_openfabric.xml.in | not stripped | |
| protocols openfabric domain <name> interface <name> password md5 | protocols_openfabric.xml.in | not stripped | |
| protocols openfabric domain <name> interface <name> password plaintext-password | protocols_openfabric.xml.in | not stripped | |
| protocols ospf area <name> virtual-link <name> authentication md5 key-id <name> md5-key | protocols_ospf.xml.in | stripped | |
| protocols ospf area <name> virtual-link <name> authentication plaintext-password | protocols_ospf.xml.in | stripped | |
| protocols rip interface <name> authentication md5 <name> password | protocols_rip.xml.in | stripped | |
| service config-sync secondary key | service_config-sync.xml.in | stripped | |
| service dhcp-server dynamic-dns-update tsig-key <name> secret | service_dhcp-server.xml.in | stripped | |
| service dns dynamic name <name> password | service_dns_dynamic.xml.in | stripped | |
| service ipoe-server authentication radius dynamic-author key | service_ipoe-server.xml.in | stripped | |
| service monitoring telegraf loki authentication password | service_monitoring_telegraf.xml.in | stripped | |
| service monitoring zabbix-agent authentication psk secret | service_monitoring_zabbix-agent.xml.in | stripped | |
| service pppoe-server authentication radius dynamic-author key | service_pppoe-server.xml.in | stripped | |
| service pppoe-server ppp-options ipv6-peer-interface-id-secret | service_pppoe-server.xml.in | stripped | |
| service snmp trap-target <name> community | service_snmp.xml.in | not stripped | |
| service snmp v3 trap-target <name> auth encrypted-password | service_snmp.xml.in | stripped | |
| service snmp v3 trap-target <name> auth plaintext-password | service_snmp.xml.in | stripped | |
| service snmp v3 trap-target <name> privacy encrypted-password | service_snmp.xml.in | stripped | |
| service snmp v3 trap-target <name> privacy plaintext-password | service_snmp.xml.in | stripped | |
| service snmp v3 user <name> auth plaintext-password | service_snmp.xml.in | stripped | |
| service stunnel client <name> options password | service_stunnel.xml.in | stripped | |
| service stunnel client <name> psk <name> secret | service_stunnel.xml.in | stripped | |
| service stunnel server <name> psk <name> secret | service_stunnel.xml.in | stripped | |
| service webproxy authentication ldap password | service_webproxy.xml.in | stripped | |
| system config-management commit-archive location <name> ftp authentication password | system_config-management.xml.in | stripped | |
| system config-management commit-archive location <name> ftps authentication password | system_config-management.xml.in | stripped | |
| system config-management commit-archive location <name> git authentication password | system_config-management.xml.in | stripped | |
| system config-management commit-archive location <name> http authentication password | system_config-management.xml.in | stripped | |
| system config-management commit-archive location <name> https authentication password | system_config-management.xml.in | stripped | |
| system config-management commit-archive location <name> scp authentication password | system_config-management.xml.in | stripped | |
| system config-management commit-archive location <name> sftp authentication password | system_config-management.xml.in | stripped | |
| system config-management commit-archive location <name> ssh authentication password | system_config-management.xml.in | stripped | |
| system login radius server <name> key | system_login.xml.in | stripped | |
| system login tacacs server <name> key | system_login.xml.in | stripped | |
| system login user <name> authentication otp key | system_login.xml.in | stripped | |
| system login user <name> authentication plaintext-password | system_login.xml.in | stripped | |
| system proxy password | system_proxy.xml.in | stripped | |
| vpn ipsec authentication ppk <name> secret | vpn_ipsec.xml.in | stripped | |
| vpn ipsec profile <name> authentication pre-shared-secret | vpn_ipsec.xml.in | stripped | |
| vpn ipsec remote-access connection <name> authentication x509 passphrase | vpn_ipsec.xml.in | not stripped | |
| vpn ipsec remote-access radius server <name> key | vpn_ipsec.xml.in | stripped | |
| vpn ipsec site-to-site peer <name> authentication rsa passphrase | vpn_ipsec.xml.in | not stripped | |
| vpn ipsec site-to-site peer <name> authentication x509 passphrase | vpn_ipsec.xml.in | not stripped | |
| vpn l2tp remote-access authentication radius dynamic-author key | vpn_l2tp.xml.in | stripped | |
| vpn l2tp remote-access authentication radius server <name> key | vpn_l2tp.xml.in | stripped | |
| vpn l2tp remote-access ipsec-settings authentication x509 passphrase | vpn_l2tp.xml.in | not stripped | |
| vpn l2tp remote-access lns shared-secret | vpn_l2tp.xml.in | stripped | |
| vpn l2tp remote-access ppp-options ipv6-peer-interface-id-secret | vpn_l2tp.xml.in | stripped | |
| vpn openconnect accounting radius server <name> key | vpn_openconnect.xml.in | stripped | |
| vpn openconnect authentication local-users username <name> otp key | vpn_openconnect.xml.in | stripped | |
| vpn openconnect ssl passphrase | vpn_openconnect.xml.in | not stripped | |
| vpn pptp remote-access authentication radius dynamic-author key | vpn_pptp.xml.in | stripped | |
| vpn pptp remote-access authentication radius server <name> key | vpn_pptp.xml.in | stripped | |
| vpn pptp remote-access ppp-options ipv6-peer-interface-id-secret | vpn_pptp.xml.in | stripped | |
| vpn sstp authentication local-users username <name> password | vpn_sstp.xml.in | stripped | |
| vpn sstp authentication radius dynamic-author key | vpn_sstp.xml.in | stripped | |
| vpn sstp ppp-options ipv6-peer-interface-id-secret | vpn_sstp.xml.in | stripped | |
Further findings while checking
- show configuration json | strip-private and show configuration json pretty | strip-private leave the proxy password readable (the text formats show configuration and show configuration commands are stripped). The filter does not report anything, so it looks as if it worked.
- SNMP community strings stay readable in both filters, the community name of service snmp community <name> (a tag node value, which a list of leaf paths cannot strip) as well as trap-target ... community.
- RADIUS shared secrets are meant to be covered: the list already has the authentication radius server key of SSTP, L2TP, PPTP, OpenConnect, IPoE and PPPoE. The nodes in the table below are the ones it misses (login RADIUS and TACACS, IPsec remote-access, OpenConnect accounting, the dynamic-author keys, wireless).
- The regex filter has a stated constraint: T5713 (2023) narrowed the secret rule because the output of strip-private must stay a valid configuration (use-secret foo became secret xxxxxx). A path based list keeps that property, a name based regex does not.
- The two implementations have separate histories: the regex filter strip-private.py since 2021 (T3354, extended in T3642, T3926, T4177, T5713), the path list since 2024 (T6498). I found no statement which one is the reference.
Possible directions
- Add the nodes above to the list (a first step, mechanical).
- Stop maintaining the list by hand: derive the secret nodes from the definitions (for example a marker on the node) or make a unit test fail when a node whose name looks like a secret is neither in the list nor explicitly excluded.
- Decide which of the two filters is the reference and make the other one use the same list.
Questions for the maintainers: is the SNMP community meant to be redacted, and the MaxMind license key? Should | strip-private also work for JSON output, or refuse it?
Not checked
Logs, the other files of the archive, the nodes whose name does not look like a secret, the machine-readable tech-support command end to end (it stops on my image, see above), and behaviour on other versions.