diff --git a/docs/templates/template_reference.md b/docs/templates/template_reference.md
index 90e59824113e..d5b61c21d538 100644
--- a/docs/templates/template_reference.md
+++ b/docs/templates/template_reference.md
@@ -462,10 +462,18 @@ they must be of the same length.
- **arg_name** - argument name, eg. `audit`
- **arg_value** - argument value, eg. `'1'`
+ This parameter is mutually exclusive with **arg_variable**.
- **arg_variable** - the variable used as the value for the argument, eg. `'var_slub_debug_options'`
This parameter is mutually exclusive with **arg_value**.
+ - **operation** - (optional) OVAL operation used to compare the
+ collected argument value with the expected value. Default value:
+ `pattern match`. When set to a numeric operation such as
+ `greater than or equal`, the OVAL check captures only the
+ numeric portion of the argument and compares it as an integer.
+ Works with both **arg_variable** and **arg_value**.
+
- Languages: Ansible, Bash, OVAL, Blueprint, Kickstart
#### grub2_bootloader_argument_absent
diff --git a/linux_os/guide/auditing/grub2_audit_backlog_limit_argument/rule.yml b/linux_os/guide/auditing/grub2_audit_backlog_limit_argument/rule.yml
index 274342124aca..3009f42e9a89 100644
--- a/linux_os/guide/auditing/grub2_audit_backlog_limit_argument/rule.yml
+++ b/linux_os/guide/auditing/grub2_audit_backlog_limit_argument/rule.yml
@@ -51,3 +51,4 @@ template:
vars:
arg_name: audit_backlog_limit
arg_variable: var_audit_backlog_limit
+ operation: greater than or equal
diff --git a/shared/templates/grub2_bootloader_argument/oval.template b/shared/templates/grub2_bootloader_argument/oval.template
index 480a4e6caee1..7842db1bf754 100644
--- a/shared/templates/grub2_bootloader_argument/oval.template
+++ b/shared/templates/grub2_bootloader_argument/oval.template
@@ -1,10 +1,76 @@
{{#-
- We set defaults to "off", and products should enable relevant ones depending on how the product configures grub.
- - /boot/loader/entries/* may not exist.
- - If they exist, they can reference variables defined in grubenv, or they can contain literal args
- - The grub cfg may either use those loader entries, or it can contain literal values as well
- - Kernel opts can be stored in /etc/default/grub so they are persistent between kernel upgrades
+ OVAL check for a GRUB bootloader kernel argument.
+
+ Verifies ARG_NAME (and optionally ARG_VALUE / ARG_VARIABLE) is present
+ across every GRUB config location the product uses. Supports two modes
+ controlled by the OPERATION template parameter:
+
+ "pattern match" (default)
+ Object captures the full value line; state matches via regex.
+ Works for any string argument (e.g. audit=1, nosmt).
+
+ "greater than or equal" (numeric)
+ Object captures only the digits after ARG_NAME=; state compares
+ the integer against ARG_VARIABLE or ARG_VALUE.
+ Use when a minimum threshold is required (e.g. audit_backlog_limit).
+
+ Why numeric_comparison branches appear throughout the template:
+
+ OVAL has no "extract then compare" — the object's regex capture group IS
+ the value the state receives. A state with datatype="int" needs a pure
+ integer, so every object must switch its regex between wide capture (.*)
+ and narrow capture (\d+). This is an OVAL spec limitation and cannot be
+ consolidated into a single guard.
+
+ Three consequences:
+ - Every object has a {%% if numeric_comparison %%} regex branch.
+ - RHEL8 (ol8/rhel8) needs a separate test+criterion (entries_numeric)
+ because the same path also needs the wide-capture object for
+ $kernelopts detection — two objects, two tests, criteria branch.
+ This goes away when RHEL8 reaches EOL.
+ - bootc duplicates the state logic (section 6) because TOML wraps
+ values in quotes ("arg=value") vs space-delimited kernel cmdline,
+ so the regex patterns are structurally different.
+
+ Variables from rule.yml template vars:
+ ARG_NAME – kernel argument name (e.g. "audit_backlog_limit")
+ ARG_VALUE – literal expected value; mutually exclusive with ARG_VARIABLE
+ ARG_VARIABLE – XCCDF variable name supplying the value at scan time
+ OPERATION – OVAL comparison operation (default: "pattern match")
+ IS_SUBSTRING – "true" if ARG_VALUE may appear as a substring
+
+ Variables computed by template.py (preprocess):
+ ARG_NAME_VALUE – "name=value" string used in metadata and remediations
+ ESCAPED_ARG_NAME – ARG_NAME with dots escaped for regex (OVAL only)
+ ESCAPED_ARG_NAME_VALUE – ARG_NAME_VALUE with dots escaped (OVAL only)
+ SANITIZED_ARG_NAME – ARG_NAME with special chars replaced; used in OVAL IDs
+
+ Variables from the build system (product properties):
+ product – product ID (e.g. "rhel9", "fedora")
+ grub2_boot_path – BIOS GRUB dir (e.g. /boot/grub2)
+ grub2_uefi_boot_path – UEFI GRUB dir (e.g. /boot/efi/EFI/redhat)
+ bootable_containers_supported – "true" if product supports bootc Image Mode
+
+ Template structure:
+ 1. Product flags – which GRUB config locations to check
+ 2. Comparison mode – numeric_comparison flag
+ 3. Criteria tree – AND/OR across locations + bootc Image Mode
+ 4. Tests, objects & helper states — per config location:
+ 4a. RHEL8 entries-or-grubenv (+ rescue filter state)
+ 4b. /etc/default/grub
+ 4c. /etc/default/grub.d/*.cfg (Ubuntu drop-ins)
+ 4d. grubenv
+ 4e. BLS entries (+ rescue filter state)
+ 4f. grub.cfg
+ 4g. $kernelopts detection state (RHEL8 only)
+ 5. Shared state & variables — state_grub2_{SANITIZED_ARG_NAME}_argument;
+ branched by (numeric_comparison, ARG_VARIABLE):
+ 5a. numeric — state with datatype="int", optional external_variable
+ 5b. pattern match, literal — state with regex
+ 5c. pattern match, variable — state + local_variable + external_variable
+ 6. bootc Image Mode — self-contained test, object & state
-#}}
+{{#- 1. Product flags: each product enables the GRUB locations it uses -#}}
{{% set system_with_expanded_kernel_options_in_loader_entries = false -%}}
{{% set system_with_kernel_options_in_grubenv = false -%}}
{{% set system_with_expanded_kernel_options_in_loader_entries_or_with_options_in_grubenv = false -%}}
@@ -33,6 +99,10 @@
{{% set system_with_bios_and_uefi_support = true %}}
{{%- endif -%}}
+{{#- 2. Comparison mode switch: numeric_comparison drives pattern and state branches -#}}
+{{% set numeric_comparison = (OPERATION != "pattern match") -%}}
+
+{{#- 3. Criteria tree: AND/OR across all checked locations -#}}
{{{ oval_metadata("Ensure " + ARG_NAME_VALUE + " is configured in the kernel line in /etc/default/grub.", rule_title=rule_title) }}}
@@ -42,8 +112,13 @@
{{% endif %}}
{{% if system_with_expanded_kernel_options_in_loader_entries_or_with_options_in_grubenv %}}
+ {{% if numeric_comparison %}}
+
+ {{% else %}}
+ {{% endif %}}
- {{% if system_with_bios_and_uefi_support -%}}
+ {{% if system_with_bios_and_uefi_support -%}}
@@ -72,20 +147,20 @@
{{%- endif %}}
{{% elif system_with_expanded_kernel_options_in_loader_entries -%}}
-
+
{{%- endif %}}
{{% if system_with_expanded_kernel_options_in_grub_cfg -%}}
- {{% if system_with_bios_and_uefi_support -%}}
-
- {{%- endif %}}
-
- {{% if system_with_bios_and_uefi_support -%}}
-
-
- {{%- endif %}}
+ {{% if system_with_bios_and_uefi_support -%}}
+
+ {{%- endif %}}
+
+ {{% if system_with_bios_and_uefi_support -%}}
+
+
+ {{%- endif %}}
{{%- endif %}}
{{% if system_with_kernel_options_in_etc_default_grub -%}}
@@ -121,7 +196,22 @@
+{{#- 4. Tests, objects & helper states — per config location -#}}
+
+{{#- 4a. RHEL8 entries-or-grubenv (ol8, rhel8)
+ BLS entries may contain args expanded inline OR reference $kernelopts from grubenv.
+ Three tests handle this:
+ entries_expanded_or_referenced — every non-rescue entry has the arg OR $kernelopts
+ at_least_one_entry_referenced — helper: does any entry use $kernelopts?
+ entries_numeric (numeric only) — integer value in expanded entries meets threshold -#}}
{{% if system_with_expanded_kernel_options_in_loader_entries_or_with_options_in_grubenv %}}
+ {{#- Test "entries_expanded_or_referenced": each non-rescue *.conf must satisfy at least
+ one of two states (state_operator="OR"):
+ state_argument — the arg is present in the captured options line
+ state_is_kernelopts — the line contains $kernelopts (value lives in grubenv)
+ Not referenced in criteria in numeric mode — the narrow (\d+) capture can't do the
+ OR trick, so entries_numeric is used instead. This test and its object are still
+ generated because at_least_one_entry_referenced reuses the object. -#}}
@@ -130,6 +220,9 @@
+ {{#- Object "obj_entries_expanded_or_referenced": scans /boot/loader/entries/*.conf.
+ Regex: ^options (.*)$ → group 1 = entire kernel command line after "options ".
+ Filter excludes *rescue.conf via the rescue state below. -#}}
/boot/loader/entries/
^.*\.conf$
@@ -138,20 +231,56 @@
state_grub2_rescue_entry_for_{{{ _RULE_ID }}}
+ {{#- Filter state: matches filenames ending in "rescue.conf".
+ Used by to skip rescue boot entries. -#}}
.*rescue\.conf$
+ {{#- Test "at_least_one_entry_referenced": checks if at least one non-rescue entry
+ contains $kernelopts. Used with negate="true" in the criteria tree to build
+ the implication: "IF entries reference $kernelopts THEN grubenv must have the arg."
+ Reuses the same object as entries_expanded_or_referenced. -#}}
+
+ {{% if numeric_comparison %}}
+ {{#- Test "entries_numeric" (numeric mode only): for entries that have ARG_NAME=,
+ compare the captured integer against the threshold.
+ check_existence="any_exist" — entries using $kernelopts produce no match and
+ that's OK; the grubenv check covers those. -#}}
+
+
+
+
+
+ {{#- Object "obj_entries_numeric": narrow capture — only the digits after ARG_NAME=.
+ Regex: ^options .*ESCAPED_ARG_NAME=(\d+) → group 1 = integer value.
+ Entries without the arg or using $kernelopts produce no item (invisible). -#}}
+
+ /boot/loader/entries/
+ ^.*\.conf$
+ ^options .*{{{ ESCAPED_ARG_NAME }}}=(\d+)
+ 1
+ state_grub2_rescue_entry_for_{{{ _RULE_ID }}}
+
+ {{%- endif %}}
{{% endif %}}
+{{#- 4b. /etc/default/grub (all products)
+ Two GRUB variables to check: GRUB_CMDLINE_LINUX and GRUB_CMDLINE_LINUX_DEFAULT.
+ Pattern match regex: ^\s*GRUB_CMDLINE_LINUX="(.*)"$ → group 1 = full quoted value
+ Numeric regex: ^\s*GRUB_CMDLINE_LINUX=".*ARG=(\d+).*"$ → group 1 = digits only -#}}
{{%- if system_with_kernel_options_in_etc_default_grub %}}
+ {{#- Test "argument": GRUB_CMDLINE_LINUX in /etc/default/grub. -#}}
@@ -159,12 +288,21 @@
+ {{#- Object "argument": captures from GRUB_CMDLINE_LINUX in /etc/default/grub.
+ Pattern match: ^\s*GRUB_CMDLINE_LINUX="(.*)"$ → group 1 = everything inside quotes.
+ Numeric: ^\s*GRUB_CMDLINE_LINUX=".*ESCAPED_ARG_NAME=(\d+).*"$ → digits only. -#}}
/etc/default/grub
+ {{% if numeric_comparison %}}
+ ^\s*GRUB_CMDLINE_LINUX=".*{{{ ESCAPED_ARG_NAME }}}=(\d+).*"$
+ {{% else %}}
^\s*GRUB_CMDLINE_LINUX="(.*)"$
+ {{% endif %}}
1
+ {{#- Test "argument_default": GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub.
+ Used with GRUB_DISABLE_RECOVERY=true (criteria tree requires both). -#}}
@@ -172,15 +310,26 @@
+ {{#- Object "argument_default": same patterns as above but for GRUB_CMDLINE_LINUX_DEFAULT. -#}}
/etc/default/grub
+ {{% if numeric_comparison %}}
+ ^\s*GRUB_CMDLINE_LINUX_DEFAULT=".*{{{ ESCAPED_ARG_NAME }}}=(\d+).*"$
+ {{% else %}}
^\s*GRUB_CMDLINE_LINUX_DEFAULT="(.*)"$
+ {{% endif %}}
1
-{{%- endif %}}
+{{% endif %}}
+{{#- 4c. /etc/default/grub.d/*.cfg drop-in configs (Ubuntu only)
+ Filepath regex: /etc/default/grub.d/[^/]+\.cfg ([^/]+ prevents crossing directories)
+ Same GRUB_CMDLINE_LINUX / _DEFAULT patterns as 4b.
+ Pattern match: captures everything inside the quotes.
+ Numeric: captures only the digits after ARG_NAME=. -#}}
{{% if system_with_kernel_options_in_etc_default_grub_d -%}}
+ {{#- Test "argument_configdir": GRUB_CMDLINE_LINUX in drop-in .cfg files. -#}}
@@ -188,6 +337,7 @@
+ {{#- Test "argument_default_configdir": GRUB_CMDLINE_LINUX_DEFAULT in drop-in .cfg files. -#}}
@@ -195,22 +345,39 @@
+ {{#- Object "argument_configdir": reads GRUB_CMDLINE_LINUX from drop-in .cfg files.
+ Pattern match: group 1 = everything inside the quotes.
+ Numeric: group 1 = digits after ARG_NAME=, so the state can compare as int. -#}}
/etc/default/grub.d/[^/]+\.cfg
+ {{% if numeric_comparison %}}
+ ^\s*GRUB_CMDLINE_LINUX=".*{{{ ESCAPED_ARG_NAME }}}=(\d+).*"$
+ {{% else %}}
^\s*GRUB_CMDLINE_LINUX="(.*)"$
+ {{% endif %}}
1
+ {{#- Object "argument_default_configdir": same as above but for GRUB_CMDLINE_LINUX_DEFAULT. -#}}
/etc/default/grub.d/*.cfg
+ {{% if numeric_comparison %}}
+ ^\s*GRUB_CMDLINE_LINUX_DEFAULT=".*{{{ ESCAPED_ARG_NAME }}}=(\d+).*"$
+ {{% else %}}
^\s*GRUB_CMDLINE_LINUX_DEFAULT="(.*)"$
+ {{% endif %}}
1
-{{%- endif %}}
+{{% endif %}}
-{{%- if system_with_kernel_options_in_grubenv or system_with_expanded_kernel_options_in_loader_entries_or_with_options_in_grubenv %}}
-{{%- macro test_and_object_for_kernel_options_grub_env(base_name, path) %}}
+{{#- 4d. grubenv — GRUB environment block (rhel8, ol8)
+ Macro generates a test+object pair; called once for BIOS, optionally again for UEFI.
+ Pattern match: ^kernelopts=(.*)$ → group 1 = full kernelopts value.
+ Numeric: ^kernelopts=.*ARG_NAME=(\d+) → group 1 = digits only, no $ anchor. -#}}
+{{% if system_with_kernel_options_in_grubenv or system_with_expanded_kernel_options_in_loader_entries_or_with_options_in_grubenv %}}
+ {{%- macro test_and_object_for_kernel_options_grub_env(base_name, path) %}}
+ {{#- Test: check kernelopts line in grubenv at the given path. -#}}
@@ -218,43 +385,72 @@
+ {{#- Object: reads grubenv's "kernelopts=" line.
+ Pattern match: ^kernelopts=(.*)$ → captures everything after "kernelopts=".
+ Numeric: ^kernelopts=.*ARG_NAME=(\d+) → captures digits only; no $ anchor
+ because the arg may appear mid-line. -#}}
{{{ path }}}
+ {{% if numeric_comparison %}}
+ ^kernelopts=.*{{{ ESCAPED_ARG_NAME }}}=(\d+)
+ {{% else %}}
^kernelopts=(.*)$
+ {{% endif %}}
1
-{{%- endmacro %}}
-
-{{{ test_and_object_for_kernel_options_grub_env("grub2_" ~ SANITIZED_ARG_NAME ~ "_argument_grub_env", grub2_boot_path ~ "/grubenv") }}}
-{{% if system_with_bios_and_uefi_support -%}}
-{{{ test_and_object_for_kernel_options_grub_env("grub2_" ~ SANITIZED_ARG_NAME ~ "_argument_grub_env_uefi", grub2_uefi_boot_path ~ "/grubenv") }}}
-{{%- endif %}}
-{{%- endif %}}
-
-{{%- if system_with_expanded_kernel_options_in_loader_entries %}}
-
-
-
-
+ {{%- endmacro %}}
+
+ {{{- test_and_object_for_kernel_options_grub_env("grub2_" ~ SANITIZED_ARG_NAME ~ "_argument_grub_env", grub2_boot_path ~ "/grubenv") }}}
+ {{%- if system_with_bios_and_uefi_support -%}}
+ {{{- test_and_object_for_kernel_options_grub_env("grub2_" ~ SANITIZED_ARG_NAME ~ "_argument_grub_env_uefi", grub2_uefi_boot_path ~ "/grubenv") }}}
+ {{%- endif %}}
+{{% endif %}}
+{{#- 4e. BLS entries — /boot/loader/entries/*.conf (rhel9, rhel10, fedora, ol9)
+ Modern BLS layout: each *.conf has an "options ..." line with kernel args.
+ check="all" + check_existence="all_exist" — every non-rescue entry must match.
+ Pattern match: ^options (.*)$ → group 1 = entire kernel command line.
+ Numeric: ^options .*ARG_NAME=(\d+) → group 1 = digits only. -#}}
+{{% if system_with_expanded_kernel_options_in_loader_entries %}}
+ {{#- Test "entries": every non-rescue BLS entry must pass the state check. -#}}
+
+
+
+
+
+ {{#- Object "obj_entries": scans every *.conf in /boot/loader/entries/.
+ Pattern match: ^options (.*)$ → wide capture; state checks for the arg token.
+ Numeric: ^options .*ESCAPED_ARG_NAME=(\d+) → narrow capture; entries without
+ the arg produce no item and are invisible to the test. -#}}
/boot/loader/entries/
^.*\.conf$
+ {{% if numeric_comparison %}}
+ ^options .*{{{ ESCAPED_ARG_NAME }}}=(\d+)
+ {{% else %}}
^options (.*)$
+ {{% endif %}}
1
state_grub2_rescue_entry_for_{{{ _RULE_ID }}}
+ {{#- Filter state: excludes filenames matching *rescue.conf from the object results. -#}}
.*rescue\.conf$
-{{%- endif %}}
+{{% endif %}}
-{{%- if system_with_expanded_kernel_options_in_grub_cfg %}}
-{{%- macro test_and_object_for_kernel_options_grub_cfg(base_name, path) %}}
+{{#- 4f. grub.cfg — legacy GRUB config (ol7, Ubuntu)
+ Macro generates test+object pair; called once for BIOS, optionally again for UEFI.
+ ol7/Ubuntu regex: ^.*/vmlinuz.*(root=.*)$ → captures from "root=" onward.
+ ol7/Ubuntu numeric: ^.*/vmlinuz.*ARG_NAME=(\d+) → digits only.
+ Other: ^set default_kernelopts=(.*)$ (or numeric variant). -#}}
+{{% if system_with_expanded_kernel_options_in_grub_cfg %}}
+ {{%- macro test_and_object_for_kernel_options_grub_cfg(base_name, path) %}}
+ {{#- Test: check kernel boot line in grub.cfg at the given path. -#}}
@@ -262,24 +458,39 @@
+ {{#- Object: reads grub.cfg; pattern depends on product and comparison mode. -#}}
{{{ path }}}
- {{% if product in ["ol7"] or 'ubuntu' in product %}}
+ {{% if product in ["ol7"] or 'ubuntu' in product %}}
+ {{% if numeric_comparison %}}
+ ^.*/vmlinuz.*{{{ ESCAPED_ARG_NAME }}}=(\d+)
+ {{% else %}}
^.*/vmlinuz.*(root=.*)$
+ {{% endif %}}
+ {{% else %}}
+ {{% if numeric_comparison %}}
+ ^set default_kernelopts=.*{{{ ESCAPED_ARG_NAME }}}=(\d+)
{{% else %}}
^set default_kernelopts=(.*)$
{{% endif %}}
+ {{% endif %}}
1
-{{%- endmacro %}}
+ {{%- endmacro %}}
-{{{ test_and_object_for_kernel_options_grub_cfg("grub2_" + SANITIZED_ARG_NAME + "_argument_grub_cfg", grub2_boot_path ~ "/grub.cfg") }}}
-{{% if system_with_bios_and_uefi_support -%}}
-{{{ test_and_object_for_kernel_options_grub_cfg("grub2_" + SANITIZED_ARG_NAME + "_argument_grub_cfg_uefi", grub2_uefi_boot_path ~ "/grub.cfg") }}}
-{{%- endif %}}
-{{%- endif %}}
+ {{{- test_and_object_for_kernel_options_grub_cfg("grub2_" + SANITIZED_ARG_NAME + "_argument_grub_cfg", grub2_boot_path ~ "/grub.cfg") }}}
+ {{%- if system_with_bios_and_uefi_support -%}}
+ {{{- test_and_object_for_kernel_options_grub_cfg("grub2_" + SANITIZED_ARG_NAME + "_argument_grub_cfg_uefi", grub2_uefi_boot_path ~ "/grub.cfg") }}}
+ {{%- endif %}}
+{{% endif %}}
+{{#- 4g. State "$kernelopts detection" (RHEL8 only): matches options lines containing
+ the $kernelopts variable reference — meaning the real args live in grubenv.
+ Regex: ^(?:.*\s)?\$kernelopts(?:\s.*)?$
+ (?:.*\s)? — optional: preceding args + whitespace (word boundary)
+ \$kernelopts — literal "$kernelopts" (the $ is regex-escaped)
+ (?:\s.*)?$ — optional: whitespace + trailing args -#}}
{{% if system_with_expanded_kernel_options_in_loader_entries_or_with_options_in_grubenv %}}
@@ -287,11 +498,44 @@
{{% endif %}}
-{{% if not ARG_VARIABLE %}}
+{{#- 5. Shared state & variables: branched by (numeric_comparison, ARG_VARIABLE).
+ All non-bootc tests reference the same state ID: state_grub2_{SANITIZED_ARG_NAME}_argument.
+ Each branch defines a state; some also declare external/local variables. -#}}
+
+{{#- 5a. State (numeric mode): captured (\d+) compared as integer.
+ With ARG_VARIABLE → var_ref (XCCDF variable injected at scan time via check-export).
+ With ARG_VALUE → literal integer baked in.
+ external_variable declares the XCCDF variable so OVAL knows about it. -#}}
+{{% if numeric_comparison %}}
+
+ {{% if ARG_VARIABLE %}}
+
+ {{% else %}}
+ {{{ ARG_VALUE }}}
+ {{% endif %}}
+
+ {{% if ARG_VARIABLE %}}
+
+ {{% endif %}}
+{{#- 5b. State (pattern match, literal value): regex checks the arg is a
+ space-delimited token in the captured line.
+ Regex: ^(?:.*\s)?ESCAPED_ARG_NAME_VALUE(?:\s.*)?$
+ (?:.*\s)? — optional preceding args + whitespace (acts as word boundary)
+ ARG=VALUE — literal match (dots escaped)
+ (?:\s.*)?$ — optional trailing args -#}}
+{{% elif not ARG_VARIABLE %}}
^(?:.*\s)?{{{ ESCAPED_ARG_NAME_VALUE }}}(?:\s.*)?$
+{{#- 5c. State (pattern match, XCCDF variable): regex built at scan time via .
+ provides the regex skeleton; splices in
+ the variable's value. IS_SUBSTRING="true" adds \S* pads around the value for
+ substring matching (e.g. slub_debug on ol8).
+ external_variable declares the XCCDF variable (datatype="string" here). -#}}
{{% else %}}
@@ -303,13 +547,13 @@
datatype="string" version="1">
^(?:.*\s)?{{{ ARG_NAME }}}=
- {{% if IS_SUBSTRING == "true" %}}
+ {{% if IS_SUBSTRING == "true" %}}
\S*
- {{% endif %}}
+ {{% endif %}}
- {{% if IS_SUBSTRING == "true" %}}
+ {{% if IS_SUBSTRING == "true" %}}
\S*
- {{% endif %}}
+ {{% endif %}}
(?:\s.*)?$
@@ -317,24 +561,52 @@
{{% endif %}}
+{{#- 6. bootc / RHEL Image Mode (rhel9, rhel10): /usr/lib/bootc/kargs.d/*.toml
+ TOML format: kargs = ["arg1=val1", "arg2=val2", ...]
+ Separate test, object, and state (IDs suffixed with _usr_lib_bootc_kargs_d).
+ The TOML double quotes around each arg act as natural word boundaries. -#}}
{{% if bootable_containers_supported == "true" %}}
+ {{#- Test "bootc": at least one .toml file must contain the arg. -#}}
+ {{#- Object "bootc": scans *.toml files in /usr/lib/bootc/kargs.d/.
+ Pattern match: ^kargs = \[([^\]]+)\]$ → group 1 = bracketed content.
+ Numeric: ^kargs = \[.*"ESCAPED_ARG_NAME=(\d+)".*\]$ → group 1 = digits only.
+ Quotes around the arg in TOML prevent substring false positives. -#}}
/usr/lib/bootc/kargs.d/
^.*\.toml$
+ {{% if numeric_comparison %}}
+ ^kargs = \[.*"{{{ ESCAPED_ARG_NAME }}}=(\d+)".*\]$
+ {{% else %}}
^kargs = \[([^\]]+)\]$
+ {{% endif %}}
1
-{{% if not ARG_VARIABLE %}}
+ {{#- bootc states: same three-way branch as section 5 but with bootc-specific IDs
+ and TOML-adapted patterns (values are wrapped in double quotes). -#}}
+ {{#- bootc state (numeric): compare captured (\d+) as integer. -#}}
+ {{%- if numeric_comparison %}}
+
+ {{% if ARG_VARIABLE %}}
+
+ {{% else %}}
+ {{{ ARG_VALUE }}}
+ {{% endif %}}
+
+ {{#- bootc state (pattern match, literal): check "ARG_NAME_VALUE" appears in TOML array.
+ Regex: ^.*"ESCAPED_ARG_NAME_VALUE".*$ → quotes provide word boundaries. -#}}
+ {{%- elif not ARG_VARIABLE %}}
^.*"{{{ ESCAPED_ARG_NAME_VALUE }}}".*$
-{{% else %}}
+ {{#- bootc state (pattern match, variable): runtime regex via with TOML quotes. -#}}
+ {{%- else %}}
@@ -344,19 +616,19 @@
datatype="string" version="1">
^.*"{{{ ARG_NAME }}}=
- {{% if IS_SUBSTRING == "true" %}}
+ {{% if IS_SUBSTRING == "true" %}}
\S*
- {{% endif %}}
+ {{% endif %}}
- {{% if IS_SUBSTRING == "true" %}}
+ {{% if IS_SUBSTRING == "true" %}}
\S*
- {{% endif %}}
+ {{% endif %}}
".*$
-{{% endif %}}
+ {{%- endif %}}
{{% endif %}}
diff --git a/shared/templates/grub2_bootloader_argument/template.py b/shared/templates/grub2_bootloader_argument/template.py
index a777f04dcf13..b0e3ab9fbecf 100644
--- a/shared/templates/grub2_bootloader_argument/template.py
+++ b/shared/templates/grub2_bootloader_argument/template.py
@@ -1,29 +1,56 @@
import ssg.utils
+VALID_OPERATIONS = {
+ "pattern match",
+ "greater than or equal",
+}
+
def preprocess(data, lang):
+ # arg_value and arg_variable are mutually exclusive
if 'arg_value' in data and 'arg_variable' in data:
raise RuntimeError(
"ERROR: The template should not set both 'arg_value' and 'arg_variable'.\n"
"arg_name: {0}\n"
"arg_variable: {1}".format(data['arg_value'], data['arg_variable']))
- if 'arg_variable' in data:
+ # Fallback to pattern match operation if not set
+ if "operation" not in data:
+ data["operation"] = "pattern match"
+
+ # Placeholder values substituted into tests/*.sh scenarios via
+ # TEST_CORRECT_VALUE / TEST_WRONG_VALUE (e.g. grub2_bootloader_argument_remediation calls)
+ match data["operation"]:
+ case "pattern match":
+ data["test_correct_value"] = "correct_value"
+ data["test_wrong_value"] = "wrong_value"
+ case "greater than or equal":
+ data["test_correct_value"] = "200"
+ data["test_wrong_value"] = "199"
+ case _:
+ raise RuntimeError(
+ f"ERROR: Invalid operation '{data['operation']}' for rule "
+ f"'{data['_rule_id']}'. "
+ f"Must be one of: {sorted(VALID_OPERATIONS)}"
+ )
+
+ # Build ARG_NAME_VALUE ("name=value") used in oval.template comments/metadata,
+ # bash.template remediation, and ansible.template remediation.
+ # When arg_variable is set the value comes from an XCCDF variable at eval time.
+
+ if 'arg_variable' in data or "arg_value" not in data:
data["arg_name_value"] = data["arg_name"]
else:
- if "arg_value" in data:
data["arg_name_value"] = data["arg_name"] + "=" + data["arg_value"]
- else:
- data["arg_name_value"] = data["arg_name"]
if 'is_substring' not in data:
data["is_substring"] = "false"
- if lang == "oval":
- # escape dot, this is used in oval regex
- data["escaped_arg_name_value"] = data["arg_name_value"].replace(".", "\\.")
- data["escaped_arg_name"] = data["arg_name"].replace(".", "\\.")
- # replace . with _, this is used in test / object / state ids
-
+ # OVAL-specific: escape dots for regex patterns in oval.template
+ # (ESCAPED_ARG_NAME_VALUE in state subexpressions, ESCAPED_ARG_NAME in object patterns)
+ data["escaped_arg_name_value"] = data["arg_name_value"].replace(".", "\\.")
+ data["escaped_arg_name"] = data["arg_name"].replace(".", "\\.")
+ # SANITIZED_ARG_NAME: used as component of OVAL IDs (test_grub2__*,
+ # obj_grub2__*, state_grub2__*) and bash bootc .toml filenames
data["sanitized_arg_name"] = ssg.utils.escape_id(data["arg_name"])
return data
diff --git a/shared/templates/grub2_bootloader_argument/tests/arg_not_in_entries.fail.sh b/shared/templates/grub2_bootloader_argument/tests/arg_not_in_entries.fail.sh
index f36c7d8bcd64..908c606a4177 100644
--- a/shared/templates/grub2_bootloader_argument/tests/arg_not_in_entries.fail.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/arg_not_in_entries.fail.sh
@@ -4,8 +4,8 @@
# packages = grub2,grubby
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
{{%- endif %}}
source common.sh
diff --git a/shared/templates/grub2_bootloader_argument/tests/arg_not_in_etcdefaultgrub.fail.sh b/shared/templates/grub2_bootloader_argument/tests/arg_not_in_etcdefaultgrub.fail.sh
index d9da255cc194..977e63cebe32 100644
--- a/shared/templates/grub2_bootloader_argument/tests/arg_not_in_etcdefaultgrub.fail.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/arg_not_in_etcdefaultgrub.fail.sh
@@ -3,8 +3,8 @@
# platform = multi_platform_all
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
{{%- endif %}}
source common.sh
diff --git a/shared/templates/grub2_bootloader_argument/tests/arg_not_in_etcdefaultgrub_recovery_disabled.fail.sh b/shared/templates/grub2_bootloader_argument/tests/arg_not_in_etcdefaultgrub_recovery_disabled.fail.sh
index 8291aaf0294a..3603dbf60091 100644
--- a/shared/templates/grub2_bootloader_argument/tests/arg_not_in_etcdefaultgrub_recovery_disabled.fail.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/arg_not_in_etcdefaultgrub_recovery_disabled.fail.sh
@@ -2,8 +2,8 @@
# platform = multi_platform_all
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
{{%- endif %}}
source common.sh
diff --git a/shared/templates/grub2_bootloader_argument/tests/arg_not_in_grubenv_and_not_referenced.pass.sh b/shared/templates/grub2_bootloader_argument/tests/arg_not_in_grubenv_and_not_referenced.pass.sh
index 59d4ddd5d11b..fb9c98ae7f9a 100644
--- a/shared/templates/grub2_bootloader_argument/tests/arg_not_in_grubenv_and_not_referenced.pass.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/arg_not_in_grubenv_and_not_referenced.pass.sh
@@ -4,8 +4,8 @@
# packages = grub2,grubby
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
{{%- endif %}}
source common.sh
diff --git a/shared/templates/grub2_bootloader_argument/tests/arg_not_in_grubenv_but_referenced.fail.sh b/shared/templates/grub2_bootloader_argument/tests/arg_not_in_grubenv_but_referenced.fail.sh
index 4b5e130626bd..49f287bb1ba2 100644
--- a/shared/templates/grub2_bootloader_argument/tests/arg_not_in_grubenv_but_referenced.fail.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/arg_not_in_grubenv_but_referenced.fail.sh
@@ -3,8 +3,8 @@
# platform = Oracle Linux 8,Red Hat Enterprise Linux 8
# packages = grub2,grubby
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
{{%- endif %}}
source common.sh
diff --git a/shared/templates/grub2_bootloader_argument/tests/arg_value_below_minimal.fail.sh b/shared/templates/grub2_bootloader_argument/tests/arg_value_below_minimal.fail.sh
new file mode 100644
index 000000000000..39f1fad3c852
--- /dev/null
+++ b/shared/templates/grub2_bootloader_argument/tests/arg_value_below_minimal.fail.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+{{% if OPERATION == "pattern match" %}}
+# platform = Not Applicable
+{{% else %}}
+# platform = multi_platform_all
+{{% endif %}}
+{{%- if 'ubuntu' in product %}}
+# packages = grub2
+{{%- else %}}
+# packages = grub2,grubby
+{{%- endif %}}
+{{%- if ARG_VARIABLE %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{% endif %}}
+
+source common.sh
+
+{{{ grub2_bootloader_argument_remediation(ARG_NAME, ARG_NAME ~ "=" ~ TEST_WRONG_VALUE) }}}
diff --git a/shared/templates/grub2_bootloader_argument/tests/arg_value_meets_minimal.pass.sh b/shared/templates/grub2_bootloader_argument/tests/arg_value_meets_minimal.pass.sh
new file mode 100644
index 000000000000..3adf2a8268cb
--- /dev/null
+++ b/shared/templates/grub2_bootloader_argument/tests/arg_value_meets_minimal.pass.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+{{% if OPERATION == "pattern match" %}}
+# platform = Not Applicable
+{{% else %}}
+# platform = multi_platform_all
+{{% endif %}}
+{{%- if 'ubuntu' in product %}}
+# packages = grub2
+{{%- else %}}
+# packages = grub2,grubby
+{{%- endif %}}
+{{%- if ARG_VARIABLE %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{% endif %}}
+
+source common.sh
+
+{{{ grub2_bootloader_argument_remediation(ARG_NAME, ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE) }}}
diff --git a/shared/templates/grub2_bootloader_argument/tests/correct_recovery_disabled.pass.sh b/shared/templates/grub2_bootloader_argument/tests/correct_recovery_disabled.pass.sh
index e6d17a7e2c8e..7facadcd6be7 100644
--- a/shared/templates/grub2_bootloader_argument/tests/correct_recovery_disabled.pass.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/correct_recovery_disabled.pass.sh
@@ -7,8 +7,8 @@
# packages = grub2,grubby
{{%- endif %}}
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
{{%- endif %}}
source common.sh
diff --git a/shared/templates/grub2_bootloader_argument/tests/correct_value_etcdefault_dir_noupdate.fail.sh b/shared/templates/grub2_bootloader_argument/tests/correct_value_etcdefault_dir_noupdate.fail.sh
index da3053c291a7..4785331a4abb 100644
--- a/shared/templates/grub2_bootloader_argument/tests/correct_value_etcdefault_dir_noupdate.fail.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/correct_value_etcdefault_dir_noupdate.fail.sh
@@ -4,8 +4,8 @@
# packages = grub2
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
{{%- endif %}}
# Clean up
diff --git a/shared/templates/grub2_bootloader_argument/tests/correct_value_grubenv_only.pass.sh b/shared/templates/grub2_bootloader_argument/tests/correct_value_grubenv_only.pass.sh
index dc6f7e6119a7..7a166e4b2493 100644
--- a/shared/templates/grub2_bootloader_argument/tests/correct_value_grubenv_only.pass.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/correct_value_grubenv_only.pass.sh
@@ -3,8 +3,8 @@
# platform = Oracle Linux 8,Red Hat Enterprise Linux 8
# packages = grub2,grubby
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
{{%- endif %}}
source common.sh
diff --git a/shared/templates/grub2_bootloader_argument/tests/correct_value_mix_entries_and_grubenv.pass.sh b/shared/templates/grub2_bootloader_argument/tests/correct_value_mix_entries_and_grubenv.pass.sh
index 3b3687f453ca..0e5611ab6a30 100644
--- a/shared/templates/grub2_bootloader_argument/tests/correct_value_mix_entries_and_grubenv.pass.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/correct_value_mix_entries_and_grubenv.pass.sh
@@ -3,8 +3,8 @@
# platform = Oracle Linux 8,Red Hat Enterprise Linux 8
# packages = grub2,grubby
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
{{%- endif %}}
source common.sh
diff --git a/shared/templates/grub2_bootloader_argument/tests/correct_value_noupdate.fail.sh b/shared/templates/grub2_bootloader_argument/tests/correct_value_noupdate.fail.sh
index 380353886a81..394fd2d82b92 100644
--- a/shared/templates/grub2_bootloader_argument/tests/correct_value_noupdate.fail.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/correct_value_noupdate.fail.sh
@@ -3,8 +3,8 @@
# platform = multi_platform_all
# packages = grub2
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
{{%- endif %}}
source common.sh
diff --git a/shared/templates/grub2_bootloader_argument/tests/correct_value_remediated.pass.sh b/shared/templates/grub2_bootloader_argument/tests/correct_value_remediated.pass.sh
index d3c822e36fc0..c45618ae9b58 100644
--- a/shared/templates/grub2_bootloader_argument/tests/correct_value_remediated.pass.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/correct_value_remediated.pass.sh
@@ -7,8 +7,8 @@
# packages = grub2,grubby
{{%- endif %}}
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
{{%- endif %}}
source common.sh
diff --git a/shared/templates/grub2_bootloader_argument/tests/correct_value_substring_left.pass.sh b/shared/templates/grub2_bootloader_argument/tests/correct_value_substring_left.pass.sh
index 7bf115155c3b..2f0cce75988e 100644
--- a/shared/templates/grub2_bootloader_argument/tests/correct_value_substring_left.pass.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/correct_value_substring_left.pass.sh
@@ -11,8 +11,8 @@
{{%- endif %}}
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
{{%- endif %}}
{{%- set ARG_NAME_VALUE= ARG_NAME_VALUE ~ "A" %}}
diff --git a/shared/templates/grub2_bootloader_argument/tests/correct_value_substring_right.pass.sh b/shared/templates/grub2_bootloader_argument/tests/correct_value_substring_right.pass.sh
index dc2440d7f6bd..aa22ca1c0558 100644
--- a/shared/templates/grub2_bootloader_argument/tests/correct_value_substring_right.pass.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/correct_value_substring_right.pass.sh
@@ -11,8 +11,8 @@
{{%- endif %}}
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
{{%- endif %}}
{{%- set ARG_NAME_VALUE = (ARG_NAME_VALUE | replace("=","=A")) %}}
diff --git a/shared/templates/grub2_bootloader_argument/tests/invalid_rescue.pass.sh b/shared/templates/grub2_bootloader_argument/tests/invalid_rescue.pass.sh
index c6d5b6b1bacc..1f9d9f6afb9b 100644
--- a/shared/templates/grub2_bootloader_argument/tests/invalid_rescue.pass.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/invalid_rescue.pass.sh
@@ -3,8 +3,8 @@
# platform = Red Hat Enterprise Linux 9,Red Hat Enterprise Linux 10,multi_platform_fedora
# packages = grub2,grubby
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
{{%- endif %}}
source common.sh
diff --git a/shared/templates/grub2_bootloader_argument/tests/wrong_value_entries.fail.sh b/shared/templates/grub2_bootloader_argument/tests/wrong_value_entries.fail.sh
index 788f128b3973..67bbcf574597 100644
--- a/shared/templates/grub2_bootloader_argument/tests/wrong_value_entries.fail.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/wrong_value_entries.fail.sh
@@ -3,9 +3,9 @@
# platform = multi_platform_fedora,multi_platform_rhel
# packages = grub2,grubby
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
-{{%- set ARG_NAME_VALUE_WRONG= ARG_NAME ~ "=wrong_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
+{{%- set ARG_NAME_VALUE_WRONG= ARG_NAME ~ "=" ~ TEST_WRONG_VALUE %}}
{{%- else %}}
{{%- set ARG_NAME_VALUE_WRONG= "wrong_variable" %}}
{{%- endif %}}
diff --git a/shared/templates/grub2_bootloader_argument/tests/wrong_value_etcdefault.fail.sh b/shared/templates/grub2_bootloader_argument/tests/wrong_value_etcdefault.fail.sh
index b2ab149053bb..d6e89664a018 100644
--- a/shared/templates/grub2_bootloader_argument/tests/wrong_value_etcdefault.fail.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/wrong_value_etcdefault.fail.sh
@@ -9,9 +9,9 @@
{{%- endif %}}
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
-{{%- set ARG_NAME_VALUE_WRONG= ARG_NAME ~ "=wrong_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
+{{%- set ARG_NAME_VALUE_WRONG= ARG_NAME ~ "=" ~ TEST_WRONG_VALUE %}}
{{%- else %}}
{{%- set ARG_NAME_VALUE_WRONG= "wrong_variable" %}}
{{%- endif %}}
diff --git a/shared/templates/grub2_bootloader_argument/tests/wrong_value_etcdefault_dir.fail.sh b/shared/templates/grub2_bootloader_argument/tests/wrong_value_etcdefault_dir.fail.sh
index 514b8006e4d8..2c1f3c10d7ab 100644
--- a/shared/templates/grub2_bootloader_argument/tests/wrong_value_etcdefault_dir.fail.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/wrong_value_etcdefault_dir.fail.sh
@@ -4,8 +4,8 @@
# packages = grub2
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
{{%- endif %}}
# Clean up and make sure we are at a passing state
@@ -15,5 +15,5 @@ echo "GRUB_CMDLINE_LINUX=\"{{{ ARG_NAME_VALUE }}}\"" > /etc/default/grub.d/custo
{{{ grub_command("update") }}}
# Set to wrong var/value
-echo "GRUB_CMDLINE_LINUX=\"\$GRUB_CMDLINE_LINUX {{{ ARG_NAME }}}=wrong_value\"" > /etc/default/grub.d/custom.cfg
+echo "GRUB_CMDLINE_LINUX=\"\$GRUB_CMDLINE_LINUX {{{ ARG_NAME }}}={{{ TEST_WRONG_VALUE }}}\"" > /etc/default/grub.d/custom.cfg
diff --git a/shared/templates/grub2_bootloader_argument/tests/wrong_value_etcdefaultgrub_recovery_disabled.fail.sh b/shared/templates/grub2_bootloader_argument/tests/wrong_value_etcdefaultgrub_recovery_disabled.fail.sh
index e7266d6c7af0..d6a003b87006 100644
--- a/shared/templates/grub2_bootloader_argument/tests/wrong_value_etcdefaultgrub_recovery_disabled.fail.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/wrong_value_etcdefaultgrub_recovery_disabled.fail.sh
@@ -2,9 +2,9 @@
# platform = multi_platform_all
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
-{{%- set ARG_NAME_VALUE_WRONG= ARG_NAME ~ "=wrong_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
+{{%- set ARG_NAME_VALUE_WRONG= ARG_NAME ~ "=" ~ TEST_WRONG_VALUE %}}
{{%- else %}}
{{%- set ARG_NAME_VALUE_WRONG= "wrong_variable" %}}
{{%- endif %}}
diff --git a/shared/templates/grub2_bootloader_argument/tests/wrong_value_grubenv.fail.sh b/shared/templates/grub2_bootloader_argument/tests/wrong_value_grubenv.fail.sh
index d17a4d81b2ff..224aab46b00c 100644
--- a/shared/templates/grub2_bootloader_argument/tests/wrong_value_grubenv.fail.sh
+++ b/shared/templates/grub2_bootloader_argument/tests/wrong_value_grubenv.fail.sh
@@ -4,9 +4,9 @@
# packages = grub2,grubby
{{%- if ARG_VARIABLE %}}
-# variables = {{{ ARG_VARIABLE }}}=correct_value
-{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=correct_value" %}}
-{{%- set ARG_NAME_VALUE_WRONG= ARG_NAME ~ "=wrong_value" %}}
+# variables = {{{ ARG_VARIABLE }}}={{{ TEST_CORRECT_VALUE }}}
+{{%- set ARG_NAME_VALUE= ARG_NAME ~ "=" ~ TEST_CORRECT_VALUE %}}
+{{%- set ARG_NAME_VALUE_WRONG= ARG_NAME ~ "=" ~ TEST_WRONG_VALUE %}}
{{%- else %}}
{{%- set ARG_NAME_VALUE_WRONG= "wrong_variable" %}}
{{%- endif %}}