Handbook sections▾
Foundations
Understanding the threats to a Linux hostWhy we hardenThe defense principles behind every ruleEffective configuration: the truth no file holdsThe standards Pavois maps toSOCLE control ID modelEvidence & exportsHow the A-E grade is computedWhat a PASS proves: the qualified verdictTrust model for the evidence bundleIs SOCLE just your own norm? (governance & the circularity question)What Pavois covers, and what it doesn'tDomains
Hardening SSHHardening PAMMandatory Access Control (SELinux / AppArmor)Hardening the host firewallHardening sudoFile Permissions & OwnershipMount & filesystem hardeningHardening kernel modulesHardening the kernel & network with sysctlAudit logging with auditdHardening logging with journald and rsyslogHardening systemd servicesPackage hygieneHardening the bootloader (GRUB)Synchronizing timeLogin banners and MOTDControlling cron and at accessHardening the GNOME desktop (dconf)Tooling
Undo a hardening run: restore pointsOperating Pavois: privileges, air-gap, timing, exceptionsRun Pavois in CI (GitHub Actions)Feature status: delivered, partial, roadmapGovernance: licence, versioning, provenance, securityHardening the bootloader (GRUB)
Last reviewed
GRUB runs before the OS and before any OS-level control. Protect it with a password, lock down grub.cfg, and pass hardening flags on the kernel command line.
The threat: an editable boot prompt is unauthenticated root
The bootloader runs before the operating system: before logins, before sudo, before SELinux or AppArmor, before any control you configured. Anyone at the console or with physical access can interrupt GRUB, press e to edit a boot entry, and rewrite the kernel command line. The classic moves are appending single (or 1) to drop into single-user mode, or init=/bin/bash to replace init with a shell: both yield an unauthenticated root prompt that bypasses every OS-level safeguard. From there an attacker resets the root password, reads or rewrites disks, or plants persistence. A world-readable grub.cfg leaks the layout and any hashes it carries, and a writable one lets a local user inject boot parameters that survive reboots.
Why harden it
The bootloader is the root of the boot trust chain: it decides what kernel runs and with which parameters. If it can be edited without authentication, none of your downstream hardening matters, the attacker simply boots around it. Hardening GRUB closes the physical/console attack path and makes the kernel command line itself a layer of defense, enabling mitigations that can only be set at boot time (CPU side-channel fixes, memory hygiene, mandatory access control).
Defense principles applied
- Authentication before privilege: set a GRUB superuser with a
password_pbkdf2hash so editing entries or reaching the GRUB shell requires a password. This is what stops thesingle/init=/bin/bashedit. - The
--unrestrictedcaveat: a superuser password without--unrestrictedon the normal menu entries blocks every boot and will hang a headless machine at the GRUB prompt. Add--unrestrictedso the password gates editing and the shell, not routine booting. This is the single most common way to brick a server while hardening it. - Least privilege on files:
grub.cfgshould be owned byroot:rootand not readable, writable or executable by group/other (mode0600), so its contents can't leak and no local user can tamper with boot parameters (CIS 1.4.2, ANSSI BP-028 R29). - Defense in depth on the kernel command line: turn on boot-time mitigations such as
pti=on(Meltdown), the spectre/MDS/L1TF flags,init_on_alloc=1/init_on_free=1andpage_poison=1(zero memory to kill use-after-free leaks),slab_nomerge,vsyscall=none, and keepselinux=0absent.
What Pavois audits: effective at runtime, not the template
Hardening only counts if it is effective at runtime, not merely written in /etc/default/grub:
- GRUB password (
grub-password, severity high): Pavois greps the renderedgrub.cfgacross BIOS (/boot/grub,/boot/grub2) and EFI (/boot/efi/EFI/*/grub.cfg) layouts, plus/etc/grub.d/, forset superusersand apassword_pbkdf2/passworddirective. It validates the generated config that GRUB actually loads, not a template fragment. - Kernel command line: each rule reads
/proc/cmdline, the line the running kernel actually booted with, and matches the required flag (pti=on,init_on_alloc=1,slab_nomerge, the absence ofselinux=0). Reading/proc/cmdlineinstead of/etc/default/grubcatches a flag edited but never regenerated, or regenerated but not yet rebooted. grub.cfgpermissions:root:root, no group/other read/write/execute on the realgrub.cfgand its EFI variant, guarded by anonly_ifexistence test.
When pavois harden apply sets the password it uses the grub_password resource (PBKDF2 hash, snippet in grub.d, config regenerated, reboot_required) and appends --unrestricted automatically, so applying the control never locks you out of a normal boot.
How do you set it and verify?
- Generate a PBKDF2 hash:
grub-mkpasswd-pbkdf2(RHEL:grub2-mkpasswd-pbkdf2) and copy thegrub.pbkdf2.sha512...string. - Declare the superuser in a
grub.dsnippet (e.g./etc/grub.d/01_users):set superusers="admin"thenpassword_pbkdf2 admin <hash>. - Keep normal boot unattended: add
--unrestrictedto theCLASSin/etc/grub.d/10_linuxso menu entries boot without the password (only editing and the shell are gated). - Regenerate:
update-grub(Debian/Ubuntu) orgrub2-mkconfig -o /boot/grub2/grub.cfg(RHEL), thenchmod 0600the renderedgrub.cfg. - Verify:
cat /proc/cmdlinefor the live flags,grep -E 'superusers|password_pbkdf2|unrestricted' /boot/grub*/grub.cfg, then reboot to confirm the machine boots unattended and that pressingeprompts for the password.
Pitfalls
- Password without
--unrestrictedbricks a headless boot: the machine hangs at the GRUB password prompt. Always pair them. - Editing
/etc/default/grubis not enough: nothing changes until you regenerategrub.cfgand reboot. Pavois reads/proc/cmdline, so it tells you the truth. - EFI vs BIOS paths differ: the real
grub.cfgmay be under/boot/efi/EFI/<distro>/. Edit and check the one actually in use. - Recovery: if you lock yourself out, boot the install media in rescue mode to fix the snippet.
FAQ
Does a GRUB password stop the machine from booting on its own? Only if you forget --unrestricted. With it, normal entries boot unattended and the password is required only to edit an entry or open the GRUB shell.
Why does Pavois read /proc/cmdline and the rendered grub.cfg instead of /etc/default/grub? Because /etc/default/grub is a template; the kernel boots with /proc/cmdline and GRUB loads the generated grub.cfg. A flag edited but never regenerated, or not yet rebooted, is a false pass on the template.
Where do I put the password? In a /etc/grub.d/ snippet (so grub-mkconfig renders it into grub.cfg), never by editing the generated grub.cfg directly.