Press ESC to close Press / to search

OpenSCAP Automated CIS Benchmark Compliance Scanning on RHEL 9 in 2026

Compliance auditors no longer accept “we ran a hardening script once.” They expect continuous, automated,...

Security Tools Linux Open Source

Compliance auditors no longer accept “we ran a hardening script once.” They expect continuous, automated, evidenced scanning against a recognized benchmark — and for RHEL-family systems that benchmark is almost always the CIS Red Hat Enterprise Linux Benchmark. OpenSCAP, maintained by Red Hat and the SCAP Security Guide project, is the NIST-certified scanner built for exactly this. It ingests SCAP content, scans the running system against every rule, and produces human- and machine-readable reports you can drop straight into your audit evidence folder. In 2026, with SSG 0.1.76 and OpenSCAP 1.4, you can automate CIS compliance scanning across a fleet of RHEL 9 (and AlmaLinux, Rocky) hosts in an afternoon. This guide walks through setup, profiles, remediation, and scheduling.

## What You Get Out of the Box

The `scap-security-guide` package ships profiles for multiple benchmarks on RHEL 9: CIS Level 1 Server, CIS Level 2 Server, CIS Workstation, PCI DSS 4.0, HIPAA, DISA STIG, ANSSI BP-028, Australian ACSC ISM, and more. Each profile is a bundle of XCCDF rules tied to OVAL definitions that OpenSCAP evaluates against the running system.

## Installing OpenSCAP

On RHEL 9, AlmaLinux 9, or Rocky 9:

“`bash
sudo dnf install -y openscap-scanner scap-security-guide openscap-utils
“`

Confirm the CIS profile is present:

“`bash
sudo oscap info /usr/share/xml/scap/ssg/content/ssg-almalinux9-ds.xml | grep -i cis
“`

You should see `xccdf_org.ssgproject.content_profile_cis` for Level 1 Server and `xccdf_org.ssgproject.content_profile_cis_server_l2` for Level 2.

## Running Your First Scan

Evaluate the host against CIS Level 1:

“`bash
sudo oscap xccdf eval \
–profile xccdf_org.ssgproject.content_profile_cis \
–results /var/log/scap/results-$(hostname)-$(date +%F).xml \
–report /var/log/scap/report-$(hostname)-$(date +%F).html \
/usr/share/xml/scap/ssg/content/ssg-almalinux9-ds.xml
“`

On a default AlmaLinux 9 install, expect 40–60% of rules to fail. That is normal — the default install is not hardened. The HTML report shows each rule, its CIS section, severity, and what to do about it.

## Reading the Report

Open the HTML report in a browser. It is grouped by rule with a color-coded pass/fail/notapplicable indicator. Three sections you will care about:

– **High severity failures**: fix these first. Examples: no password for single-user mode, world-writable files in `/etc`, SSH root login enabled.
– **Medium severity failures**: fix in the next maintenance window.
– **Unchecked rules**: often because a package (auditd, aide) is not installed. Installing the package flips them to checked.

Each rule has an “Identifiers and References” block linking back to the CIS section and the specific NIST 800-53 controls, which makes audit mapping trivial.

## Automated Remediation

OpenSCAP generates Ansible playbooks, Bash scripts, or runtime remediation commands for most rules. Generate an Ansible playbook that applies the CIS profile:

“`bash
sudo oscap xccdf generate fix \
–profile xccdf_org.ssgproject.content_profile_cis \
–fix-type ansible \
/usr/share/xml/scap/ssg/content/ssg-almalinux9-ds.xml \
> cis-remediate.yml
“`

Read it carefully before running. A few rules disable services you may actually use (rsync daemon, FTP, NIS). Comment those out of the playbook, then run against your fleet:

“`bash
ansible-playbook -i production cis-remediate.yml -l cde –check
ansible-playbook -i production cis-remediate.yml -l cde
“`

After remediation, re-scan and compare reports. You should see compliance jump from ~50% to 90%+ on the first pass.

## Tailoring a Custom Profile

You will have controls you cannot or should not implement verbatim. Rather than ignoring failures, document deviations by tailoring a custom profile that extends CIS:

“`bash
sudo dnf install -y scap-workbench
scap-workbench
“`

Or tailor from CLI:

“`bash
sudo oscap xccdf generate customization \
–profile xccdf_org.ssgproject.content_profile_cis \
/usr/share/xml/scap/ssg/content/ssg-almalinux9-ds.xml \
> tailoring.xml
“`

Edit `tailoring.xml` to disable specific rules with justification, then scan with `–tailoring-file tailoring.xml`. The scan report now reflects your policy, not the upstream default.

## Scheduling Scans

Drop a systemd timer so the scan runs weekly and reports land in a durable location:

“`ini
# /etc/systemd/system/oscap-scan.service
[Unit]
Description=Weekly SCAP CIS scan
After=network-online.target

[Service]
Type=oneshot
ExecStart=/bin/bash -c ‘mkdir -p /var/log/scap && oscap xccdf eval –profile xccdf_org.ssgproject.content_profile_cis –results /var/log/scap/results-$(date +\%%F).xml –report /var/log/scap/report-$(date +\%%F).html /usr/share/xml/scap/ssg/content/ssg-almalinux9-ds.xml’
“`

