Safeguard
Supply Chain Security•

PXE and UEFI HTTP Boot Explained: Network Booting, iPXE and Security

PXE boots a machine with DHCP and TFTP; UEFI HTTP Boot fetches a URI over HTTP or HTTPS. How both work, where iPXE fits and how to secure network boot.

Safeguard Security Team
39 min read

Network booting starts a computer from files on a server instead of a local disk. Legacy PXE learns a boot file from DHCP and fetches it over unauthenticated TFTP; UEFI HTTP Boot fetches a URI over HTTP or HTTPS. Neither is safe by default: add HTTPS, Secure Boot, signed scripts and an isolated provisioning network.

This guide goes one level deeper than our posts on how DHCP works and its risks and on MITRE ATT&CK T1542.005, TFTP Boot. This one follows a single boot from power on to a running kernel: which DHCP options carry what, what the firmware checks, how iPXE changes the picture and where Secure Boot stops. Option numbers, architecture codes and directives come from the RFCs, the IANA registry, the iPXE and dnsmasq documentation and the EDK2 source listed under Sources.

Key takeaways

  • Network boot has two steps: get boot information from DHCP or DHCPv6, then download a network bootstrap program and run it.
  • Legacy PXE sends PXEClient in option 60 and its firmware type in option 93 (RFC 4578), and gets a TFTP server (option 66 or siaddr) and file name (option 67 or file) back (RFC 2132).
  • TFTP (RFC 1350) has no login, access control or integrity protection. Whoever answers first can hand the client a different program.
  • UEFI HTTP Boot sends HTTPClient and an HTTP architecture code (0x10 for x64) and expects a full URI. EDK2 refuses http:// unless built to allow it and ships with no TLS trust anchor.
  • iPXE supports HTTPS and detached CMS signatures, but its default "is always to allow untrusted images". Enforcement needs an embedded imgtrust script and a signature check on every file, including the initrd.
  • Secure Boot checks executables, not DHCP answers, scripts, menus, command lines or a separate initrd. Unified Kernel Images and signed iPXE scripts close most of that gap.
  • The largest exposure is often what the boot server hands out: answer files and enrollment tokens with secrets, served to anyone who asks.

What is network booting, and when is it used?

A machine network boots when its firmware fetches the first program it runs from a server. RFC 5970 gives the motivation: where administrators maintain many nodes, "serving all boot and configuration files from a central server" cuts the work.

Bare metal provisioning

The most common use is installing an operating system on servers without touching them. Each machine network boots an installer, which pulls an answer file (kickstart, preseed, autoinstall or cloud-init), partitions the disks and installs the OS. Afterwards the boot order falls through to local disk. Most server lifecycle tooling sits on this pattern.

Labs, classrooms and test benches

Labs reset machines to a known image on every start. A CI hardware lab can boot each test device into a freshly built image without reflashing storage.

Diskless and stateless clients

Thin clients, cluster nodes and kiosks may have no local OS at all, booting a kernel each time and mounting a root file system over NFS or iSCSI. Patching becomes: update the server image, reboot the fleet.

Recovery and diagnostics

Technicians boot memory testers, firmware updaters or rescue systems from a central server when a disk is broken or encrypted.

Network devices

Routers and switches can load their system image from a TFTP server. MITRE ATT&CK technique T1542.005 (created 20 October 2020, last modified 12 May 2026) covers adversaries pointing a device at a malicious TFTP server. Our T1542.005 post covers that angle; this post focuses on servers and PCs.

How does legacy PXE work, step by step?

The Preboot Execution Environment (PXE) was defined by Intel in a specification usually cited as PXE 2.1. We could not retrieve a primary copy, so the steps below come from RFC 4578 (PXE wire format), RFC 2132 (DHCP options), RFC 1350 (TFTP) and the dnsmasq and iPXE documentation.

Step 1: the client broadcasts a DHCPDISCOVER that says "I am PXE"

The network card's option ROM (BIOS) or the UEFI network stack sends a DHCPDISCOVER. Three things make it a PXE request:

  • Option 60, vendor class identifier. RFC 2132 defines option 60 as a string clients use "to optionally identify the vendor type and configuration of a DHCP client". PXE clients send a string beginning PXEClient, which dnsmasq matches when it encapsulates PXE options.
  • Option 93, client system architecture. RFC 4578 defines option 93 as a list of 16 bit architecture type identifiers that "describes the pre-boot runtime environment(s) of the client machine". A BIOS client sends 0; a 64 bit UEFI client sends 7 in practice (see the warning below).
  • Option 94, client network interface identifier, and option 97, client machine identifier. RFC 4578 says option 94 encodes the UNDI interface type and revision (type 1, revision 2.1 for example) and option 97 carries a 16 octet GUID. Both "MUST be present in all DHCP and PXE packets sent by PXE-compliant clients and servers."

Clients must also request options 128 to 135, meant for the downloaded boot program. RFC 4578 warns these were site specific before November 2004 and "may conflict with other uses" on the same network.

Step 2: the server offers an address and a boot file

