Skip to content

IOS-XE baseline standard

A baseline standard is the set of values every device of one type should have: the same DNS and NTP servers, the same admin account, the same management access. This page walks through the stock baseline standard, ios-baseline.policy, one section at a time. Import it with Import Templates (see importing a stock template), then edit the values to match your own.

The definition has eleven blocks, one per section. Each block is one rule, so the compliance report shows a result per section. The definition needs rConfig 8.3.0 or later, because the VTY section uses evaluate_block.

  • Array sections (must_match_all_from_array) pass when every listed line appears somewhere in the config. Each line is matched as text, not as a whole line: ntp server 192.0.2.10 also matches ntp server 192.0.2.10 prefer, and also ntp server 192.0.2.100. The order of the lines and the section they sit in do not matter.
  • Wildcard sections (wildcard_match_single_string) treat * as any run of characters on that line, so the section passes whatever the hash or next hop is.
  • The VTY section (evaluate_block with scope: ^line vty) checks each line vty block on its own. Every block must pass.

These are the results recorded with rConfig Pro’s evaluator in the repository’s expected results. The snippets on this page come from the first two samples.

SectionHardened Catalyst 9500 (synthetic)Cisco 1921 (lab, unhardened)Catalyst 9500 (synthetic)Operational standards (synthetic)
Servicespasspassfailfail
DNSpassfailfailfail
NTPpassfailfailpass
Otherpasspassfailfail
Credspassfailfailfail
Creds: no plaintext passwordspassfailpasspass
HTTPpassfailfailfail
Routingpasspasspasspass
SSHpasspasspasspass
SNMPpassfailfailfail
VTYpassfailpasspass

The lab router passes Services, Other, Routing and SSH because it has those lines. Every sample has a default route and ip ssh version 2, so the failing configs for those two sections are the hardened sample with that one line removed. In the repository checks, removing or changing one line per section in the hardened sample fails that section and no other.


Debug and log messages carry millisecond timestamps, and the DHCP server and relay are off. service dhcp is on by default, so IOS prints only no service dhcp when it is off.

// Cisco Services Standard
#[must_match_all_from_array]
service timestamps debug datetime msec
service timestamps log datetime msec
no service dhcp

From the hardened Catalyst 9500 sample. The localtime show-timezone options still pass, because each line is matched as text.

service timestamps debug datetime msec localtime show-timezone
service timestamps log datetime msec
service password-encryption
service call-home
no service dhcp

From the Catalyst 9500 sample. There is no no service dhcp line.

service timestamps debug datetime msec localtime show-timezone
service timestamps log datetime msec localtime show-timezone
service password-encryption
service call-home

Remove no service dhcp if the device serves or relays DHCP. Add any other service lines your standard requires, one per line.


DNS lookup of mistyped commands is off, the domain name is set, and both standard name servers are configured.

// Cisco DNS Standard
#[must_match_all_from_array]
no ip domain lookup
ip domain name example.com
ip name-server 192.0.2.53
ip name-server 198.51.100.53

From the hardened Catalyst 9500 sample.

no ip domain lookup
ip domain name example.com
ip name-server 192.0.2.53
ip name-server 198.51.100.53

From the Cisco 1921 lab sample. The name servers are not the standard ones.

no ip domain lookup
ip domain name example.com
ip name-server 192.0.2.8
ip name-server 192.0.2.1
ip name-server 192.0.2.3
ip name-server 192.0.2.4

Replace example.com and the two addresses. Each name server needs its own ip name-server line in the config: a device that shows both on one line (ip name-server 192.0.2.53 198.51.100.53) fails, because the second line of the block is not in the config. Older IOS releases print ip domain-name and no ip domain-lookup; use the form your devices print.


Both standard NTP servers are configured.

// Cisco NTP Standard
#[must_match_all_from_array]
ntp server 192.0.2.10
ntp server 192.0.2.11

From the hardened Catalyst 9500 sample. prefer after the address still passes.

ntp source Vlan99
ntp server 192.0.2.10 prefer
ntp server 192.0.2.11

