SSD Nodes Learn 🎉 VPS from $5.50/mo
Guides Matt ConnorBy Matt Connor

How FreeBSD Handles Security Updates

FreeBSD patches the base system with freebsd-update and finds vulnerable packages with pkg audit. Two separate tools, and two separate feeds to watch.

How FreeBSD handles security updates

FreeBSD handles security updates with two separate tools, because a FreeBSD server is two separate things. The base system, meaning the kernel and the userland that shipped with the release, is patched with freebsd-update. Everything you installed on top of it is a package, and packages are patched with pkg. Run one and skip the other and half the machine stays unpatched, and nothing on the box will tell you.

SSD Nodes does not offer FreeBSD images. Our plans run Linux. This post is here anyway because the reader overlap is total: the people who run our Ubuntu and Debian servers also run FreeBSD on a firewall or on the one machine they inherited. The split patching model is the part that catches a Linux admin, so it is the part worth writing down. Every command, advisory format and support date below was checked against the FreeBSD security page and the project's manual pages in August 2026.

One note before the commands. FreeBSD does not install sudo in the base system. Everything here needs root. Use su -, or install sudo or doas from packages first.

The base system and packages are separate universes

On Ubuntu, apt owns the whole machine. The kernel, openssl, nginx and your own tools all arrive as .deb files from one tool, and apt upgrade moves all of them together.

FreeBSD splits that in half. The base system is built as one unit and versioned as one unit: 15.1-RELEASE-p3 is a single number covering the kernel, the C library, sshd and the OpenSSL copy in /usr/lib. None of it comes from pkg. Everything else lives under /usr/local, arrives as a binary package built from the ports tree, and carries its own version.

So one box can hold two copies of OpenSSL: the base copy in /usr/lib, patched only by freebsd-update, and the package copy in /usr/local/lib, patched only by pkg. Which one a program uses depends on which one it was linked against, and software installed from packages usually links the package copy. Patching one does nothing for the other.

Three commands tell you where you stand:

freebsd-version -u
freebsd-version -k
uname -r

freebsd-version -u prints the patch level of the installed userland. freebsd-version -k prints the patch level of the installed kernel, and freebsd-version(1) is explicit about why that is not the same as uname: "if a new kernel has been installed but the system has not yet rebooted, freebsd-version will print the version and patch level of the new kernel". uname -r prints the kernel running right now. There is also freebsd-version -r, which prints the running kernel but is "unaffected by environment variables", which matters inside a jail where UNAME_r is often set to something else.

Security Advisories and Errata Notices

Two kinds of notice come out of the FreeBSD Security Team, and they mean different things.

A Security Advisory covers a security vulnerability in the base system. The identifier looks like FreeBSD-SA-26:55.elf: the letters SA, the two digit year, a number that counts up through that year, then the affected component. FreeBSD-SA-26:52.if_wg and FreeBSD-SA-26:50.kqueue were both published on 2026-07-29. The full list lives on the FreeBSD advisories page.

An Errata Notice covers a correctness or stability problem worth pushing to a release branch, with no security impact. Same shape, with EN in place of SA: FreeBSD-EN-26:19.zfs, FreeBSD-EN-26:18.tzdata. A time zone data update is the classic example. Nobody can attack you with stale time zone data, and your timestamps are wrong until you take the fix. Errata are listed on the FreeBSD errata notices page.

Both kinds are signed with the Security Officer's PGP (pretty good privacy) key and archived at security.FreeBSD.org, and both are delivered to your machine by freebsd-update.

Here is the part that catches Linux admins. Neither kind covers packages. The security page says so plainly: problems in the FreeBSD Ports Collection "are covered separately in the FreeBSD VuXML document". A remote hole in the nginx package will never receive an SA number. If the advisory feed is the only thing you watch, you will never hear about it.

How do I hear about a FreeBSD security update?

The list to join is freebsd-security-notifications. It is moderated and low volume, and it carries the advisories and errata notices themselves. Subscribe at lists.freebsd.org.

freebsd-announce is also moderated and carries advisories alongside release announcements, so it works if you want one list for everything. freebsd-security is the discussion list. It is useful reading, and it is not where you go to learn that you need to patch.

All of these carry base system news only. Package vulnerabilities never arrive by mail. You find those by running a command.

pkg audit, and the database behind it

VuXML, the Vulnerabilities and Exposures Markup Language, is the FreeBSD project's record of security problems in ports and packages. Each entry names the affected package, the version ranges that are vulnerable, the CVE (common vulnerabilities and exposures) identifiers and a short description. The whole set is browsable at the VuXML index, sorted by package, by CVE or by date.

pkg audit is the tool that reads it:

pkg audit -F

-F fetches a fresh copy of the database before checking. Use it every time. Without -F you are matching against whatever copy the machine already has, which can be months stale, so a clean result means nothing. The command compares every installed package version against every VuXML entry, prints each match with its CVE numbers and a link to the VuXML page, then ends with a count line telling you how many problems were found in how many installed packages.