A DHCP server that understands PXE answers with a DHCPOFFER containing an address and two boot parameters:

  • Where to download from. Either the siaddr (next server) field in the fixed DHCP header, or option 66, "TFTP server name", which RFC 2132 defines for use "when the 'sname' field in the DHCP header has been used for DHCP options."
  • What to download. Either the 128 byte file field in the DHCP header, or option 67, "Bootfile name", which RFC 2132 defines for use "when the 'file' field in the DHCP header has been used for DHCP options."

So options 66 and 67 are strictly overflow fields, but many servers send both forms because clients differ. EDK2's source even notes that RFC 2132 "does not strictly state" option 67 is null terminated, and handles both cases.

Step 3 (optional): proxy DHCP and boot servers

A "proxy DHCP" server can hand out only boot parameters while another server assigns addresses; dnsmasq documents this mode and PXE boot menus through its pxe-service setting. This matters for security: a second responder on the segment is normal PXE behavior, so a rogue one only has to answer the boot question.

Step 4: the client downloads the network bootstrap program with TFTP

The client sends a TFTP read request to UDP port 69. RFC 1350 says TFTP "currently has no provisions for user authentication"; data moves in 512 byte blocks, each acknowledged before the next. RFC 2348 (May 1998) lets the two sides negotiate blocks of 8 to 65464 octets, RFC 2349 adds transfer size and timeout options, and RFC 7440 (January 2015) adds a window of several blocks in flight. None adds authentication, encryption or integrity checks, and RFC 1350's security section tells administrators to limit what the server can read and disallow writes.

Step 5: the network bootstrap program runs

The downloaded network bootstrap program (NBP) is a real mode program such as pxelinux.0 or iPXE's undionly.kpxe on BIOS, or an EFI application such as shimx64.efi, grubx64.efi or ipxe.efi on UEFI. It fetches its own configuration, a kernel and an initrd, and boots the OS.

The RFC and the registry disagree. RFC 4578's table lists type 7 as "EFI BC" and 9 as "EFI x86-64". The IANA Processor Architecture Types registry lists 0x0007 as "x64 UEFI" and 0x0009 as "EBC", and x64 UEFI firmware sends 7. Copy match rules from the registry, not the RFC table.

The DHCP options at a glance

OptionNameDefined inDirectionWhat it does in network boot
60Vendor class identifierRFC 2132Client and serverClient says PXEClient or HTTPClient; server echoes the class it is answering
66TFTP server nameRFC 2132ServerBoot server when sname is used for options
67Bootfile nameRFC 2132ServerFile name, or a full URI for HTTP Boot, when file is used for options
93Client system architectureRFC 4578ClientFirmware type, such as 0 (BIOS), 7 (x64 UEFI), 0x10 (x64 UEFI HTTP)
94Client network interface identifierRFC 4578ClientUNDI interface type and revision
97Client machine identifierRFC 4578Client16 octet GUID of the machine
128 to 135PXE requested optionsRFC 4578ServerFree for the boot program; not used by the boot ROM
DHCPv6 59OPT_BOOTFILE_URLRFC 5970ServerBoot file URL, for example a tftp:// or http:// URL
DHCPv6 60OPT_BOOTFILE_PARAMRFC 5970ServerOrdered parameters passed to the boot file
DHCPv6 61OPTION_CLIENT_ARCH_TYPERFC 5970ClientSame architecture codes as option 93
DHCPv6 62OPTION_NIIRFC 5970ClientNetwork interface identifier, like option 94

How does network boot work over IPv6?

RFC 5970 (September 2010) carries PXE into DHCPv6 with one change: the server sends a single URL. Option 59 carries "the URL for the boot file" (literal IPv6 hosts go in square brackets), option 60 carries ordered parameters for the boot file, and options 61 and 62 mirror the IPv4 architecture and interface identifiers. DHCPv6 network boot was never tied to TFTP, and the IANA registry, which now also cites RFC 9915, holds the architecture codes for both IP versions.

RFC 5970's security section still reads as a list of what goes wrong today:

  • A rogue server can make the client boot "the wrong operating system that has been provided by a malicious file server."
  • Messages are unencrypted, so credentials in a boot URL are exposed.
  • Authenticated DHCPv6 "does not protect against attacks on the boot file download channel"; use HTTPS or signed images with a configurable key.

All three apply equally to IPv4 PXE.

What do UEFI PXE and UEFI HTTP Boot change?

UEFI PXE: same protocol, different payload

UEFI firmware has its own network stack and PXE Base Code protocol. On the wire UEFI PXE looks like BIOS PXE, with a UEFI architecture code in option 93 (7 for x64, 0x0B for 64 bit Arm per IANA). The differences are in what is downloaded:

  • The NBP is a PE/COFF EFI application, so servers hand out a file per architecture; iPXE's chainloading guide sends undionly.kpxe to architecture 00:00 and ipxe.efi to the rest.
  • Secure Boot applies: the firmware only starts an NBP signed by a key in db and not revoked in dbx. That is the biggest security difference from BIOS PXE.
  • iPXE notes UEFI network booting "tends to be substantially slower", one reason sites chainload early into a faster program.

UEFI HTTP Boot: drop TFTP, fetch a URI

