Remediation Guides

Ensure gpgcheck Is Globally Activated: How to Fix It on RHEL, Rocky, AlmaLinux and Oracle Linux

26 September 2026 8 min read

“Ensure gpgcheck is globally activated” is a CIS check that fails when DNF or YUM may install RPM packages without verifying their GPG signatures. To fix it, set gpgcheck=1 in the [main] section of /etc/dnf/dnf.conf (/etc/yum.conf on RHEL 7), change every gpgcheck=0 in /etc/yum.repos.d/ to 1, and import missing repository keys with rpm –import.

Order matters. If you flip the flag on a repository whose signing key is not trusted yet, the next update from that repository fails. Import keys first, then enable the check.

What the scanner is actually detecting

This is a configuration item from Tenable’s CIS audit files for the RHEL family, run over an authenticated SSH session as part of a compliance scan. It reports PASSED or FAILED. The audit text describes the gpgcheck option in the main section of /etc/dnf/dnf.conf and in the individual /etc/yum.repos.d/* files, and its remediation asks you to set gpgcheck=1 in [main] and set every gpgcheck line in the repository files to 1. So the item fails when the main value is missing or not 1, or when any repository file turns the check off.

The item number differs by benchmark, so search your report by title:

Tenable audit (CIS benchmark) Item title
CIS Rocky Linux 9 v2.0.0 L1 Server 1.2.1.2 Ensure gpgcheck is globally activated
CIS AlmaLinux OS 9 v2.0.0 L1 Server 1.2.1.2 Ensure gpgcheck is globally activated
CIS Oracle Linux 9 v2.0.0 L1 Server 1.2.1.2 Ensure gpgcheck is globally activated
CIS Red Hat EL8 Server L1 v2.0.0 1.2.3 Ensure gpgcheck is globally activated – dnf.conf and 1.2.3 … – /etc/yum.repos.d/*
CIS Red Hat Enterprise Linux 7 STIG v2.0.0 L1 Server 1.2.3 Ensure gpgcheck is globally activated (checks /etc/yum.conf)

Some audits split the item into two results, one for the main file and one for the repository directory, so one host can show one pass and one failure. Two neighbouring items are different controls: “Ensure GPG keys are configured” (a manual review of trusted keys) and the Level 2 item “Ensure repo_gpgcheck is globally activated”, which covers signatures on repository metadata rather than on packages.

Real-world risk, stated honestly

With gpgcheck on, DNF refuses to install a package unless its signature verifies against a key imported into the RPM database. With it off for a repository, DNF installs whatever that repository serves. Package scriptlets run as root, so a substituted package means root code execution on every host that updates from it.

Exploiting that requires control over what the repository delivers: a compromised mirror or internal repository server, write access to a shared repository directory, or a network position against a plain HTTP baseurl. HTTPS helps against the last case but not against a compromised server. The signature is what ties a package to its publisher.

This is not remotely exploitable on its own and exposes nothing on the network. In most fleets the failure traces back to one third-party or internal repository, not to the distribution repositories.

How to confirm it on the host

# Main section (RHEL 8 and later family)
grep -Ei '^s*gpgchecks*=' /etc/dnf/dnf.conf

# RHEL 7, CentOS 7, Oracle Linux 7
grep -Ei '^s*gpgchecks*=' /etc/yum.conf

# Repository files that turn the check off (any spacing, 0/no/false/off)
sudo grep -rEin '^s*gpgchecks*=s*(0|no|false|off)s*$' /etc/yum.repos.d/

# Effective value per repository as DNF sees it (needs dnf-plugins-core)
sudo dnf config-manager --dump '*' | grep -E '^[|^gpgcheck '

The simple grep -rl gpgcheck=0 /etc/yum.repos.d/ misses variants DNF also accepts as false, such as gpgcheck = 0 or gpgcheck=False. The dump is the ground truth: it lists every defined repository, enabled or not, and each should show gpgcheck = 1. A repository with no gpgcheck line inherits the [main] value, because DNF uses [main] as the default that each repository can override.

How to fix it

Step 1: back up outside the repository directory

sudo cp -a /etc/dnf/dnf.conf /root/dnf.conf.bak      # /etc/yum.conf on RHEL 7
sudo tar -czf /root/yum.repos.d-backup.tgz -C /etc yum.repos.d

Do not leave .bak copies inside /etc/yum.repos.d/. DNF ignores them, but a check that reads every file in the directory may not.

Step 2: import each yum repository GPG key

# Keys RPM already trusts
rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}t%{SUMMARY}n'

# Key files shipped by the OS and by *-release packages
ls /etc/pki/rpm-gpg/

# Check a vendor key's fingerprint against the one the vendor publishes, then import it
gpg --show-keys /etc/pki/rpm-gpg/RPM-GPG-KEY-vendor
sudo rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-vendor

Point each repository at its key so DNF knows which one to use:

[vendor-repo]
name=Vendor packages
baseurl=https://repo.example.com/el9/$basearch/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-vendor

If an internal repository holds unsigned packages, the durable fix is to sign them at build time (rpmsign –addsign from the rpm-sign package) and distribute the public key. Enabling gpgcheck before that happens will break the repository.

Step 3: set gpgcheck=1 in [main]

RHEL, Rocky Linux, AlmaLinux and Oracle Linux 8 and 9 (the first command is the benchmark’s own remediation):

sudo sed -i 's/^gpgchecks*=s*.*/gpgcheck=1/' /etc/dnf/dnf.conf
grep -Eq '^s*gpgchecks*=' /etc/dnf/dnf.conf || sudo sed -i '/^[main]/a gpgcheck=1' /etc/dnf/dnf.conf