Two more flags from pkg-audit(8) are worth knowing. pkg audit -r also "prints packages that depend on vulnerable packages and are thus potentially vulnerable as well", which is how you learn that a vulnerable library matters because six installed things link it. pkg audit -R prints the same result as JSON or another machine format, which is what you feed a monitoring check.

The pkg package installs a periodic script at /usr/local/etc/periodic/security/410.pkg-audit. It runs as part of the daily security check and mails the result to root. Confirm it is on with a line in /etc/periodic.conf:

daily_status_security_pkgaudit_enable="YES"

That daily mail is the closest FreeBSD gets to the unattended-upgrades habit on Ubuntu, and the difference is the whole point: unattended-upgrades installs the fix while you sleep, and pkg audit only tells you a fix is needed. pkg audit reports. It never patches. Nothing on a stock FreeBSD system installs a security update without you.

Fixing a vulnerable package

pkg update
pkg upgrade

There is no security-only pocket in the FreeBSD package repositories. Ubuntu can pull from noble-security alone and leave every other package where it is. FreeBSD has no equivalent, so fixing one vulnerable package means taking whatever version the repository currently offers, plus any dependencies that moved with it. Plan package patching as a change, not as a background job.

Which repository branch you are on decides how fast a fix reaches you. The default is the quarterly branch, which the handbook describes as giving "a more predictable and stable experience" by accepting only non-feature updates. The latest branch takes the newest version of everything. So when pkg audit -F reports a package as vulnerable and pkg upgrade says there is nothing to do, the fix has not landed on your branch yet, and that is the mechanism behind the confusion.

To move a machine to the latest branch, copy the repository file that ships with the system and edit the copy:

mkdir -p /usr/local/etc/pkg/repos
cp /etc/pkg/FreeBSD.conf /usr/local/etc/pkg/repos/FreeBSD.conf

Change quarterly to latest in the url line of the copy, then run pkg update -f to pull the new catalogue. Copy the file rather than typing the repository name from memory: the name inside /etc/pkg/FreeBSD.conf is the one your system actually uses, and a file under /usr/local/etc/pkg/repos only overrides a repository whose name it matches exactly.

Applying base system patches

freebsd-update fetch
freebsd-update install

fetch downloads patches for your current release and prints the list of files it will change. When there is nothing to do it prints No updates needed to update system to 15.1-RELEASE-p3. and exits. When there is something to do it finishes by telling you to run the install command. Nothing is applied until you run freebsd-update install, so fetch is safe to run any time.

freebsd-update(8) serves binary updates for ALPHA, BETA, RC and RELEASE versions, and not for PRERELEASE, STABLE or CURRENT. If you track stable/15 you build from source, and this tool has nothing for you.

Automate the download and keep the install manual. The handbook's line for /etc/crontab:

@daily                                  root    freebsd-update cron

freebsd-update cron sleeps a random amount of time between 1 and 3600 seconds, then downloads updates exactly as fetch does, and mails root when something is waiting. The random sleep is there so that every FreeBSD machine on the internet does not hit the update mirrors in the same second.

Two things in the output confuse people. src component not installed, skipped is normal on a server with no source tree, and it is not an error. The set of components is controlled by a Components line in /etc/freebsd-update.conf, and the choices are src, world and kernel.

If an install goes wrong, freebsd-update rollback uninstalls the most recently installed updates. On a ZFS root you can do better and take a boot environment first:

bectl create pre-patch
freebsd-update fetch install

If the patched system does not boot, select the old boot environment from the loader menu and you are back where you started. That escape hatch is one of the practical reasons for running ZFS as the root filesystem, and it costs almost no disk until the two environments diverge.

Is my FreeBSD release still supported?

Each release is supported for a fixed window, published as a branch table on the security page. As of August 2026 that table reads:

  • releng/15.1, which is 15.1-RELEASE, until 31 March 2027
  • releng/15.0, which is 15.0-RELEASE, until 30 September 2026
  • releng/14.4, which is 14.4-RELEASE, until 31 December 2026
  • stable/15 until 31 December 2029
  • stable/14 until 30 November 2028

Point releases get short windows. 15.0-RELEASE runs out about seven weeks after this post was written, because 15.1 shipped and put it on a clock. The stable branches last for years, and they are source branches that freebsd-update does not serve.

Check your own with freebsd-version -u and compare it against the table. freebsd-update warns you as well. Approaching the date, fetch prints:

WARNING: FreeBSD 15.0-RELEASE is approaching its End-of-Life date.
It is strongly recommended that you upgrade to a newer
release within the next 2 months.

Once the date passes, the warning becomes WARNING: FreeBSD 15.0-RELEASE HAS PASSED ITS END-OF-LIFE DATE. An unsupported release keeps working. It stops receiving advisories, which means the next base vulnerability is yours to keep forever.

Moving up a release is freebsd-update -r 15.1-RELEASE upgrade, then freebsd-update install, then a reboot, then freebsd-update install a second time, then pkg-static upgrade -f to reinstall every package against the new libraries, then a final freebsd-update install. The handbook notes there may be only two install phases instead of three, depending on whether any library version numbers were bumped. Book a maintenance window, and read the FreeBSD 15 server setup guide before you start.

