When working with STIG compliance checks, a common challenge is that many checks only verify the existence of a control—not whether the configured values align with site-specific requirements. This can be a problem when compliance policies vary across different data centers and locations.
With a little work, it is easy to customize the queries. Benefits are apparent. You get:
- more precision to verify your specific ACL and group names
- Verifying differing configuration policies across multiple data centers or locations
- Improved compliance and governance across a variety of configurations and regions
There are two approaches you can use to customize queries.
- Copy the query and modify the block match to include the value of your parameter
- Parametrize the query and use your location-specific string value as a query parameter.
Parameterized queries are slightly more complex but make existing STIG checks - and other NQEs - more flexible.
Let’s use an example of a library STIG query /Forward Library/Security/STIGs/Cisco/Cisco IOS Router NDM/CISC-ND-000140 V-215667 to illustrate. The intent of the query as described by the DISA is:
* @intent The Cisco router must be configured to enforce approved authorizations for controlling the flow of management information within the device based on control policies.
The library query offers the following logic:
patternAcccessList = ```
line vty
access-class {string} in
```;
isVulnerable(params, config)= !hasBlockMatch(config, patternAcccessList);
The code looks for the control plane configuration (“line vty”) within the Cisco device configuration and marks it as a violation if the vty line is not configured to restrict access to an access-class.
For a more precise policy verification, you would want to check that the vty line access is restricted to not just any access-class, but a specific access class specified by your corporate policy.
Let’s try that with the assumption that the access class in your location A carries the name of VTY_IN_A.
Taking approach 1 you can copy the query to your own org repository and modify the check as follows:
patternAcccessList = ```
line vty
access-class VTY_IN_A in
```;
isVulnerable(params, config)= !hasBlockMatch(config, patternAcccessList);
Note: when copying the query you need to modify the import statement from the relative to an absolute path to read:
import "@fwd/Security/STIGs/Cisco/Utils";
This simple approach works well if your policy calls for the same access list in all locations. However, if you still want more precision but your policy is location-specific, you may take approach number 2 and make the query parameterized.
Parametrizing the query is an approach that allows you to run an NQE query with arguments using @query
statement. More details about this approach are in this NQE documentation chapter.
In this case the check code would look like this:
patternAcccessList = ```
line vty
access-class {accessClass:string} in
```;
//VTY_ACCESS_IN in vrf-also
getMatches(params, config) =
foreach match in blockMatches(config, patternAcccessList)
select { "List_name": match.data.accessClass,
"ByPolicy": match.data.accessClass == toString(params)
} ;
isVulnerable(params, config) =
!any(foreach match in getMatches(params, config) select match.ByPolicy);
This query retrieves the string that restricts the access-class, if that string exists. Then it outputs all matches with the determination if the string matches the policy string. Finally, it declares a violation if no access-class restrictions are found or any of the found strings do not match the string specified as a query parameter.
To call the query you would use a @query NQE command. When executing the query, specify your string in the Parameters section.

The query below is a full parameterized version of the query we described above.
Let us know if you have questions or need help adapting it for your setup!
* @intent The Cisco router must be configured to enforce approved authorizations for
controlling the flow of management information within the device based on
control policies. Severity: medium
* @description A mechanism to detect and prevent unauthorized communication flow must be
configured or provided as part of the system design. If management information
flow is not enforced based on approved authorizations, the network device may
become compromised. Information flow control regulates where management
information is allowed to travel within a network device. The flow of all
management information must be monitored and controlled so it does not introduce
any unacceptable risk to the network device or data.
Application-specific
examples of enforcement occur in systems that employ rule sets or establish
configuration settings that restrict information system services or
message-filtering capability based on message content (e.g., implementing key
word searches or using document characteristics).
Applications providing
information flow control must be able to enforce approved authorizations for
controlling the flow of management information within the system in accordance
with applicable policy.
*
* Severity: medium
* Operating System: cisco_ios
* Device Type: Router
* Version/Revision: V3R1
* Group_Title: SRG-APP-000038-NDM-000213
* Vulnerability ID: V-215667
* Rule ID: SV-215667r991819_rule
* Rule Version: CISC-ND-000140
* Legacy Vulnerabilities: >"CCI-001368", "CCI-004192", "SV-105161", "V-96023"]
*/
import "@fwd/Security/STIGs/Cisco/Utils";
// AUTO-GENERATED ABOVE HERE
patternAcccessList = ```
line vty
access-class {accessClass:string} in
```;
//VTY_ACCESS_IN in vrf-also
getMatches(params, config) =
foreach match in blockMatches(config, patternAcccessList)
select { "List_name": match.data.accessClass,
"ByPolicy": match.data.accessClass == toString(params)
} ;
isVulnerable(params, config) =
!any(foreach match in getMatches(params, config) select match.ByPolicy);
// isVulnerable(params, config)= !hasBlockMatch(config, patternAcccessList);
// AUTO-GENERATED BELOW HERE
checkContent = """
Review the Cisco router configuration to verify that it is compliant with this
requirement.
Step 1: Verify that the line vty has an ACL inbound applied as
shown in the example below.
line vty 0 1
access-class MANAGEMENT_NET in
transport input ssh
Step 2: Verify that the ACL permits only hosts from the
management network to access the router.
ip access-list extended MANAGEMENT_NET
permit ip x.x.x.0 0.0.0.255 any
deny ip any any log-input
If the Cisco
router is not configured to enforce approved authorizations for controlling the
flow of management information within the device based on control policies, this
is a finding.
""";
fixText = """
Configure the Cisco router to restrict management access to specific IP
addresses via SSH as shown in the example below.
SW2(config)#ip access-list
standard MANAGEMENT_NET
SW2(config-std-nacl)#permit x.x.x.0 0.0.0.255
SW2(config-std-nacl)#exit
SW2(config)#line vty 0 1
SW2(config-line)#transport
input ssh
SW2(config-line)#access-class MANAGEMENT_NET in
SW2(config-line)#end
""";
intent = """
The Cisco router must be configured to enforce approved authorizations for
controlling the flow of management information within the device based on
control policies.
""";
description = """
A mechanism to detect and prevent unauthorized communication flow must be
configured or provided as part of the system design. If management information
flow is not enforced based on approved authorizations, the network device may
become compromised. Information flow control regulates where management
information is allowed to travel within a network device. The flow of all
management information must be monitored and controlled so it does not introduce
any unacceptable risk to the network device or data.
Application-specific
examples of enforcement occur in systems that employ rule sets or establish
configuration settings that restrict information system services or
message-filtering capability based on message content (e.g., implementing key
word searches or using document characteristics).
Applications providing
information flow control must be able to enforce approved authorizations for
controlling the flow of management information within the system in accordance
with applicable policy.
""";
ruleData =
{ severity: "2 - medium",
intent,
description,
checkContent,
fixText,
ruleId: "SV-215667r991819_rule",
ruleVersion: "CISC-ND-000140",
vulnerabilityId: "V-215667",
stig: "Cisco IOS Router NDM",
stigVersion: "V3R1",
skipped: false,
};
export ruleDataV215667 = ruleData;
export isVulnerableV215667(config: List<ConfigLine>) = isVulnerable({}, config);
f(params) =
foreach device in network.devices
where isPresent(device.files.config)
where isIosRouter(device.platform)
select {
violation: isVulnerable(params, device.files.config),
ListMatches: getMatches(params, device.files.config),
Device: device.name,
OS_Version: device.platform.osVersion,
Model: device.platform.model,
Mgmt_IPs: device.platform.managementIps,
};
// AUTO GENERATED ABOVE HERE
@query
query(params: String) = f(params);