The UEFI specification added HTTP Boot in version 2.5, according to iPXE. uefi.org blocked our fetches, so the details below come from EDK2 (the open source UEFI reference code), the IANA registry and the iPXE note.

  • The client announces itself as an HTTP client. EDK2 sends an HTTP Boot architecture code and treats an offer carrying "HTTPClient" as an HTTP offer. IANA lists "boot from http" codes per firmware: 0x0F x86 UEFI, 0x10 x64 UEFI, 0x12 and 0x13 Arm UEFI, 0x1A and 0x1C RISC-V UEFI, and others.
  • The server answers with HTTPClient and a URI. Per iPXE, the server must "provide the string HTTPClient as the vendor class identifier, and an HTTP URI as the boot filename"; on DHCPv6 the URI goes in option 59.
  • The firmware can boot more than one kind of file. EDK2 maps application/efi to an EFI image, application/vnd.efi-iso to a CD image and application/vnd.efi-img to a disk image; images are booted from a RAM disk, so a whole installer ISO can boot over HTTP.
  • HTTPS is the default posture in EDK2. NetworkPkg sets PcdAllowHttpConnections to FALSE by default ("Only the "https://" URI scheme is permitted"). Vendors can change this at build time, so check what your platform accepts.
  • There is no trust anchor until you add one. OVMF's README says HTTPS Boot needs HTTP and TLS compiled in and "by default, there is no trusted certificate." You import CAs through a "TLS Auth Configuration" screen or, for VMs, a firmware configuration blob.

Why HTTP Boot matters for security

HTTP Boot runs over TCP, routes across subnets, uses DNS names and, with HTTPS and a configured CA, authenticates the server, which is what RFC 5970 asked for in 2010. It does not fix DHCP. A rogue DHCP server can still point the client elsewhere, but its server then needs a certificate chaining to a CA the firmware trusts. With a private boot CA that is a high bar; with a public CA bundle it is low, since anyone can get a public certificate for a domain they control.

What is iPXE, and how does chainloading work?

iPXE is open source boot firmware that can be burned into a NIC ROM, built into UEFI firmware, or downloaded at boot by an existing PXE or HTTP Boot client. Its documentation covers HTTP, HTTPS, TFTP, iSCSI and AoE booting, scripting and menus, and many provisioning systems use it as their second stage.

Chainloading from PXE

iPXE's chainloading guide: put undionly.kpxe (BIOS) or ipxe.efi (UEFI) on the TFTP server as the boot file; the vendor ROM fetches iPXE, which does the rest over HTTP or HTTPS. Because iPXE sends its own DHCP request, a server that hands out iPXE again creates "the infinite loop". The guide's three fixes:

  1. An autoexec.ipxe script beside the binary, run automatically where supported.
  2. A DHCP rule that tells the two requests apart, returning the real boot script to iPXE. iPXE uses option 175 as its own option space (the crosscert setting is 175.93).
  3. An embedded script built in with EMBED=script.ipxe, which ignores the DHCP boot file name.

Only the third puts policy where a network attacker cannot change it.

Chainloading from UEFI HTTP Boot

iPXE's UEFI HTTP note drops TFTP entirely: the firmware's HTTP Boot client downloads ipxe.efi, then iPXE adds HTTPS, scripts, menus and "customisable code signing". Its DHCP rule returns HTTPClient and the ipxe.efi URI to architecture 16 (0x10).

What iPXE's cryptography covers

iPXE's cryptography page documents three features, each behind a build option:

FeatureBuild optionWhat it protectsWhat it does not protect
HTTPSDOWNLOAD_PROTO_HTTPSConfidentiality of the download and identity of the web serverAnything that came from DHCP, and files fetched over plain HTTP or TFTP
Code signingIMAGE_TRUST_CMDIntegrity and origin of each file you explicitly verify with imgverifyFiles you forget to verify, such as an initrd, unless you verify them too
File decryptionIMAGE_CRYPT_CMDConfidentiality of encrypted images at rest on the serverIntegrity, unless combined with code signing

Specifics from the iPXE pages:

  • TLS. TLS 1.0 to 1.2 with RSA or ECDSA keys, ECDHE or DHE, AES-GCM or AES-CBC. TLS 1.3 is not listed, so a TLS 1.3 only server will not work.
  • Trust. By default iPXE trusts one "iPXE root CA" that cross-signs the Mozilla CA list, so it trusts "the same set of certificates as the Firefox web browser". TRUST=ca.crt at build time replaces that with your own root; on an isolated network you must also make the full root available, or mirror the cross-signing service plus an OCSP proxy.
  • Signing. Detached CMS signatures from a certificate with digitalSignature and codeSigning usage. imgverify checks a file and can pin a signer name with --signer.
  • Enforcement. imgtrust refuses unverified images; imgtrust --permanent cannot be undone in that session. The docs state "there is no way to use trusted images without using an embedded script".
  • The initrd gap. imgtrust blocks an untrusted kernel "but will not prevent the use of an untrusted initrd". Verify the initrd explicitly.

The safe pattern: build iPXE yourself with HTTPS, signing and your own root, embed a script that runs imgtrust --permanent first, and verify every script, kernel and initrd against a pinned signer.

How does Secure Boot apply to network boot?

Secure Boot asks one question per step: is this executable signed by a key in db and not revoked in dbx? Our Secure Boot, Trusted Boot and Measured Boot explainer covers the model; here is how it maps onto network boot.

The usual Linux chain: firmware, shim, GRUB, kernel

  1. Firmware loads the NBP only if its signature checks out. shim's SBAT document notes PC Secure Boot typically trusts two authorities, the Microsoft UEFI CA and the Windows CA; distribution shims are signed through the former.
  2. shim loads the next stage. Its README calls it "a trivial EFI application" that falls back to a certificate built into shim when firmware keys do not cover the binary. Since 16.1 it overrides the firmware load functions so later stages are checked the same way, and its netboot.c fetches the second stage from the same server.
  3. GRUB loads the kernel after shim verifies it through the shim lock protocol.
  4. The kernel runs with its own module signing and lockdown policies.

Where the chain is weakest

Signature checks cover executables. Network boot is full of things that are not:

  • DHCP replies. A rogue DHCP server cannot make an unsigned file run, but it can steer the client to any signed file, including an old, vulnerable one still trusted.
  • Configuration and menus. A network-fetched grub.cfg, PXELINUX menu or unsigned iPXE script decides which kernel boots and with what command line, which can disable security features or point an installer at another answer file.
  • The initrd. In shim plus GRUB the initrd is unsigned. A Unified Kernel Image puts kernel, initrd and command line in one signed file, and shim's README says sections inside a signed UKI are covered by its outer signature.
  • Revocation lag. A flawed signed component stays bootable until dbx or SBAT revokes it. shim's SBAT document records that after BootHole (CVE-2020-10713) in 2020, 3 certificates and 150 hashes went into the x64 dbx, about 10 kB of the roughly 32 kB typically available, which is why SBAT revokes by component generation instead.
  • Early boot parsers. NVD's entry for CVE-2023-40547, published 25 January 2024, describes shim's HTTP boot support trusting attacker controlled values in an HTTP response, exploitable from a man in the middle position or a compromised boot server. Anything parsing network input before the OS exists is attack surface.

Can iPXE run with Secure Boot on?

Only if the firmware trusts its signature. iPXE's documentation says Secure Boot requires binaries signed by Microsoft and calls its signing effort a "work in progress". The options are a distribution's signed shim and boot loader instead, a shim that trusts your own certificate, or your own key in db with ipxe.efi signed yourself (see Secure Boot with your own keys). Do not disable Secure Boot to make iPXE work.

What are the risks of network boot?

Rogue DHCP servers

RFC 2131 says "DHCP in its current form is quite insecure" and "unauthorized DHCP servers may be easily set up". Whoever answers first chooses the client's boot server and file. On a flat network any compromised or misconfigured host can do it.

Unauthenticated TFTP

TFTP has no authentication or encryption. An on-path attacker can substitute blocks, anyone who can reach the server can read every file, and a writable TFTP root lets one write replace the NBP for every machine.

Image tampering on the server

The boot server is a single point of trust. Anyone who can change its files (through a weak pipeline, shared admin account or mirror sync) controls every later boot. Secure Boot limits that to signed binaries, but scripts, menus, initrds and answer files stay in reach. MITRE's T1542.005 mitigations include auditing "the integrity of the running configuration and system image", boot integrity features and restricting unauthenticated protocols.

Exposed provisioning secrets

The most underestimated risk. Answer files and first boot data routinely hold password hashes, domain join credentials, enrollment tokens or SSH keys, served over plain HTTP to any client that asks for the right path. RFC 5970 warns about URLs that "contain sensitive information like user names and passwords".

Network boot left on after provisioning

Installed machines that keep network boot first let any rogue DHCP server redirect every reboot, even into an installer that wipes the disk.

Old, signed boot programs

Secure Boot trusts signatures, not versions, so a controlled boot path can serve an old, flawed but unrevoked shim. Keep dbx and SBAT current on clients, not just the server.

Comparison: legacy PXE, UEFI PXE, UEFI HTTP Boot and iPXE

Legacy (BIOS) PXEUEFI PXEUEFI HTTP BootiPXE (chainloaded or built in)
DiscoveryDHCPv4, PXEClient, option 93 = 0DHCPv4 or DHCPv6, PXEClient, UEFI arch code (7 for x64)DHCPv4 or DHCPv6, HTTPClient, HTTP arch code (0x10 for x64)Its own DHCP request, or a fixed URL from an embedded script
Boot file locationsiaddr/option 66 plus file/option 67Same, or OPT_BOOTFILE_URL on IPv6Full URI in option 67 or OPT_BOOTFILE_URLAny URI: HTTP, HTTPS, TFTP, iSCSI and others
TransportTFTP over UDPTFTP over UDPHTTP or HTTPS over TCPHTTP, HTTPS, TFTP, storage protocols
Server authenticationNoneNoneWith HTTPS and an imported CAWith HTTPS; default trusts public CAs via cross-signing, or your own root
Integrity of the first fileNoneSecure Boot signature checkSecure Boot signature check, plus TLS in transitDepends on how iPXE itself was loaded
Integrity of scripts, kernel, initrdNoneDepends on the boot loaderDepends on the boot loader; ISO and disk images boot from a RAM diskimgverify per file, enforced with imgtrust --permanent in an embedded script
Secure BootNot applicableYes, for EFI executablesYes, for EFI executablesOnly if ipxe.efi is signed by a key the firmware trusts
Routing across subnetsNeeds DHCP relay and TFTP reachabilitySameDHCP relay plus ordinary HTTP routingOrdinary HTTP routing after the first hop
Typical role todayOlder hardware, legacy fleetsDefault network boot on UEFI hardwareModern servers and VMs, installer ISOsSecond stage for flexible, scripted provisioning

Which should you use?

If your situation isA reasonable choice
All clients are recent UEFI machines and you control the CAUEFI HTTP Boot over HTTPS with a private CA, booting a signed shim and boot loader or a signed UKI
You need scripting, menus or iSCSI, and can manage your own keysUEFI HTTP Boot or UEFI PXE to load a self-built, signed ipxe.efi with an embedded script that enforces imgtrust
You must support old BIOS clientsBIOS PXE to undionly.kpxe, then HTTPS and signed images inside iPXE, on an isolated VLAN
You only need to boot an installer ISO occasionallyUEFI HTTP Boot of the ISO over HTTPS; no TFTP server at all

Step by step: build a UEFI HTTPS boot lab with dnsmasq and verify the chain

This lab runs on one Linux host: an isolated virtual network, dnsmasq for DHCP, an HTTPS server with a private CA, and a QEMU VM with OVMF firmware that boots over HTTPS into iPXE with enforced signature checks. Use test keys only. Commands assume Debian or Ubuntu; package names, OVMF paths and whether your OVMF build includes HTTP Boot and TLS vary by distribution.

Step 1: install the pieces

sudo apt install dnsmasq nginx qemu-system-x86 ovmf openssl sbsigntool build-essential git
sudo systemctl disable --now dnsmasq   # run it only on the lab bridge

Step 2: create an isolated bridge

Boot servers answer broadcasts, so keep the lab off any shared network.

sudo ip link add br-boot type bridge
sudo ip addr add 192.168.100.1/24 dev br-boot
sudo ip link set br-boot up
sudo ip tuntap add dev tap-boot mode tap user "$USER"
sudo ip link set tap-boot master br-boot
sudo ip link set tap-boot up

Never attach a physical interface to br-boot, or your lab becomes a rogue DHCP server.

Step 3: make a private CA, a server certificate and a code signing certificate

The CA is the only trust anchor for both the firmware and iPXE.

mkdir -p ~/bootlab/ca && cd ~/bootlab/ca
openssl req -x509 -newkey rsa:3072 -nodes -days 365 \
  -subj "/CN=Boot Lab Root CA" -keyout ca.key -out ca.crt

# Server certificate for the HTTPS boot server, with the IP address as a subject alternative name
openssl req -newkey rsa:3072 -nodes -subj "/CN=192.168.100.1" \
  -addext "subjectAltName=IP:192.168.100.1" -keyout server.key -out server.req
openssl x509 -req -in server.req -CA ca.crt -CAkey ca.key -CAcreateserial \
  -days 90 -copy_extensions copy -out server.crt

# Code signing certificate for iPXE image signatures
openssl req -newkey rsa:3072 -nodes -subj "/CN=bootlab-signer" -keyout codesign.key -out codesign.req
printf "keyUsage=digitalSignature\nextendedKeyUsage=codeSigning\n" > codesign.ext
openssl x509 -req -in codesign.req -CA ca.crt -CAkey ca.key -CAcreateserial \
  -days 90 -extfile codesign.ext -out codesign.crt
openssl x509 -in codesign.crt -noout -ext keyUsage,extendedKeyUsage

These use OpenSSL 3 options. The last command should show Digital Signature and Code Signing, which iPXE requires. In production, keep ca.key and codesign.key on a separate signing host or hardware token, never on the boot server.

Step 4: configure dnsmasq for DHCP only, with per-architecture boot files

# /etc/dnsmasq.d/bootlab.conf
# DHCP only; disable the DNS function
port=0
interface=br-boot
bind-interfaces
dhcp-range=192.168.100.50,192.168.100.99,1h
log-dhcp

# Tag clients by option 93 (client system architecture), using IANA codes
dhcp-match=set:efi-x64-http,option:client-arch,16
# iPXE identifies itself with option 175; tag it so it gets a script, not itself
dhcp-match=set:ipxe,175

# UEFI HTTP Boot: answer with vendor class HTTPClient and an HTTPS URI
dhcp-option-force=tag:efi-x64-http,60,HTTPClient
dhcp-boot=tag:efi-x64-http,tag:!ipxe,https://192.168.100.1/ipxe.efi

# iPXE second DHCP request: hand out the signed boot script URI
dhcp-boot=tag:ipxe,https://192.168.100.1/boot.ipxe

From the dnsmasq manual: port=0 "completely disables DNS function"; dhcp-match tags a client whose option 93 list contains the number (use IANA values); dhcp-option-force sends option 60 even when not requested; dhcp-boot is IPv4 only (on IPv6, send option 59 with the option6: form of dhcp-option); the manual describes option 175 as the one sent to iPXE, and matching 175 in requests is the common way to recognize iPXE's own DHCP request (with the embedded script below, that second answer is only a fallback); log-dhcp shows every option. This lab has no TFTP. If BIOS clients need it, use tftp-root, which rejects .. paths, and tftp-secure, which serves only files owned by the dnsmasq user.

sudo dnsmasq --test --conf-file=/etc/dnsmasq.d/bootlab.conf
sudo dnsmasq --no-daemon --conf-file=/etc/dnsmasq.d/bootlab.conf

Step 5: build iPXE with HTTPS, code signing, your root and an enforcing script

cd ~/bootlab && git clone https://github.com/ipxe/ipxe.git && cd ipxe/src

# Enable HTTPS and the image trust command in the local build configuration
cat > config/local/general.h <<'EOF'
#define DOWNLOAD_PROTO_HTTPS
#define IMAGE_TRUST_CMD
EOF

# Embedded script: require trusted images permanently, then verify everything
cat > ~/bootlab/embed.ipxe <<'EOF'
#!ipxe
imgtrust --permanent
dhcp
imgfetch --name boot https://192.168.100.1/boot.ipxe
imgverify --signer bootlab-signer boot https://192.168.100.1/boot.ipxe.sig
chain boot
EOF

make bin-x86_64-efi/ipxe.efi EMBED=$HOME/bootlab/embed.ipxe \
  TRUST=$HOME/bootlab/ca/ca.crt CERT=$HOME/bootlab/ca/ca.crt

TRUST= replaces the public CA trust with your lab root; CERT= embeds the full root, since only its fingerprint is built in by default; EMBED= bakes in the enforcing script. Then write the boot script it will fetch and verify:

cat > ~/bootlab/boot.ipxe <<'EOF'
#!ipxe
kernel https://192.168.100.1/vmlinuz console=ttyS0
imgverify --signer bootlab-signer vmlinuz https://192.168.100.1/vmlinuz.sig
initrd https://192.168.100.1/initrd.img
imgverify --signer bootlab-signer initrd.img https://192.168.100.1/initrd.img.sig
boot
EOF

The imgverify on initrd.img is the line people forget.

Step 6: sign files and publish them on an HTTPS server

sudo mkdir -p /srv/boot
sudo cp ~/bootlab/ipxe/src/bin-x86_64-efi/ipxe.efi ~/bootlab/boot.ipxe /srv/boot/
# Copy a test kernel and initrd from a distribution netboot or installer image
sudo cp /path/to/test/vmlinuz /path/to/test/initrd.img /srv/boot/

cd /srv/boot
for f in boot.ipxe vmlinuz initrd.img; do
  sudo openssl cms -sign -binary -noattr -in "$f" \
    -signer ~/bootlab/ca/codesign.crt -inkey ~/bootlab/ca/codesign.key \
    -certfile ~/bootlab/ca/ca.crt -outform DER -out "$f.sig"
done

This is the signing form iPXE documents. Serve the directory over HTTPS only:

# /etc/nginx/sites-available/bootlab
server {
    listen 192.168.100.1:443 ssl;
    ssl_certificate     /etc/nginx/bootlab/server-chain.crt;
    ssl_certificate_key /etc/nginx/bootlab/server.key;
    ssl_protocols       TLSv1.2;
    root /srv/boot;
    autoindex off;
    types {
        application/efi efi;
    }
    default_type application/octet-stream;
}
sudo mkdir -p /etc/nginx/bootlab
cat ~/bootlab/ca/server.crt ~/bootlab/ca/ca.crt | sudo tee /etc/nginx/bootlab/server-chain.crt >/dev/null
sudo cp ~/bootlab/ca/server.key /etc/nginx/bootlab/
sudo ln -s /etc/nginx/sites-available/bootlab /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
curl --cacert ~/bootlab/ca/ca.crt -sI https://192.168.100.1/ipxe.efi | head -3

TLSv1.2 matches iPXE's documented ceiling, and application/efi is the type EDK2 treats as an EFI executable.

Step 7: give the firmware the CA and boot the VM

OVMF's README documents the etc/edk2/https/cacerts entry for trusted CAs. Build it from the lab CA alone with efisiglist (DER input); the README's p11-kit extract example would import every CA your host trusts.

cd ~/bootlab
openssl x509 -in ca/ca.crt -outform DER -out ca/ca.der
efisiglist -a ca/ca.der -o cacerts.bin

cp /usr/share/OVMF/OVMF_VARS_4M.fd ./vars.fd
qemu-system-x86_64 -machine q35 -m 2048 -nographic \
  -drive if=pflash,format=raw,readonly=on,file=/usr/share/OVMF/OVMF_CODE_4M.fd \
  -drive if=pflash,format=raw,file=./vars.fd \
  -netdev tap,id=n0,ifname=tap-boot,script=no,downscript=no \
  -device virtio-net-pci,netdev=n0 \
  -fw_cfg name=etc/edk2/https/cacerts,file=cacerts.bin

Pick the HTTP boot entry in the firmware boot manager. If none appears, rebuild OVMF from EDK2 with NETWORK_HTTP_BOOT_ENABLE and NETWORK_TLS_ENABLE, plus NETWORK_ALLOW_HTTP_CONNECTIONS=FALSE to refuse http://, as the OVMF README describes. The dnsmasq log should show architecture 16 and HTTPClient; the nginx log should show ipxe.efi, boot.ipxe and each file with its .sig; imgstat in iPXE marks verified images [TRUSTED].

Step 8: prove the checks work

Watch it fail safely: build cacerts.bin from an unrelated certificate (the firmware should refuse TLS), append a comment to boot.ipxe without re-signing (iPXE should stop), and swap in the wrong initrd.img.sig (boot should stop at the initrd check). Check signatures server side in your release pipeline too:

cd /srv/boot
for f in boot.ipxe vmlinuz initrd.img; do
  openssl cms -verify -binary -inform DER -in "$f.sig" -content "$f" \
    -CAfile ~/bootlab/ca/ca.crt -purpose any -out /dev/null && echo "OK  $f" || echo "BAD $f"
done

Step 9 (optional): turn on Secure Boot and check the EFI signatures

With Secure Boot on, the firmware refuses your ipxe.efi unless its signer is in db. Enroll a lab key per the own keys guide, then sign and check:

sbsign --key db.key --cert db.crt --output ipxe-signed.efi ipxe.efi
sbverify --list ipxe-signed.efi
sbverify --cert db.crt ipxe-signed.efi

For a distribution shim and GRUB, sbverify --list shows which certificate each depends on. Remove the lab afterwards with sudo ip link del tap-boot and sudo ip link del br-boot.

How do you secure network boot in production?

NIST SP 800-147 (April 2011) built firmware integrity on an authenticated update mechanism in which signatures block unauthorized firmware. Network boot needs the same idea one layer up, in four layers of control.

1. Contain the network

  • A dedicated provisioning VLAN, holding machines only while they provision.
  • DHCP snooping or equivalent switch features, so only designated ports can send DHCP server replies.
  • Relay DHCP only from provisioning VLANs to the boot DHCP server.
  • Reach TFTP and the boot web server only from the provisioning VLAN, per MITRE's "limit access to resource over network".

2. Authenticate what is downloaded

  • UEFI HTTP Boot over HTTPS with a boot-only private CA; disable plain HTTP where firmware allows.
  • Secure Boot on, booting signed shims, loaders and, where possible, signed UKIs.
  • Self-built iPXE with HTTPS, signing, your own root and an embedded imgtrust --permanent script that verifies every file against a pinned signer.
  • Current dbx and SBAT on clients, so old signed components cannot be replayed.

3. Protect the boot server and its content

  • Treat the boot server as production: restricted admin access, read only TFTP root, web server without write access to boot files.
  • Sign in the pipeline, not on the server, and publish only signed artifacts.
  • Monitor file integrity of boot directories and alert on changes outside a release.
  • Pin what each machine boots with per-machine scripts keyed by MAC or machine GUID (option 97).

4. Keep secrets out of the boot path

  • Short lived, single use enrollment tokens instead of long lived credentials in answer files.
  • Answer files over HTTPS only, ideally with client certificates, which iPXE supports.
  • No passwords in boot URLs, which DHCP carries in clear text.
  • After install, move network boot down the boot order and set a firmware setup password.

Timeline: how network boot evolved

DateEventSource
July 1992RFC 1350 publishes TFTP revision 2; no authenticationRFC 1350
March 1997RFC 2131 (DHCP) and RFC 2132 (options including 60, 66, 67) published; RFC 2131 calls DHCP "quite insecure"RFC 2131, RFC 2132
May 1998RFC 2348 and RFC 2349 add TFTP block size, transfer size and timeout optionsRFC 2348, RFC 2349
Late 1990sIntel's PXE specification (cited as version 2.1) defines PXE; exact publication date not confirmed for this postNot confirmed
November 2006RFC 4578 documents PXE options 93, 94 and 97RFC 4578
September 2010RFC 5970 defines DHCPv6 network boot options 59 to 62, including the boot file URLRFC 5970
April 2011NIST SP 800-147, BIOS Protection Guidelines, publishedNIST SP 800-147
January 2015RFC 7440 adds the TFTP windowsize optionRFC 7440
UEFI 2.5UEFI HTTP Boot introduced, per the iPXE projectiPXE UEFI HTTP note
2020BootHole (CVE-2020-10713) revocation drives the SBAT design in shimshim SBAT.md
20 October 2020MITRE ATT&CK creates T1542.005, TFTP BootMITRE ATT&CK
25 January 2024NVD publishes CVE-2023-40547 in shim's HTTP boot supportNVD

Common mistakes

  • Copying architecture codes from the RFC 4578 table instead of the IANA registry. Check log-dhcp for what clients send.
  • HTTPS in iPXE without imgtrust and imgverify, with the default trust store accepting public CAs.
  • Verifying the kernel but not the initrd.
  • Importing a full public CA bundle into firmware, so any publicly trusted certificate passes.
  • A writable TFTP root.
  • Secrets in answer files readable over plain HTTP by anyone on the VLAN.
  • Disabling Secure Boot instead of signing boot programs.
  • Network boot left first in the boot order on installed machines.
  • A lab DHCP server on a shared network.
  • Forgetting client-side revocation: a new shim on the server does not help a client whose dbx still trusts an old one.

FAQ

What is the difference between PXE and UEFI HTTP Boot?

PXE gets a server and file name from DHCP and downloads over unauthenticated TFTP. UEFI HTTP Boot gets a full URI and downloads over HTTP or HTTPS, which is faster, routable and, with an imported CA, authenticates the server.

What are DHCP options 66 and 67 used for?

Option 66 is the TFTP server name and option 67 the boot file name (RFC 2132), formally overflow for the sname and file header fields. For UEFI HTTP Boot, option 67 carries a full URI.

What is DHCP option 93?

The client system architecture type (RFC 4578): 0 for BIOS, 7 for x64 UEFI, 0x0B for 64 bit Arm UEFI, 0x10 for x64 UEFI HTTP Boot. The IANA registry is the current reference.

Is PXE boot secure?

Not by itself, because DHCP and TFTP are unauthenticated. Add an isolated network, DHCP snooping, Secure Boot, HTTPS with a private CA, signed scripts and no secrets in the boot path.

Does Secure Boot protect PXE boot?

Partly. It checks downloaded EFI programs and, via shim and GRUB, the kernel, but not DHCP answers, menus, scripts, command lines or a separate initrd. Signed UKIs and signed iPXE scripts cover most of that gap.

What is iPXE chainloading?

An existing PXE or HTTP Boot client downloads iPXE, which takes over with HTTPS, scripts and menus. You stop it reloading itself with autoexec.ipxe, a DHCP rule or an embedded script.

Does iPXE support HTTPS and signed images?

Yes, built with DOWNLOAD_PROTO_HTTPS and IMAGE_TRUST_CMD: TLS up to 1.2, CMS signatures via imgverify, enforcement via imgtrust in an embedded script. Verify the initrd separately.

Can UEFI HTTP Boot boot an ISO file directly?

In EDK2, yes: application/vnd.efi-iso or application/vnd.efi-img responses are booted from a RAM disk. Vendor builds vary.

Does network boot work over IPv6?

Yes. RFC 5970 defines DHCPv6 boot options, and EDK2 has build settings for IPv6 PXE and IPv6 HTTP Boot; vendor support varies.

Why does UEFI HTTPS Boot fail with a certificate error?

Usually the firmware has no trusted CA: EDK2 ships with none, so import yours. Also check that the certificate name or IP matches the URI and the server sends the full chain.

Where Safeguard fits

Safeguard's fit here is indirect. It does not inspect firmware, scan boot images, watch the boot network or manage devices. It covers the software around network boot: provisioning repositories and boot server container images can be scanned for known vulnerable open source dependencies (safeguard scan --dir . or safeguard scan --image <name>), with reachability ranking, a view of which projects carry a component version, and policy gates in CI via safeguard exec. It cannot tell you whether a client's dbx is current, a DHCP server is rogue or an answer file leaks a password.

Network boot looks like a firmware topic, but most of what a boot server runs is ordinary open source software: a DHCP server, a web server, iPXE, boot loaders and the container images and scripts that package them. Those components get vulnerabilities like any other dependency, and a rebuilt fleet pulls whatever versions your boot pipeline last published, so keeping that pipeline current matters.

Fix it without waiting for upstream

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

The demos show Safeguard on ordinary software projects, not firmware or boot traffic; they apply to provisioning repositories, boot server containers and the CI jobs that build and sign boot images.

The first demo is a real Safeguard CLI session. After install, safeguard opens the interactive terminal, you ask it to fix the lodash CVE in a repository, and it reads the finding and advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with your approval, prints a summary and pushes nothing. It ends with /permissions, /model and /scan. The same approval-first loop suits boot tooling that reaches a whole fleet.

Click through it at your own pace, or open it full screen.

The local runner demo shows how to set up the runner on your own machine, approve it with its device code, and then scan from the terminal. A runner on a build host inside an isolated provisioning network can scan boot server images where they live.

Click through it at your own pace, or open it full screen.

The third demo shows how to connect Claude to the Safeguard MCP server with OAuth and choose which tools Claude can use, so an engineer can ask about known vulnerabilities in provisioning projects using only the tools you allowed.

Click through it at your own pace, or open it full screen.

To try it on your own repositories, download Safeguard and follow the CLI documentation.

Quick check

A UEFI client boots iPXE over HTTPS, and iPXE runs an embedded script that permanently requires trusted images. The boot script verifies the kernel but not the initrd. Is the initrd protected?

No. Per the iPXE docs, imgtrust blocks an unsigned kernel but not an unsigned initrd, so the initrd needs its own imgverify line.

Your DHCP server sends ipxe.efi to clients whose option 93 is 9, following the RFC 4578 table, but x64 UEFI machines never get it. Why?

RFC 4578's table lists 9 as "EFI x86-64", but the IANA registry lists 7 as x64 UEFI and 9 as EBC. Match on 7 (and 16 for x64 HTTP Boot).

Sources

Last reviewed: 24 October 2026. Firmware HTTP Boot and HTTPS support, default trust anchors and allowed URI schemes vary by vendor and firmware build; check your platform's documentation and test in an isolated lab before changing a production boot network.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.