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 `` and add a comment in your security policy explaining the compensating control.
The goal is not 100% pass rate; it is 100% justified pass-or-deviation. Auditors accept documented exceptions; they do not accept silent ignores.
## Combining With Image Builds
Bake OpenSCAP into your image-build pipeline so every image rolls out compliant. With Image Builder on RHEL or Packer on AlmaLinux, run the remediation as a provisioning step:
“`bash
oscap xccdf eval –remediate \
–profile xccdf_org.ssgproject.content_profile_cis \
/usr/share/xml/scap/ssg/content/ssg-almalinux9-ds.xml || true
“`
Then run the scan again and fail the build if the pass rate is below your threshold. New systems boot already at 95%+ compliance, and the production drift problem largely goes away.
## Mapping CIS to Other Frameworks
The CIS Benchmark rules include cross-references to NIST 800-53, ISO 27001, PCI DSS, and HIPAA controls. Extract the cross-references from the SCAP content and you get a one-to-many compliance matrix: a single rule pass satisfies multiple framework requirements. This matrix is auditor catnip — instead of separately mapping every Linux configuration to every framework, you map once to CIS and inherit the others.
## Limitations
OpenSCAP scans the running system; it does not catch issues in code or workloads. A perfectly hardened host running a vulnerable application is still vulnerable. Use OpenSCAP as one layer among many — vulnerability scanning, application security testing, and runtime detection complete the picture. Also note that many checks are static configuration tests, not dynamic behavior tests, so a host that passes today can be misconfigured tomorrow if drift detection is not in place.
## Long-Term Maintenance
The SCAP Security Guide gets monthly updates with new rules, fixed false positives, and updated remediation. Subscribe to the GitHub releases and bump the package quarterly. When a new RHEL major version drops, the CIS profile usually trails by a few months — plan ahead and run the previous major’s profile until the new content lands. Document the version of SSG and OpenSCAP your scans use; auditors occasionally ask, especially for FedRAMP and DoD-adjacent assessments.
Was this article helpful?