From the Catalyst 9500 sample. Neither standard server is configured.

ntp source Vlan99
ntp server 192.0.2.1 prefer
ntp server 192.0.2.2

Replace the two addresses. Because each line is matched as text, ntp server 192.0.2.10 also passes on ntp server 192.0.2.100. If that matters, use the regex rule in ios-operational-standards.policy, which matches each address as a whole and accepts ntp server vrf <name>.


AAA is enabled and IPv6 unicast routing is on.

// Cisco Other Standard
#[must_match_all_from_array]
aaa new-model
ipv6 unicast-routing

Excerpts from the hardened Catalyst 9500 sample. The two lines are in different parts of the config.

aaa new-model
...
ip name-server 198.51.100.53
!
ipv6 unicast-routing

Excerpts from the Catalyst 9500 sample. AAA is enabled, but there is no ipv6 unicast-routing line anywhere in the config.

aaa new-model
...
ip routing
!
no ip domain lookup
ip domain name dub.example.net

Remove ipv6 unicast-routing if your devices do not route IPv6. Add other global lines your standard requires.


A local admin user exists with privilege 15 and a type 9 (scrypt) secret. The * matches any hash.

// Cisco Creds Standard
#[wildcard_match_single_string]
username admin privilege 15 secret 9 *

From the hardened Catalyst 9500 sample. The hash is made up.

username admin privilege 15 secret 9 $9$EXAMPLEONLY001$EXAMPLEONLYFAKEHASHEXAMPLEONLYFAKEHASH12345
username netops privilege 15 secret 9 $9$5J0T7SYCEJJ3F7$K508GSW4V4P8230Z3VK1FA20CJUKCT8R6UUQCCP6UY8

From the Cisco 1921 lab sample. There is no admin user, and the users have plaintext passwords.

username cisco privilege 15 password 0 ExamplePass1
username labuser1 password 0 ExamplePass2

Replace admin with your local account name. To accept any secret type, change secret 9 * to secret *; that also accepts a type 5 (MD5) hash.


No line stores a password as type 0, which is plaintext: username ... password 0 ... or any other password 0 line.

// Cisco Creds Standard: no plaintext passwords
#[must_not_match_regex]
/^.*\bpassword 0 \S/m

From the hardened Catalyst 9500 sample. Secrets are hashed and keys are type 7.

username admin privilege 15 secret 9 $9$EXAMPLEONLY001$EXAMPLEONLYFAKEHASHEXAMPLEONLYFAKEHASH12345
username netops privilege 15 secret 9 $9$5J0T7SYCEJJ3F7$K508GSW4V4P8230Z3VK1FA20CJUKCT8R6UUQCCP6UY8

From the Cisco 1921 lab sample.

username cisco privilege 15 password 0 ExamplePass1
username labuser1 password 0 ExamplePass2

Nothing to replace. IOS prints a line password without a type ( password example-vty), so this section does not catch it; the VTY section does.


The HTTP and HTTPS servers are both off, and HTTP authentication uses the local user database if the server is turned on later.

// Cisco HTTP Standard
#[must_match_all_from_array]
no ip http server
ip http authentication local
no ip http secure-server

From the hardened Catalyst 9500 sample.

no ip http server
ip http authentication local
no ip http secure-server

From the Cisco 1921 lab sample. The HTTPS server is on.

no ip http server
ip http authentication local
ip http secure-server
ip http secure-client-auth

If your standard enables the HTTPS server for the web UI, do not simply change the last line to ip http secure-server: the line is matched as text, so it would also match no ip http secure-server. Put that line in an evaluate_block rule with equals:, which compares whole lines (see section-scoped checks). The stock Cisco IOS services hardening file also fails when the HTTPS server is on.


A static default route is configured. The * matches any next hop or interface.

// Cisco Routing Standard
#[wildcard_match_single_string]
ip route 0.0.0.0 0.0.0.0 *

From the hardened Catalyst 9500 sample.

ip ssh source-interface Vlan99
ip tacacs source-interface Vlan99
ip route 0.0.0.0 0.0.0.0 192.0.2.1