“`ini
# /etc/systemd/system/oscap-scan.timer
[Unit]
Description=Weekly SCAP scan timer

[Timer]
OnCalendar=Sun 04:00
Persistent=true

[Install]
WantedBy=timers.target
“`

Enable with `sudo systemctl enable –now oscap-scan.timer`.

## Central Reporting with ARF

The XML results file is in ARF (Asset Reporting Format), machine-readable for ingestion into compliance dashboards. Collect them centrally:

“`bash
rsync -a /var/log/scap/ compliance-host:/srv/scap/$(hostname)/
“`

Ingest into Foreman/Katello’s OpenSCAP plugin, Red Hat Insights, or a custom script that feeds Elasticsearch.

## Scanning Containers and Images

OpenSCAP can scan container images offline with `oscap-podman`:

“`bash
sudo dnf install -y openscap-utils
sudo oscap-podman almalinux:9 xccdf eval \
–profile xccdf_org.ssgproject.content_profile_cis \
–report container-report.html \
/usr/share/xml/scap/ssg/content/ssg-almalinux9-ds.xml
“`

Add this to your CI pipeline to fail builds that regress compliance.

## Integrating with Ansible at Install Time

For new systems, install with a Kickstart file that applies CIS during the initial build:

“`
%addon org_fedora_oscap
content-type = scap-security-guide
profile = xccdf_org.ssgproject.content_profile_cis
%end
“`

The installer runs the oscap remediation at first boot, producing a compliant system from the start rather than remediating after deployment.

## Reviewing Drift

Over time, systems drift as admins make changes. Compare weekly scan results with `oscap xccdf compare` or by ingesting ARF into a database and tracking pass rate per host per rule over time. Drift that lowers the pass rate should trigger an alert.

## FAQ

**Does OpenSCAP work on Ubuntu?** There is a Ubuntu SSG profile set but Canonical-supported content is much less complete. For Ubuntu, consider Ubuntu Security Guide (USG).

**Will the CIS remediation break my system?** It can. Review the playbook before running, test in staging, and avoid fully automated application to production without a safety net.

**What is the difference between CIS and DISA STIG profiles?** Both are hardening baselines but STIG is DoD-specific and somewhat stricter on audit rules and banners. Most commercial orgs use CIS; government uses STIG.

**Can I use OpenSCAP for PCI DSS evidence?** Yes. The `pci-dss` profile maps rules directly to PCI DSS requirements and the report is auditor-friendly.

**Does Red Hat Insights replace this?** Insights layers on top and provides a SaaS dashboard for the same SCAP data. OpenSCAP is the engine; Insights is presentation.

**How long does a scan take?** Typically 2–10 minutes per host depending on how many rules are evaluated and system performance. CIS Level 2 takes longer than Level 1 because it includes more file integrity checks.

**Can I run OpenSCAP from a CI pipeline against an image?** Yes — `oscap-podman` and `oscap-vm` scan container images and VM disk images respectively without needing to boot them.

**What is the difference between SCAP, OVAL, and XCCDF?** SCAP is the umbrella protocol, XCCDF is the rule format, and OVAL is the language describing what to check on a system. Together they make scans portable across scanners.

## Tying Scans Into Ansible

The most maintainable pattern is wrapping OpenSCAP scanning into an Ansible role. The role installs the package, copies the tailoring file, runs the scan, and ships the results to a central location:

“`yaml
– name: Install scap tooling
dnf:
name:
– openscap-scanner
– scap-security-guide
state: present

– name: Run CIS scan
command: >
oscap xccdf eval
–profile xccdf_org.ssgproject.content_profile_cis
–tailoring-file /etc/scap/tailoring.xml
–results /var/log/scap/results.xml
–report /var/log/scap/report.html
/usr/share/xml/scap/ssg/content/ssg-almalinux9-ds.xml
register: scap_result
changed_when: false
failed_when: scap_result.rc not in [0, 2]

– name: Fetch results
fetch:
src: /var/log/scap/results.xml
dest: ./scap-results/{{ inventory_hostname }}.xml
flat: yes
“`

Run this nightly through AWX and you have continuous compliance evidence with no per-host effort.

## Comparing Scans Over Time

OpenSCAP results are XML, so diffing two scans against each other is straightforward. Build a small script that extracts the pass/fail per rule and compares week over week. New failures (regressions) are tickets; new passes (improvements) are wins to celebrate. Trending the overall pass rate as a single metric over time gives leadership a clear “compliance score” to track.

## Tailoring for Real Environments

The default CIS profile inevitably includes rules that conflict with your operational reality. Examples: disabling cron access for non-admins (you have a build user that needs cron), enforcing umask 077 (your shared directories need 027), removing rsh (you actually use it for some legacy backup process). For each, document the deviation in the tailoring file with a `