Reboot, or is a service restart enough?

FreeBSD answers this with one comparison:

freebsd-version -k
uname -r

freebsd-version -k is the kernel on disk. uname -r is the kernel in memory. Different strings mean a new kernel is installed and you are not running it, so reboot. Matching strings mean the patch did not touch the kernel, and a reboot buys you nothing.

For a userland patch, restart whatever uses the patched code. A fix to the base OpenSSL in /usr/lib does nothing for an sshd that started three weeks ago and still has the old library mapped into its address space. The file on disk is new. The running process is not.

service sshd restart

The same rule covers packages. pkg upgrade replaces the binary on disk while the running process holds the old one open, so service nginx restart is the step that makes the fix real.

The base system has no equivalent of Debian's needrestart, so nothing prompts you and nothing keeps a list. Either track which services link which patched library, or reboot after any patch that touches base libraries. On a server with its configuration in version control, a reboot is a routine operation, and it is far cheaper than believing you are patched when you are not.

Patching a machine that runs jails

A jail shares the host kernel, so a kernel advisory is a host problem and every jail on the box inherits it. Patch the host and reboot, and the kernel side is done for all of them. The userland inside each jail is a separate installation with its own patch level, and freebsd-version -j <jail> reports it from the host. Packages inside a jail are separate too, and pkg -j <jail> audit -F audits them without entering the jail. That shared kernel and separate userland split is the same structural difference that shapes how jails compare with Docker containers.

The Ubuntu translation

Each FreeBSD habit has a counterpart, so you can carry the routine in either direction.

  • Base system patches: freebsd-update fetch then freebsd-update install. On Ubuntu, apt update && apt upgrade, which covers the base and everything else at once.
  • Third party software: pkg update && pkg upgrade on FreeBSD. On Ubuntu, apt again.
  • Known vulnerability check: pkg audit -F on FreeBSD. On Ubuntu 24.04 the nearest command is pro security-status, which shows security updates for installed packages including Expanded Security Maintenance content.
  • Automatic installation: unattended-upgrades on Ubuntu applies security updates for you. FreeBSD ships nothing equivalent, so freebsd-update cron downloads and mails while you install by hand.
  • Advisory feed: freebsd-security-notifications carries FreeBSD-SA and FreeBSD-EN items. ubuntu-security-announce carries Ubuntu Security Notices.
  • Vulnerability database: VuXML for FreeBSD ports and packages. The Ubuntu CVE tracker for Ubuntu packages.
  • Reboot check: freebsd-version -k against uname -r on FreeBSD. The presence of /var/run/reboot-required on Ubuntu.
  • Support window: the branch table on the FreeBSD security page. The release schedule and pro security-status on Ubuntu.

The underlying routine is identical on both systems: subscribe to the feed, run the audit on a schedule, then decide what to install and when to restart. FreeBSD just makes you say the second half out loud, because it will not do it for you. The wider comparison of Linux and FreeBSD as a server platform covers what else changes when you move a workload between them.

FAQ

Does freebsd-update patch my packages as well?

No. freebsd-update covers the base system only, meaning the kernel and the userland that shipped with the release. Software installed under /usr/local comes from packages, and it is patched with pkg upgrade. Run pkg audit -F to find which installed packages have known vulnerabilities, because base advisories never mention them and the security mailing lists never announce them.

How do I know whether a FreeBSD update needs a reboot?

Compare freebsd-version -k with uname -r. The first prints the kernel installed on disk, including one that was just written but not yet booted. The second prints the kernel that is running. Different strings mean you need a reboot. Matching strings mean the patch was userland only, so restart the affected services instead, for example service sshd restart, because a running process keeps the old library mapped until it restarts.

What is the difference between a Security Advisory and an Errata Notice?

A Security Advisory, such as FreeBSD-SA-26:55.elf, fixes a security vulnerability in the base system. An Errata Notice, such as FreeBSD-EN-26:18.tzdata, fixes a correctness or stability problem that has no security impact, like out of date time zone data. Both use the pattern year, colon, sequence number, component. Both are signed by the Security Officer and delivered by freebsd-update, and neither one covers software installed from ports or packages.

Is there an unattended-upgrades equivalent for FreeBSD?

Not in the base system. freebsd-update cron downloads pending base patches and mails root, and it never installs them. The periodic script that pkg installs runs pkg audit daily and mails the result, and it never upgrades anything. Unattended installation is something you would build yourself with a cron job, and because a FreeBSD package upgrade takes the newest version rather than a security-only backport, most admins read the mail and install by hand.

How do I check that my FreeBSD release is still supported?

Run freebsd-version -u for your userland version, then compare it against the supported branch table on the FreeBSD security page. Point releases have short windows: as of August 2026, 15.0-RELEASE ends on 30 September 2026 while 15.1-RELEASE runs to 31 March 2027. freebsd-update fetch warns you as the date approaches, and once the date passes it prints a line saying the release HAS PASSED ITS END-OF-LIFE DATE. After that point no further advisories apply to you.

#freebsd#security#patching#advisories#pkg