The hardened Catalyst 9500 sample with the default route removed.

ip ssh source-interface Vlan99
ip tacacs source-interface Vlan99

To require one next hop, replace * with it, for example ip route 0.0.0.0 0.0.0.0 192.0.2.1. A default route in a VRF (ip route vrf ...) does not match.


SSH version 2 is configured. A line must read exactly ip ssh version 2.

// Cisco SSH Standard
#[must_match_single_string]
ip ssh version 2

From the hardened Catalyst 9500 sample.

ip ssh version 2
ip ssh time-out 60
ip ssh authentication-retries 3

The hardened Catalyst 9500 sample with ip ssh version 2 removed.

ip ssh time-out 60
ip ssh authentication-retries 3

Nothing to replace. To add other SSH settings, such as ip ssh time-out 60, change the method to must_match_all_from_array and list them, one per line. An array method needs at least two lines.


The standard SNMPv3 group uses authPriv (authentication and encryption), and traps go to the standard host with SNMPv3 authPriv.

// Cisco SNMP Standard
#[must_match_all_from_array]
snmp-server group SNMPV3GROUP v3 priv
snmp-server host 192.0.2.50 version 3 priv SNMPV3USER

Excerpts from the hardened Catalyst 9500 sample.

snmp-server group NMS-GROUP v3 priv
snmp-server group SNMPV3GROUP v3 priv
...
snmp-server host 192.0.2.50 version 3 priv SNMPV3USER
snmp-server host 192.0.2.60 version 3 priv nms-poller

From the Cisco 1921 lab sample. There is no SNMPv3 group, and the hosts use communities.

snmp-server community public RO
snmp-server host 192.0.2.1 TESTCOMMUNITY
snmp-server host 198.51.100.2 TESTCOMMUNITY12xxxxx

Replace SNMPV3GROUP, 192.0.2.50 and SNMPV3USER. SNMPv3 users (snmp-server user) are not shown in the running config, so the user itself cannot be checked.


Every VTY line block accepts SSH only and has no line password, so logins use AAA or local users.

// Cisco VTY Standard
#[evaluate_block]
scope: ^line vty
all:
- equals: transport input ssh
- not:
regex: '/^\s*password\b/m'

From the hardened Catalyst 9500 sample. Both VTY blocks pass.

line vty 0 4
access-class MGMT-ACCESS in vrf-also
exec-timeout 5 0
logging synchronous
transport input ssh
line vty 5 15
access-class MGMT-ACCESS in vrf-also
exec-timeout 5 0
transport input ssh

From the Cisco 1921 lab sample. The block has a line password and allows Telnet.

line vty 0 4
password example-vty
login local
no activation-character
international
transport input telnet ssh

equals: compares whole lines, so transport input ssh telnet fails. A config with no line vty block fails, because a scoped block fails when nothing matches its scope.


The sidecar records these references. They are for reading only: the generated framework files collect hardening files, not this baseline. A section provides evidence towards a control; it does not make a device compliant with it.

SectionNIST SP 800-53HIPAA (45 CFR)ISO/IEC 27001:2022
NTPAU-8NoneA.8.17
CredsIA-5NoneA.5.17
Creds: no plaintext passwordsIA-5NoneA.5.17
HTTPCM-7NoneA.8.9
SSHAC-17164.312(a)(1)A.8.24
SNMPSC-12164.312(e)(1)A.8.5, A.8.24
VTYAC-17164.312(a)(1)A.8.5

Services, DNS, Other and Routing have no references.

ItemDetail
Tested OS versionIOS XE 17.9 (synthetic samples built from rConfig Pro’s IOS-XE demo generator) and IOS 15.7 (sanitised lab sample). The passing configs were not captured from a device.
Minimum rConfig version8.3.0 (evaluate_block)
EditionsPro, Vector, Enterprise
Sourcecisco/ios-baseline.policy and its samples in rconfig/pro-policy-definitions v1.4.0. Results are recorded with rConfig Pro’s evaluator, not asserted by a Pro test.