The second line adds the setting if it is missing, because DNF’s built-in default for gpgcheck is False. On RHEL 7, run the same two commands against /etc/yum.conf.

On RHEL 8 and later, /etc/yum.conf is a symlink to /etc/dnf/dnf.conf. GNU sed -i replaces a symlink with a regular file unless you pass –follow-symlinks, so a script written for RHEL 7 quietly splits the two files. Edit /etc/dnf/dnf.conf directly.

Step 4: fix the repository files

# One file at a time, after its key is imported
sudo sed -i -E 's/^s*gpgchecks*=s*(0|no|false|off)s*$/gpgcheck=1/I' /etc/yum.repos.d/vendor.repo

# Or by repository ID
sudo dnf config-manager --save --setopt=vendor-repo.gpgcheck=1

The benchmark’s bulk version rewrites every gpgcheck line in every .repo file at once. Use it only after Step 2 has covered every repository:

sudo find /etc/yum.repos.d/ -name "*.repo" -exec echo "Checking:" {} ; -exec sed -i 's/^gpgchecks*=s*.*/gpgcheck=1/' {} ;

Do not hand-edit /etc/yum.repos.d/redhat.repo. Its repositories are generated by subscription-manager, and the config-manager documentation says to manage them with subscription-manager instead. Look for an override that disables the check and remove it:

sudo subscription-manager repo-override --repo=REPO_ID --list
sudo subscription-manager repo-override --repo=REPO_ID --remove=gpgcheck

On Satellite-managed hosts, custom repositories get their key from Satellite: add the signing key as a content credential of type GPG Key and assign it there, rather than editing each host.

How to verify the fix and rescan

grep -Ei '^s*gpgchecks*=' /etc/dnf/dnf.conf                                    # gpgcheck=1
sudo grep -rEil '^s*gpgchecks*=s*(0|no|false|off)s*$' /etc/yum.repos.d/   # no output
sudo dnf config-manager --dump '*' | grep -E '^[|^gpgcheck '                   # gpgcheck = 1 everywhere

# Prove signatures verify, without changing the system
sudo dnf clean all
sudo dnf reinstall --downloadonly -y PACKAGE_FROM_THAT_REPO

With –downloadonly, DNF still runs its signature check on the downloaded packages before stopping. Run it once for each repository you changed. A failure ends with “GPG check FAILED”. Then rerun the same compliance scan with the same audit file; the item should move to PASSED.

What can break and how to roll back

  • Unsigned packages: DNF reports “Package … is not signed” and aborts the whole transaction, so one unsigned package can stop an entire patch run.
  • Keys not imported: interactive runs prompt to import the key from gpgkey. Unattended runs without -y refuse (“Refusing to automatically import keys when running unattended”). Pre-import keys with rpm –import so cron jobs and automation do not stall.
  • Key rotation: when a vendor signs with a new key, updates fail with “Public key for … is not installed” until you import it.

To roll back, restore the backups:

sudo cp -a /root/dnf.conf.bak /etc/dnf/dnf.conf
sudo tar -xzf /root/yum.repos.d-backup.tgz -C /etc

If one repository genuinely cannot be signed yet, set gpgcheck=0 in that repository only and record it as a documented exception. The CIS item will keep failing for that host, which is accurate.

Common false positive reasons

  • Leftover files in /etc/yum.repos.d/. .bak, .rpmsave or .rpmnew copies are not loaded by DNF, but can still contain gpgcheck=0 and trip a check that reads every file. Move them out.
  • Non-literal true values. DNF treats yes, true and on as enabled, but an audit expecting 1 may not. Write gpgcheck=1 exactly.
  • Disabled repositories. A gpgcheck=0 line in a repository with enabled=0 still fails. It is low risk until someone enables it, so fix it anyway.
  • The scan never really ran. If SSH login or privilege escalation failed, the whole audit is unreliable. Check the setup in our guide to Linux authenticated scans with SSH and sudo.

FAQ

Does gpgcheck=1 in dnf.conf override gpgcheck=0 in a .repo file?

No. The [main] value is only a default. A gpgcheck line in a repository section overrides it for that repository, which is why the audit inspects both places.

What is the difference between gpgcheck, repo_gpgcheck and localpkg_gpgcheck?

gpgcheck verifies packages from repositories, repo_gpgcheck verifies repository metadata, and localpkg_gpgcheck verifies RPM files you install from disk. This finding covers only gpgcheck.

Is dnf –nogpgcheck safe for a one-off install?

It skips signature checks for that command only, if RPM policy allows. The scan will not notice, but it defeats the control, so treat it as an emergency measure.

Does this setting affect rpm -i?

No. rpm does not read dnf.conf. Direct rpm installs follow RPM’s own verification policy, set by the %_pkgverify_level macro.

Tracking this finding across many hosts

The finding tends to come back when a vendor installer or a developer drops a new .repo file with gpgcheck=0 months after the fleet was fixed. If you use SITEY, you can upload the .nessus export from the compliance scan, let its AI draft a host-specific remediation script that runs only after a human approves it, deploy it through SITEY agents on Linux endpoints, and have SITEY re-test to verify the finding is closed. Duplicate findings are merged per scanner, not across scanners.

Sources

SITEY closes the loop, not just the report.Discover, validate, fix and verify in your own infrastructure.

See pricing