When a critical CVE drops, you have hours—not days—to decide whether to patch immediately or wait for more information. I've seen production servers go down because teams rushed a kernel update without testing, and I've also seen sites compromised because teams waited too long. The goal is speed with safety.
This workflow prioritizes assessment, containment, and controlled rollout so you can patch fast without breaking production.
Step 1: Assess the CVE within the first hour
Not every CVE tagged "critical" affects your stack. Start by reading the advisory and checking three things: whether the vulnerable component is installed, whether your configuration exposes the flaw, and whether an exploit is public.
Check installed versions first:
rpm -qa | grep <package-name> # RHEL/CentOS/AlmaLinux
dpkg -l | grep <package-name> # Debian/Ubuntu
If the vulnerable version is not installed, document that fact and move on. If it is installed, check whether the service is exposed to the internet. A vulnerability in a database that only listens on 127.0.0.1 is lower priority than one in Apache or SSH.
CVSS scores give you a starting point but not the full picture. A score of 9.8 sounds urgent, but if the vulnerable code path requires an authenticated admin session and you have IP whitelisting in place, you can schedule the patch during business hours instead of at 3 AM. Ask whether an attacker can reach the vulnerable endpoint from the public internet.
In tickets I handled, the panic came from headlines, not actual risk. Read the CVE description carefully and map it to your environment before you wake the team.
Step 2: Contain exposure while you plan
If the CVE is genuinely critical and you can't patch immediately, reduce the attack surface. Options include firewall rules, disabling a specific service, or moving traffic through a WAF.
For a vulnerable web service, block external access at the firewall:
firewall-cmd --add-rich-rule='rule family="ipv4" source address="0.0.0.0/0" port port="8080" protocol="tcp" reject' --permanent
firewall-cmd --reload
Or use an allow-list if you know which IPs need access:
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="203.0.113.0/24" port port="22" protocol="tcp" accept' --permanent
firewall-cmd --reload
For WordPress or web apps, put Cloudflare in front and enable the WAF. That won't stop every exploit, but it buys you time. If the CVE affects a daemon you don't actively use, stop the service outright:
systemctl stop <service>
systemctl disable <service>
Containment is not a substitute for patching. It's a bridge to let you test properly instead of rushing.
Step 3: Pull the patch and check release notes
Vendor repositories usually release patches within hours of a critical CVE disclosure. Check for updates:
yum check-update <package> # RHEL-based
apt update && apt list --upgradable | grep <package> # Debian-based
Before you install anything, read the release notes or changelog. Look for breaking changes, deprecated options, or new dependencies. A patch might fix the CVE but introduce a config syntax change that breaks your setup.
For kernel updates, check whether a reboot is required and whether your bootloader config is correct. A bad kernel parameter can leave the server unbootable, and you don't want to discover that in production.
If the vendor hasn't released a patch yet, check whether the project has a GitHub advisory or a workaround. Sometimes you can mitigate the issue with a config change while waiting for the official package.
Step 4: Test in staging—really test it
Staging exists for this exact scenario. Clone your production environment as closely as possible: same OS version, same package versions, same config files. Then apply the patch and run your application.
Don't just start the service and call it done. Test the critical paths:
- Can users log in?
- Do API calls return the expected responses?
- Does the app connect to the database without errors?
- Are cron jobs still running?
Check logs after the update:
journalctl -u <service> --since "10 minutes ago"
tail -f /var/log/messages
tail -f /var/log/httpd/error_log # or nginx, depending on your stack
If you don't have a staging server, spin up a snapshot or a temporary VPS. Patching blind in production is how you turn a security incident into an outage.
One thing I learned the hard way: test the rollback too. Before you patch production, take a snapshot or back up the relevant packages so you can revert if something breaks.
Step 5: Roll out the patch with a fallback plan
Now you're ready for production. Schedule the update during a maintenance window if possible, but for critical CVEs, you may need to patch during business hours.
If you have multiple servers, patch one at a time and monitor it before moving to the next. For a web cluster behind a load balancer:
- Remove one backend from the pool.
- Apply the patch and restart the service.
- Watch logs and test the application.
- Add it back to the pool and repeat for the next server.
For a single-server setup, the process is riskier. Take a snapshot first:
# LVM snapshot example
lvcreate -L 10G -s -n root_snap /dev/vg0/root
Or use your hosting panel's snapshot feature if available. Then apply the update:
yum update <package> -y # RHEL-based
apt-get install --only-upgrade <package> -y # Debian-based
Restart the service:
systemctl restart <service>
Monitor logs in real time while the service comes back up. If something breaks, roll back immediately. For package rollbacks:
yum history undo last # RHEL-based
apt install <package>=<old-version> # Debian-based
For LVM snapshots, you can boot from the snapshot if the system becomes unbootable.
What about zero-downtime patching?
For kernel updates, live patching tools like KernelCare or Ksplice let you apply security fixes without a reboot. They work by injecting the patched code into the running kernel. This is useful for high-availability environments where uptime requirements are strict.
Install KernelCare:
curl -s https://repo.cloudlinux.com/kernelcare/kernelcare_install.sh | bash
kcarectl --update
Check whether the patch was applied:
kcarectl --info
Live patching doesn't cover every CVE, and some updates still require a reboot. Check the vendor's patch notes.
For application-level vulnerabilities, rolling updates across a cluster give you zero downtime. Pull one server out of rotation, patch it, verify, then move to the next. The load balancer handles the traffic shift.
Step 6: Verify and document
After patching, confirm the vulnerability is closed. Re-run your vulnerability scanner or check the package version:
rpm -q <package> # RHEL-based
dpkg -l | grep <package> # Debian-based
Cross-reference the installed version against the CVE advisory to confirm it includes the fix.
Document what you did: which servers were patched, what time, and whether any issues came up. If you had to adjust configs or work around breaking changes, note those too. Six months from now when the next critical CVE drops, you'll want that reference.
Update your runbooks with anything you learned. If the patch process revealed gaps—no staging environment, unclear rollback steps, missing monitoring—fix those gaps now, not during the next emergency.
What to check first
When a critical CVE hits, start with installed versions and exposure. Contain what you can while you test the patch in staging. Roll out carefully, one server at a time, with snapshots in place. After patching, verify the fix and update your documentation.
Speed matters, but testing matters more. A delayed patch is better than a broken production server.
