Safeguard
Supply Chain Security•

Trusted Firmware-A Explained: Boot Stages, Secure World, Measured Boot

Trusted Firmware-A is Arm's open reference for secure boot and the EL3 monitor. Learn BL1 to BL33, the chain of trust, PSCI, OP-TEE and measured boot.

Safeguard Security Team
48 min read

Trusted Firmware-A (TF-A) is Arm's open source reference secure world firmware for application processors. It boots a system in stages named BL1, BL2, BL31, BL32 and BL33, verifies each image against a key rooted in the chip, then stays at Exception Level 3 as the secure monitor that switches worlds and handles OS power calls.

If you have booted a modern Arm server, a development board, an Arm laptop or many Android and embedded devices, some form of TF-A very likely ran before your bootloader did. This guide goes one level deeper than our posts on coreboot and on the difference between secure, trusted and measured boot. We read the TF-A documentation (built from the tree after the v2.15.0 release), its firmware design, Trusted Board Boot, authentication framework, measured boot, build options, QEMU platform, release, LTS and security handling chapters, the trustedfirmware.org project pages, the OP-TEE documentation, the Linux kernel PSCI binding, the EBBR specification and NIST SP 800-193. Every stage name, build flag and command below comes from those sources. Arm's own PSCI and SMC Calling Convention specifications block scripted downloads, so where we describe them we rely on how the TF-A and Linux documentation quote them.

Key takeaways

  • TF-A is not a bootloader for your OS. It is the trusted boot firmware plus a small runtime that stays at EL3 forever. Your OS bootloader (UEFI, U-Boot or a Linux kernel) runs later as BL33, in the normal world.
  • On AArch64 a TF-A cold boot runs five steps in order: BL1 (AP Trusted ROM), BL2 (Trusted Boot Firmware), BL31 (EL3 Runtime Software), the optional BL32 (Secure-EL1 Payload, for example OP-TEE) and BL33 (Non-trusted Firmware).
  • Trusted Board Boot authenticates every image up to and including BL33 using X.509 v3 certificates whose custom extensions carry public keys and image hashes. The trust anchor is a Root of Trust Public Key (ROTPK), or its hash, held in the chip, plus BL1 in ROM.
  • The images and their certificates travel together in a Firmware Image Package (FIP): a table of contents followed by payloads, each identified by a UUID. fiptool creates and inspects it, and cert_create builds the certificates.
  • PSCI is how your OS starts secondary CPUs, idles, suspends, resets and powers off. It reaches BL31 through the SMC instruction under the SMC Calling Convention.
  • Measured boot in TF-A records hashes of images and critical data into a TCG event log, and can extend them into a discrete TPM or the Runtime Security Engine (RSE). BL1 is the root of trust for measurement and is not itself measured.
  • Security fixes are published as TF-A advisories (TFV-1 to TFV-17 at the time of writing) and backported to LTS branches, but reach your device only after the silicon vendor and device maker rebuild and ship firmware. Ask which TF-A version and LTS branch you are running.

What is Trusted Firmware-A, and who maintains it?

The TF-A documentation describes the project as a reference implementation of secure world software for Armv7-A and Armv8-A, "including a Secure Monitor executing at Exception Level 3". The trustedfirmware.org project page widens that to Armv7-A, Armv8-A and Armv9-A processors. In practice that means the Cortex-A and Neoverse application cores you find in phones, laptops, servers, network appliances, automotive computers and single board computers.

TF-A implements a set of Arm interface standards so that every SoC does not invent its own. The documentation lists:

  • the Power State Coordination Interface (PSCI)
  • Trusted Board Boot Requirements CLIENT (TBBR-CLIENT)
  • the SMC Calling Convention (SMCCC)
  • the System Control and Management Interface (SCMI)
  • the Software Delegated Exception Interface (SDEI)
  • the PSA firmware update specification

The documentation calls it "a suitable starting point for productization" and tells users to do their own security validation, including penetration testing, on any secure world code derived from TF-A. The firmware in your device is a derivative, built and configured by someone else.

How is it governed?

TF-A is one of several projects under the Trusted Firmware umbrella at trustedfirmware.org. The sibling projects listed on the site include Trusted Firmware-M for Cortex-M microcontrollers, OP-TEE, Mbed TLS and TF-PSA-Crypto, Hafnium (the Secure EL2 partition manager), TF-RMM (the reference monitor for Arm Confidential Compute Architecture), MCUboot, Trusted Services, and Rusted Firmware-A (RF-A), which its project page describes as a Rust-first implementation of TF-A for the latest Arm A-class processors and which reached v0.3.0 on 8 October 2026.

The project FAQ says the governance model and the rules for Technical Steering Committee participation and voting are set out in a downloadable project charter, and that Linaro "is a Platinum Member of the Trusted Firmware project and provides governance, hosting and other services". The site footer is copyright Linaro Limited, and member companies join through a membership process. The source of record is the trustedfirmware.org Git and Gerrit servers; the FAQ notes that TF-A is migrating from GitHub to those servers, with a GitHub mirror kept for convenience. Code review happens on Gerrit at review.trustedfirmware.org, and the documentation is published at trustedfirmware-a.readthedocs.io.

How often does TF-A release?

The release process page says the project aims for a release every six months, tagged on the master branch, with a code freeze up to four weeks before. The version is set in the Makefile through VERSION_MAJOR, VERSION_MINOR and VERSION_PATCH, and the patch number only increases for long term support releases. The LTS document explains that releases are cut twice a year, in May and November, and that the project is aiming to support each LTS branch for at least seven years, up from an original plan of five, because firmware stays in the field far longer than a desktop operating system.

DateEventSource
21 October 2013The ARM-software/arm-trusted-firmware repository is created on GitHubGitHub repository metadata
October 2018v2.0 target release window (first week of October)TF-A release information
20 July 2022First draft of the TF-A LTS proposalTF-A LTS document history
March 2024Trusted Firmware project wiki deprecated in favour of readthedocstrustedfirmware.org FAQ
23 March 2026Qualcomm joins Trusted Firmwaretrustedfirmware.org news
27 May 2026TF-A 2.15.0 in the change log; Mbed TLS now included in the TF-A repositoryTF-A change log
2 June 2026TF-A v2.15 release announcedtrustedfirmware.org news
8 October 2026Rusted Firmware-A v0.3.0 releasedtrustedfirmware.org news
After v2.17ENABLE_RME build option, deprecated in v2.15.0, is due for removalTF-A release information

Which devices use TF-A?

The documentation has a full "Platform Ports" chapter covering Arm's own Fixed Virtual Platforms (FVPs) and the Juno development board, the QEMU virt machine, and ports for SoCs from many silicon vendors across mobile, automotive, networking, server and single board computer markets. Two practical consequences follow.

First, the TF-A in a shipping device is usually a vendor fork. The SoC vendor takes an upstream release, adds a platform port and often closed components such as a System Control Processor firmware image or DRAM training code, and ships that as part of a board support package. The device maker then builds it with its own keys.

Second, the TF-A version in a device can lag upstream by years. That is exactly the problem the LTS branches were created to address. The LTS document is blunt about the motivation: device makers want to keep in-market firmware changes small to avoid regressions, but they cannot skip security fixes, and the EU Cyber Resilience Act now pushes manufacturers to keep shipping updates across a product's life.

What are the boot stages BL1, BL2, BL31, BL32 and BL33?

A two minute primer on Arm exception levels

Arm A-profile processors run software at four privilege levels called exception levels, in two security states.

LevelNormal world (non-secure)Secure world
EL0ApplicationsTrusted applications (for example OP-TEE TAs)
EL1OS kernel (Linux, Windows, an RTOS)Trusted OS kernel, for example OP-TEE core at S-EL1
EL2Hypervisor (KVM, Xen) or UEFI firmwareSecure Partition Manager such as Hafnium at S-EL2 (Armv8.4 and later)
EL3None: EL3 is always secureSecure monitor: TF-A BL31

EL3 is the most privileged level, and it is where the processor decides which world runs next. The only way for code at a lower level to ask EL3 for something is to raise an exception into it, normally with the Secure Monitor Call (SMC) instruction. That is why a bug in BL31 is so serious: there is nothing above it.

The AArch64 cold boot path

The firmware design document describes the cold boot path as the sequence that starts at power on and runs until control passes to normal world firmware in DRAM. For AArch64 it has five steps.

StageName in the TF-A docsRuns atLives inMain job
BL1AP Trusted ROMEL3ROM, data in trusted SRAMReset handling, minimal CPU setup, load and (with TBB) authenticate BL2, then hand BL31's entry point over
BL2Trusted Boot FirmwareSecure EL1 (or EL3 with RESET_TO_BL2)Trusted SRAMPlatform setup, load and authenticate SCP_BL2, BL31, BL32 and BL33
BL31EL3 Runtime SoftwareEL3Trusted SRAMInstall runtime exception vectors, PSCI, SMC dispatch, initialise BL32, then enter BL33
BL32Secure-EL1 Payload (optional)Secure EL1 (or S-EL2 with an SPMC)Secure memoryTrusted OS such as OP-TEE, or the test secure payload
BL33Non-trusted FirmwareEL2 if present, else EL1Non-secure DRAMUEFI (EDK II), U-Boot, or a Linux kernel directly

On AArch32 the design is different: there are four steps and the EL3 Runtime Software is BL32 (the minimal SP_MIN implementation) rather than BL31.

BL1. Execution begins at the platform's reset vector at EL3. BL1 first decides whether this is a cold boot or a warm boot (a CPU waking from a low power state), sets up simple exception vectors and performs minimal architectural setup. It then prints "Booting Trusted Firmware" on the primary CPU, loads BL2 from platform storage into trusted SRAM and jumps to it at Secure EL1. BL1 only expects one kind of exception afterwards: an SMC from BL2 asking it to run the EL3 runtime image. BL1 is also where the optional Firmware Update (FWU) flow begins when the platform decides the normal images cannot be booted.

BL2. BL2 performs the platform initialisation needed to load the rest: on Arm platforms that includes setting up memory protection and, on systems with a System Control Processor, loading the SCP_BL2 image for the separate power and clock controller. BL2 then loads BL31 into trusted SRAM, the optional BL32 into secure memory, and BL33 into non-secure memory. It does not jump to BL32 or BL33 itself. Instead it records their entry points and the processor state they need, then raises an SMC back to BL1, which turns off the MMU, cleans caches and passes control to BL31 at EL3.

BL31. BL31 replaces BL1's exception vectors with its own, which check every SMC against the SMC Calling Convention before routing it. It initialises per-CPU data, the console, interconnect coherency, the MMU, the generic interrupt controller and the power controller, detects the system topology and starts the runtime services, PSCI first among them. If a BL32 image exists, the matching Secure Payload Dispatcher service initialises it. Finally BL31 sets up a clean EL2 or EL1 context, "ensuring that no secure state information finds its way into the non-secure execution state", and enters BL33 at the highest available exception level.

BL32. The secure payload is optional. On many products it is OP-TEE. BL31 contains a dispatcher (built with the SPD option, for example SPD=opteed) that knows how to start the trusted OS and how to route secure calls and interrupts to it.

BL33. This is the first normal world code. The QEMU platform documentation shows three common choices: EDK II UEFI firmware (QEMU_EFI.fd), U-Boot, or a Linux kernel booted directly by setting ARM_LINUX_KERNEL_AS_BL33=1, in which case BL2 passes the device tree to the kernel in register x0.

Cold boot, warm boot and secondary CPUs

During a cold boot one CPU becomes primary. The others wait in a safe platform specific state until the primary has done enough setup to release them. On QEMU, the docs explain, all CPUs are released together; BL1 picks a primary and parks the secondaries in a polling loop until the normal world asks for them through PSCI CPU_ON. A warm boot is a CPU coming out of a power down state. It does not reload images. It re-enters BL31 through its warm boot entry point, restores its context and returns to wherever the OS asked it to resume.

When the boot ROM is not TF-A's BL1

Many SoCs have their own mask ROM. The firmware design document describes two common integrations:

  • RESET_TO_BL2: some boot ROMs expect the next stage to run at EL3. Rather than waste memory on a BL1 whose only job would be dropping to Secure EL1, BL2 runs at EL3, includes the reset code itself and jumps directly to the next image. TF-A 2.15.0 reworked this path so platforms handle both EL1 and EL3 BL2 in the same setup hooks.
  • BL31 only: platforms with an existing trusted boot loader can call bl31_entrypoint() directly. TF-A documents a stable entry contract (AArch64, EL3, little endian, all interrupts masked) so the two can be updated independently.

If a vendor boot ROM and loader verify BL31, TF-A's Trusted Board Boot code in BL1 and BL2 may not run at all, and the chain of trust you need to audit is the vendor's.

How does Trusted Board Boot build a chain of trust?

Trusted Board Boot (TBB) is the TF-A feature that "prevents malicious firmware from running on the platform by authenticating all firmware images up to and including the normal world bootloader". It implements Arm's Trusted Board Boot Requirements specification, DEN0006D, and pairs with the Firmware Update design.

The trust anchor

A chain of trust starts with components that are trusted without being checked. In TF-A those are:

  1. The ROTPK, the Root of Trust Public Key, or a hash of it. On Arm development platforms a hash of the ROTPK (SHA-256 by default, selectable with HASH_ALG) sits in trusted root-key storage registers. A development ROTPK can instead be embedded in BL1 and BL2, which the docs say is "only for development purposes".
  2. BL1, on the assumption that it lives in ROM and cannot be changed.

Everything after that is a certificate or an image.

Key certificates and content certificates

TF-A's certificates follow X.509 v3, but they are not a web PKI. The design document says all certificates are self-signed and that no certificate authority is needed, because trust comes from the content of custom extensions rather than from the issuer field. There are two kinds:

  • Key certificates carry a public key that will verify the next certificate.
  • Content certificates carry the hash of a boot image (and of its configuration file).

An image is authentic when its computed hash matches the hash in a content certificate whose signature chains back to the ROTPK.

The default TBBR chain of trust uses these keys:

KeySignsPublic half stored in
Root of trust keyTrusted boot firmware certificate (BL2) and trusted key certificateThe ROTPK in the chip (or its hash)
Trusted world keyKey certificates for SCP_BL2, BL31 and BL32Trusted key certificate
Non-trusted world keyKey certificate for BL33Trusted key certificate
BL3x keys (one each for SCP_BL2, BL31, BL32, BL33)The content certificate for that imageThe matching key certificate

The certificates themselves are the trusted boot firmware certificate (hash of BL2 and of TB_FW_CONFIG, HW_CONFIG and FW_CONFIG), the trusted key certificate, and a key and content certificate pair for each of the SCP firmware, the SoC firmware (BL31 plus SOC_FW_CONFIG), the trusted OS (BL32 plus TOS_FW_CONFIG) and the non-trusted firmware (BL33 plus NT_FW_CONFIG). The SCP and trusted OS certificates are only required when those images exist.

The verification sequence

The design document gives the order, and the system panics if any step fails:

  1. BL1 loads the BL2 content certificate, hashes the issuer public key and compares it with the ROTPK hash from the root-key storage registers. If they match, it reads the BL2 hash from the certificate.
  2. BL1 loads BL2, hashes it and compares it with that value. Only then does it jump.
  3. BL2 loads the trusted key certificate, checks its issuer key against the ROTPK hash, and saves the trusted world and non-trusted world public keys.
  4. For each of SCP_BL2, BL31 and BL32, BL2 verifies the key certificate with the trusted world key, saves the image key, then verifies the content certificate with that image key and saves the image hash.
  5. For BL33, BL2 does the same using the non-trusted world key.
  6. BL2 hashes each loaded image and compares it with the saved hash.

One note in that section deserves attention: on the Arm development platforms the ROTPK matching operation in step 1 is described as platform specific and "currently unimplemented". On a reference board the chain is a demonstration. On a product, the silicon vendor's port has to implement it against real fuses.

Three default chains of trust

Platforms can define their own chain, and TF-A ships three defaults:

  • TBBR: one vendor owns the ROTPK, the trusted world key and the non-trusted world key, so that vendor signs everything.
  • Dualroot: for systems where the normal world firmware owner and the secure world firmware owner do not want to share keys. BL33 chains to a second root called the Platform ROTPK (PROTPK).
  • CCA: for Arm Confidential Compute Architecture systems, with three roots of trust, one each for the CCA firmware, the secure world firmware and the platform owner firmware, so their supply chains stay independent.

Choosing between them is a supply chain decision: dualroot lets a device maker sign its own BL33 without holding the SoC vendor's secure world key.

Anti-rollback and encryption

The TBBR specification and TF-A's authentication framework also describe non-volatile counters: certificates carry a counter value, and the platform refuses an image whose counter is lower than the value stored in hardware. That is what stops someone from flashing an older, signed but vulnerable BL31. TF-A additionally supports optional authenticated encryption of firmware images (DECRYPTION_SUPPORT=aes_gcm) through the encrypt_fw tool, which addresses the TBBR requirement for firmware confidentiality. Encryption protects the image from being read; it does not replace authentication.

The Firmware Image Package

All of these images and certificates are packed into a Firmware Image Package (FIP). The layout is a table of contents (ToC) header, one ToC entry per payload, an end marker, then the payload data. Each ToC entry holds a UUID that names the image, an offset from the start of the package, a size and flags. The UUIDs are defined in include/tools_share/firmware_image_package.h, shared by the tool and by the firmware. On Arm development platforms the FIP sits at the start of NOR flash, and the platform policy only allows loading a known set of images.

Because BL1 and BL2 parse that ToC from storage an attacker may control, the parser itself is part of the attack surface. Two TF-A advisories concern exactly this class of input: one on X.509 certificate extension validation (TFV-10) and a 2026 one on validation of FIP ToC offsets in BL1 and BL2 (TFV-15). The lesson is general: any code that parses attacker reachable data before authentication must be treated as security critical and kept up to date.

What is the secure world, and what does the secure monitor do?

TrustZone in one paragraph

Arm TrustZone splits the system into a secure state and a non-secure state. Every bus transaction carries a security attribute, so memory and peripherals can be marked secure only. The TF-A design document notes that the Base FVPs and Juno program a TrustZone Controller to carve out a region of DRAM that only the secure state can access, alongside trusted SRAM and ROM. Normal world software, including the Linux kernel and any hypervisor, cannot read that memory no matter how privileged it is.

What BL31 does at runtime

BL31 is the secure monitor. Once the system is running, it is responsible for:

  • World switching: saving one world's register context and restoring the other's when an SMC or a routed interrupt requires it. BL31 keeps a per-CPU context for each security state.
  • SMC dispatch: checking each SMC against SMCCC and routing it to the right runtime service, such as PSCI, SDEI, the secure payload dispatcher, vendor specific services or, on Arm CCA systems, the dispatcher for TF-RMM.
  • Interrupt routing: the interrupt management framework decides whether a secure interrupt that arrives while the normal world runs is taken to EL3 and handed to the secure world.
  • Power management: PSCI, plus coordination with the trusted OS so it can save its own state before a CPU powers down.
  • Errata and mitigations: applying CPU errata workarounds at reset and exposing mitigation hooks that the OS can call. This sits next to, not instead of, CPU microcode; see how CPU microcode updates load and who signs them.

OP-TEE as BL32

OP-TEE describes itself as a Trusted Execution Environment "designed as companion to a non-secure Linux kernel running on Arm Cortex-A cores using the TrustZone technology". It implements the GlobalPlatform TEE Internal Core API v1.3.1 for trusted applications and the TEE Client API v1.0 for normal world clients. Its design goals are isolation from the non-secure OS and between trusted applications, a small footprint that fits in on-chip memory, and portability.

In a TF-A system OP-TEE is loaded by BL2 as BL32 and started by BL31's OP-TEE dispatcher (SPD=opteed). The QEMU platform page shows OP-TEE split into three images, a header (tee-header_v2.bin as BL32), a pager (BL32 Extra1) and pageable code (BL32 Extra2), which BL2 loads into trusted DRAM when BL32_RAM_LOCATION=tdram is set. Linux talks to OP-TEE through its TEE subsystem driver, which issues SMCs that BL31 forwards to OP-TEE at S-EL1.

Secure partitions, Hafnium and FF-A

Armv8.4 added a secure EL2. That allows a Secure Partition Manager to sit at S-EL2 and isolate several secure partitions from each other, rather than trusting one monolithic trusted OS. The trustedfirmware.org project page points to Hafnium as the open source implementation. In this model BL31 hosts the Secure Partition Manager Dispatcher (SPMD), and the SPM Core (SPMC) runs at S-EL2 (Hafnium), at S-EL1, or at EL3 itself, depending on build options. Messages between partitions and the normal world follow Arm's Firmware Framework for A-profile (FF-A). The TF-A SPM documentation says three SPM implementations coexist in the codebase and only one can be built at a time: an S-EL2 SPMC that manages multiple S-EL1 or S-EL0 partitions with virtualization in the secure world, an EL3 SPMC that manages a single S-EL1 partition, and an SPMC at S-EL1 for cores without the secure EL2 extension. In the S-EL2 case the BL32 build option is repurposed to point at the SPMC image, for example Hafnium. For a security review, the important point is that S-EL2 isolation shrinks the blast radius of a bug in any one secure service. Hardware memory safety features are a separate layer again; see our comparison of Arm MTE and CHERI.

Arm CCA and confidential computing

On processors that implement Arm's Confidential Compute Architecture, TF-A adds a fourth security state for confidential virtual machines, managed by TF-RMM. The design note in the firmware design chapter points readers to a separate RME chapter, and the CCA chain of trust above exists for these systems. If your platform does not use CCA, none of this is built in.

What are PSCI and the SMC Calling Convention, and why do they matter to the OS?

SMCCC: the calling convention

The SMC Calling Convention defines how normal world software asks firmware for something. TF-A's documentation says normal world software "can access TF-A runtime services via the Arm SMC (Secure Monitor Call) instruction" and that the instruction must be used as SMCCC mandates. In outline:

  • The caller puts a 32-bit function identifier in register w0/x0 and arguments in the following registers, then executes SMC #0 (or HVC #0 when the call goes to a hypervisor).
  • The function identifier encodes whether the call is a fast call (it runs to completion atomically) or a yielding call, whether it uses the 32-bit or 64-bit convention, and which "owning entity" it belongs to: the Arm architecture, CPU services, SiP (silicon partner) services, OEM services, standard secure services such as PSCI, trusted applications or trusted OSes.
  • Results come back in x0 and the following registers.

That owning entity split is why TF-A's PSCI header defines PSCI_VERSION as 0x84000000, SYSTEM_OFF as 0x84000008 and SYSTEM_RESET as 0x84000009 (32-bit standard service fast calls), while CPU_ON has both 0x84000003 for AArch32 callers and 0xc4000003 for the 64-bit convention. Silicon vendor calls live in the separate SiP range. BL31 rejects calls whose bit 31 (fast or yielding) and bits 29 to 24 (owning entity number) do not match a registered service.

SMCCC also defines architecture calls that the OS uses to discover firmware mitigations. When the speculative execution issues of 2018 arrived, TF-A advisory TFV-6 described a firmware workaround for the branch target injection variant, exposed as an SMC named SMCCC_ARCH_WORKAROUND_1 for normal world privileged software to call, and the advisory notes that such software depends on the firmware changes being deployed for its own workaround to work. A firmware that does not implement it leaves the kernel unable to apply the mitigation on affected cores.

PSCI: power management through firmware

PSCI is "the interface from normal world software to firmware implementing power management use-cases (for example, secondary CPU boot, hotplug and idle)". BL31 implements it as a runtime service. The functions an OS uses most are:

PSCI functionWhat the OS uses it for
PSCI_VERSIONDiscover which PSCI version firmware implements
CPU_ONStart a secondary CPU at a given entry point (SMP bring up, CPU hotplug)
CPU_OFFPower down the calling CPU (hotplug)
CPU_SUSPENDEnter an idle or low power state on this CPU or a whole cluster
AFFINITY_INFOAsk whether a CPU is on or off
SYSTEM_OFFPower the system off
SYSTEM_RESET and SYSTEM_RESET2Reboot, optionally with an architectural or vendor reset type
SYSTEM_SUSPENDSuspend to RAM
PSCI_FEATURESAsk which optional functions are present

Internally, BL31 tracks a tree of power domains (cores, clusters, the system) and a state machine for each node with the states OFF, RUN and RETENTION. Because CPUs can be touched before their caches are on, BL31 uses Lamport's Bakery algorithm for locks during the warm boot path rather than exclusive load and store based spinlocks.

Why the OS cares

On Arm, Linux does not normally start secondary CPUs itself. The device tree cpus nodes say enable-method = "psci", and a psci node with compatible = "arm,psci-1.0" (or arm,psci-0.2) and method = "smc" or "hvc" tells the kernel which conduit to use. The Linux PSCI binding documents those properties. The QEMU platform port even has BL2 edit the QEMU generated device tree to add the PSCI node and CPU enable methods.

When PSCI is wrong, the symptoms look like OS bugs: CPUs that never come online, reboots that hang, suspend that never resumes. For security, PSCI is also an attack surface, because every PSCI call is untrusted input from the normal world into EL3. Several TF-A advisories (TFV-1, TFV-4, TFV-8, TFV-11 and TFV-14) concern how SMC handlers treat that input, from firmware update calls to register handling between SMC clients.

How does TF-A support measured boot?

Trusted Board Boot answers "may this image run?". Measured boot answers "what actually ran?". The TF-A measured boot design document defines it as "computing and securely recording hashes of code and critical data at each stage in the boot chain before the code/data is used", and stresses that it "does not authenticate the code or critical-data". The two are complementary, and our post on secure, trusted and measured boot covers the general difference.

What gets measured

All firmware images (every BLx image and its configuration file) must be measured, plus platform critical data: settings that change the boot path, values that decide which firmware to load, security policies and debug settings, and data that hardware updates. The examples the documentation gives are the list of CPU errata workarounds applied at reset, fuse states such as whether the SoC is in secure mode, and the non-volatile counters that say whether firmware is up to date.

BL1 is treated as the root of trust for measurement and is not measured itself. The measurement platform interfaces are used by BL1 and BL2 only. BL31 does not load images and therefore does not measure any.

Where measurements go

A measurement slot (a PCR in TPM terms) can only be changed by an extend operation, a one way hash of the previous value and the new measurement, so no measurement can be removed or overwritten. TF-A supports three backends:

BackendWhat it isNotes from the TF-A docs
TCG event logA log of each measurement in the crypto agile TCG_PCR_EVENT2 format from the TCG EFI Protocol SpecificationImages measured into PCR0, critical data into PCR1, following the Arm Server Base Security Guide
Discrete TPMA TPM chip that extends the same measurementsLets the TPM attest to the integrity of the event log
RSE (Runtime Security Engine)A separate security subsystem on some Arm reference designs that holds measurementsEarlier documents called it RSS; TF-A 2.15.0 removed host ROTPK retrieval from RSE

The event log is then handed to the next stage so the OS can read it and a remote verifier can replay it against the PCR values. That replay is what turns measurements into attestation: a verifier compares the reported log with known good hashes and decides whether to release a key or admit the device to a network.

Measured boot versus trusted board boot in TF-A

QuestionTrusted Board BootMeasured boot
What does it do on a bad image?Refuses to boot (panic)Records it and continues
Trust anchorROTPK in the chip, BL1 in ROMBL1 as root of trust for measurement
OutputNothing, unless it failsEvent log and extended PCRs or RSE slots
Who acts on the resultThe firmware itselfA verifier, a TPM policy or a key release service
Build flagsTRUSTED_BOARD_BOOT=1, GENERATE_COT=1MEASURED_BOOT=1 plus a backend
Protects againstUnsigned or wrongly signed imagesUndetected changes to signed but unexpected images and configuration

Production systems usually want both: authentication so unsigned code never runs, and measurement so a verifier can tell whether the signed code that ran was the expected version and configuration.

How are TF-A security advisories published, and how do fixes reach devices?

The upstream process

The TF-A security handling page says the project discloses all vulnerabilities it finds or is told about as Security Advisories listed in the documentation, and announces new ones on the project mailing list. Researchers are asked not to file security issues in the public tracker or on the mailing list but to follow the trustedfirmware.org security incident process, whose stated goal is to give makers of products that use TF-A time to assess a fix before it is public. The Trusted Firmware Security Center covers reporting, disclosure, handling of embargoed information and registration as a trusted stakeholder, which is how downstream companies get advance notice.

At the time of writing the advisory table runs from TFV-1 to TFV-17. Grouped by mechanism rather than by story, they fall into a few classes:

ClassAdvisoriesWhat it teaches
Untrusted SMC input reaching EL3 or BL1TFV-1, TFV-4, TFV-8, TFV-11, TFV-14Every SMC argument is attacker input; firmware update calls are a favourite path
Parsing boot inputs before trust is establishedTFV-10, TFV-15Certificate and FIP parsers run before authentication completes
Speculative execution and CPU errataTFV-6, TFV-7, TFV-9, TFV-13, TFV-16, TFV-17Firmware must apply errata workarounds and expose mitigations the OS can call
Register, debug and memory attribute handlingTFV-2, TFV-3, TFV-5, TFV-12Debug interfaces, timing registers and memory attributes must be configured and switched correctly between worlds

We list these to show the shape of the risk, not to recount any one bug. Read each advisory on the TF-A site for affected versions and fixes.

LTS backports

The LTS policy sets objective criteria for backporting. No features are backported. Any patch that appears in a security advisory is automatically selected, and patches can only come from the master branch, so master is always a superset of every LTS branch. LTS branches are named like lts-v2.14, and the playbook uses automated dependency update pull requests per LTS branch to keep third party code current. Testing support for LTS comes from the trustedfirmware.org CI.

The long road to the device

Upstream fixing a bug is the first of several steps:

  1. TF-A merges the fix to master and backports it to the active LTS branches.
  2. The silicon vendor merges it into the TF-A fork in its board support package, often alongside its own platform code and closed components.
  3. The device maker rebuilds the FIP, signs the new certificates with its production keys, and bumps the anti-rollback counter if the old image must never boot again.
  4. The update is delivered: through the OS vendor's firmware channel, a capsule update under UEFI, a vendor tool, or not at all for devices past their support window.

Each hand-off adds delay, and users rarely see which TF-A version they run, so ask for the version, LTS branch and advisory status in procurement. NIST SP 800-193, the Platform Firmware Resiliency Guidelines, frames the same need as protection, detection and recovery for platform firmware, including authenticated updates.

How to see what your device is running

On many boards the TF-A console prints version strings during boot (BL1 prints "Booting Trusted Firmware", and each stage prints a banner with its version and build string). From a running Linux system you can at least confirm what the firmware exposes:

# PSCI and SMCCC versions reported by firmware
dmesg | grep -iE 'psci|smccc'

# Does the device tree describe PSCI and an OP-TEE node?
ls /proc/device-tree/psci 2>/dev/null && cat /proc/device-tree/psci/compatible; echo
ls /proc/device-tree/firmware/ 2>/dev/null

# Is a TEE driver bound (OP-TEE or another TEE)?
ls /sys/bus/tee/devices/ 2>/dev/null; ls -l /dev/tee* 2>/dev/null

# Is there a TPM event log exposed to the OS?
ls /sys/kernel/security/tpm0/ 2>/dev/null

None of these tells you the exact TF-A tag. For that you need the vendor's release notes or the boot console log, which is another reason to ask for it in writing.

Step by step: build TF-A for QEMU with Trusted Board Boot and inspect the FIP

This walkthrough uses the QEMU virt platform, which the TF-A docs support directly. It runs entirely in an emulator, so nothing here touches real flash. The keys it generates are development keys: never ship them.

1. Install the prerequisites

You need an AArch64 cross compiler, GNU Make, OpenSSL development headers (used to build cert_create, encrypt_fw and fiptool) and QEMU. The TF-A prerequisites page lists the tested compiler versions and notes that OpenSSL 4 is not supported; it recommends an OpenSSL release that still receives security updates, typically an LTS release or a distribution maintained one.

# Debian or Ubuntu example; package names vary by distribution
sudo apt install build-essential git gcc-aarch64-linux-gnu \
    libssl-dev device-tree-compiler qemu-system-arm
aarch64-linux-gnu-gcc --version
openssl version
qemu-system-aarch64 --version

2. Get the source and pin a release

git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
cd trusted-firmware-a
git tag --list 'v2.1*' | sort -V | tail -5
git checkout v2.15.0
# Since 2.15.0, Mbed TLS is included in the repository
git submodule update --init --recursive

Pin to a tag, or to an lts-v2.x branch for products, rather than building whatever is on master. Record the commit hash in your build metadata.

3. Get a BL33

Download or build EDK II for QEMU as the platform page describes (QEMU_EFI.fd, built from ArmVirtPkg/ArmVirtQemuKernel.dsc), or use U-Boot built for qemu_arm64. Save it as bl33.bin next to the TF-A tree. Build a Linux Image and a small root file system (the TF-A page uses Buildroot's qemu_aarch64_virt_defconfig) if you want to boot all the way to a shell.

4. Build with Trusted Board Boot enabled

make CROSS_COMPILE=aarch64-linux-gnu- PLAT=qemu \
     BL33=../bl33.bin \
     TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \
     all fip
ls build/qemu/release/

TRUSTED_BOARD_BOOT=1 builds the authentication framework into BL1 and BL2. GENERATE_COT=1 makes the build run cert_create, which takes the images and keys (PEM files or a PKCS#11 URI when keys live in an HSM), creates any missing keys, writes the certificates in DER format, and hands them to fiptool. The output is bl1.bin and fip.bin, with the individual certificates also left in the build directory.

To add OP-TEE as BL32, build OP-TEE OS for QEMU first and pass its three images plus the dispatcher, exactly as the platform page shows:

make CROSS_COMPILE=aarch64-linux-gnu- PLAT=qemu \
     BL32=bl32.bin BL32_EXTRA1=bl32_extra1.bin BL32_EXTRA2=bl32_extra2.bin \
     BL33=bl33.bin BL32_RAM_LOCATION=tdram SPD=opteed \
     TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \
     all fip

5. Inspect the FIP

# The tool is built with the platform build; build it on its own if needed
make PLAT=qemu fiptool
FIPTOOL=./build/qemu/release/tools/fiptool/fiptool
$FIPTOOL info build/qemu/release/fip.bin

fiptool info prints one line per ToC entry with its name, offset, size and command line option, for example the trusted boot firmware (BL2), the SoC firmware (BL31), the non-trusted firmware (BL33) and each certificate. To look inside:

# unpack writes into the current directory and refuses to overwrite files
mkdir -p /tmp/fip-unpacked
(cd /tmp/fip-unpacked && "$OLDPWD/$FIPTOOL" unpack "$OLDPWD/build/qemu/release/fip.bin")
ls -l /tmp/fip-unpacked

6. Read the certificates

The certificates are ordinary DER encoded X.509, so OpenSSL can print them. The public keys and image hashes appear as non-standard extensions identified by object identifiers.

for c in build/qemu/release/*.crt; do
  echo "== $c"
  openssl x509 -inform DER -in "$c" -noout -subject -issuer -text \
    | sed -n '/X509v3 extensions/,/Signature Algorithm/p' | head -30
done

The build leaves files such as tb_fw.crt, trusted_key.crt, soc_fw_key.crt, soc_fw_content.crt, nt_fw_key.crt and nt_fw_content.crt (plus tos_fw_* when a BL32 is present). You should see the trusted boot firmware certificate holding the BL2 hash, the trusted key certificate holding two public keys, and a key and content pair for BL31 and BL33. Compare the BL31 hash in the SoC firmware content certificate with a hash you compute yourself:

sha256sum build/qemu/release/bl31.bin

7. Assemble a flash image and boot

The QEMU page concatenates BL1 and the FIP into one secure flash image. Warning: dd overwrites whatever of= names without asking. Here the target is a local file, flash.bin; before you adapt these lines for a real board, run ls -l on the output path and confirm it is not a block device such as /dev/mmcblk0 or /dev/sda.

dd if=build/qemu/release/bl1.bin of=flash.bin bs=4096 conv=notrunc
dd if=build/qemu/release/fip.bin of=flash.bin seek=64 bs=4096 conv=notrunc

qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57 \
    -kernel Image -append 'console=ttyAMA0,38400 keep_bootcon' \
    -initrd rootfs.cpio.gz -smp 2 -m 1024 -bios flash.bin -d unimp

secure=on gives the virtual machine the secure world memory and flash TF-A needs. Watch the console: BL1, BL2 and BL31 print notices as they load and authenticate each image.

8. Prove authentication works

Flip one byte in the BL33 payload inside a copy of the FIP and boot again. With Trusted Board Boot built in, BL2 computes a hash that no longer matches the non-trusted firmware content certificate and stops. Use fiptool update to replace one image without rebuilding the package:

cp ../bl33.bin /tmp/bl33-tampered.bin
printf '\x00' | dd of=/tmp/bl33-tampered.bin bs=1 seek=4096 conv=notrunc
cp build/qemu/release/fip.bin /tmp/fip-tampered.bin
$FIPTOOL update --nt-fw /tmp/bl33-tampered.bin /tmp/fip-tampered.bin

Rebuild flash.bin from the tampered FIP and boot it. The boot should halt at BL2 with an authentication error. This is the cheapest test you can run to confirm a chain of trust actually enforces anything.

9. Optional: turn on measured boot

The build options page describes MEASURED_BOOT as a flag that defaults to 0 and "can be enabled with TRUSTED_BOARD_BOOT" so that the code taking measurements is itself trusted. The QEMU platform makefile pulls in the TCG event log driver and QEMU specific BL1 and BL2 measurement code when it is set:

make CROSS_COMPILE=aarch64-linux-gnu- PLAT=qemu \
     BL33=../bl33.bin \
     TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MEASURED_BOOT=1 \
     all fip

Compare the digests recorded in the event log with sha256sum of the binaries, and check how your platform passes the log to BL33 before building attestation on top of it.

TF-A, UEFI on Arm, U-Boot and coreboot compared

These projects are often described as alternatives. On Arm they are usually layers.

TF-AUEFI on Arm (EDK II as BL33)U-Bootcoreboot
Role in the chainFirst mutable stage after ROM, plus the EL3 runtimeNormal world firmware that loads an OSNormal world bootloaderHardware init then payload, mostly on x86 and some Arm boards
Runs atEL3, Secure EL1, stays resident at EL3EL2 or EL1, exits at OS boot except runtime servicesEL2 or EL1 (can also be an earlier stage on some SoCs)Varies; on Arm it uses TF-A BL31 for EL3 services
Stays after OS bootsYes (BL31, BL32)Runtime services onlyNoNo (only tables it leaves behind)
Verifies the next stage withTrusted Board Boot (X.509 chain to ROTPK)UEFI Secure Boot (db, dbx, KEK, PK)FIT image signatures, public key in its device treevboot (signed firmware slots, root key in read only flash)
OS interfacePSCI, SMCCC, SDEI, FF-AUEFI boot and runtime services, ACPI or device treeDevice tree, bootefi UEFI subsetPayload specific
Typical systemsAlmost every Armv8 and Armv9 A-profile platformArm servers, Arm laptops, SystemReady devicesEmbedded boards, routers, many SBCsChromebooks, some open firmware laptops

Two specifications tie these together. EBBR (Embedded Base Boot Requirements) defines a subset of UEFI that U-Boot or EDK II provide so a generic distribution can boot an embedded Arm board. And the Arm server world expects UEFI plus ACPI above TF-A. Either way, TF-A sits underneath, and its chain of trust decides whether the UEFI or U-Boot binary you think you are running is the one that actually started. For U-Boot's own signing model see where the public key lives in U-Boot verified boot.

Common mistakes

  • Shipping development keys. TF-A includes development RSA and ECDSA private keys under plat/arm/board/common/rotpk/ so the reference platforms build out of the box, and cert_create will generate new keys if none are supplied. A product built with ARM_ROTPK_LOCATION=devel_rsa or with keys generated on a laptop has a chain of trust that anyone with the source can sign for. Generate production keys in an HSM and pass them by PKCS#11 URI.
  • Assuming the reference ROTPK check is implemented. On the Arm development platforms the ROTPK matching step is described as unimplemented. Check that your SoC port really compares against fused values.
  • Forgetting anti-rollback. Signed but old firmware is still signed. If the non-volatile counters are never incremented, a fixed vulnerability can be reintroduced by flashing the previous release.
  • Treating measured boot as protection. Measurements change nothing on their own. Without a verifier that reads the event log and acts on it, measured boot is a log nobody reads.
  • Building from master for a product. Use a tagged release or an LTS branch, record the commit, and track the advisory list for that branch.
  • Ignoring bundled third party code. A TF-A build pulls in Mbed TLS for certificate parsing and cryptography, libfdt for device trees, compiler runtime code and more. The change log records updates to these, and the build docs warn that the Mbed TLS version must be one that "fixes any known security vulnerabilities".
  • Skipping the OpenSSL version check for host tools. cert_create and fiptool link OpenSSL on the build machine. The prerequisites page says which versions are supported; an unmaintained OpenSSL on a signing host is a supply chain weakness of its own.
  • Exposing vendor SMCs without review. SiP services added by a silicon vendor run at EL3 with the same privilege as PSCI. Each one is attack surface that upstream never reviewed.

FAQ

Is Arm Trusted Firmware the same as Trusted Firmware-A?

Yes. The project was originally published by Arm as "ARM Trusted Firmware" and is now Trusted Firmware-A, one of the projects under trustedfirmware.org. The GitHub mirror still carries the older repository name, but the documentation, releases and code review are under the TF-A name.

Is TF-A a bootloader like U-Boot or GRUB?

No. TF-A is secure world firmware. It loads and authenticates the bootloader (BL33), then stays resident at EL3. U-Boot or UEFI runs as BL33 and loads your OS, and GRUB, if used, runs after that.

What is BL31 and why does it stay in memory?

BL31 is the EL3 Runtime Software. It stays in trusted SRAM after boot because it provides runtime services the OS calls through SMC, mainly PSCI power management, and it switches between the normal and secure worlds whenever OP-TEE or another secure payload runs.

Does every Arm device use TF-A?

Most Armv8-A and Armv9-A application processor platforms use TF-A or a vendor fork of it for EL3. Some vendors ship their own EL3 firmware or use TF-A only for BL31 behind their own boot ROM and loader. Microcontrollers based on Cortex-M use Trusted Firmware-M instead, which is a separate project.

Is OP-TEE part of TF-A?

No. OP-TEE is a separate Trusted Firmware project. TF-A loads it as BL32 and its BL31 contains an OP-TEE dispatcher (SPD=opteed) that starts it and routes calls to it. You can build TF-A without any BL32.

What is a FIP file?

A Firmware Image Package is the container TF-A loads images from. It has a table of contents with a UUID, offset and size for each entry, followed by the images and certificates. fiptool info lists its contents and fiptool unpack extracts them.

What is the ROTPK, and where is it stored?

The Root of Trust Public Key is the public key at the top of the chain. Production devices store it, or a hash of it, in hardware that software cannot change, such as the trusted root-key storage registers the TF-A documentation describes for its reference platforms. BL1 and BL2 compare certificate issuer keys against it.

How do I check which PSCI version my Arm board supports?

On Linux, run dmesg | grep -i psci. The kernel normally logs the PSCI version it detected in firmware, and on recent kernels the SMC Calling Convention version too. The device tree psci node under /proc/device-tree/psci shows the compatible string.

Does TF-A support a TPM?

Yes, as a measured boot backend. TF-A can record measurements in a TCG event log and extend them into a discrete TPM, so the TPM can attest to the log. On some Arm reference designs the Runtime Security Engine plays that role instead.

How long is a TF-A release supported?

Regular releases are every six months. Long term support branches receive security backports, and the TF-A LTS policy aims to support each LTS branch for at least seven years, with the caveat that CI infrastructure and maintainer availability may affect that.

Where Safeguard fits

Safeguard does not analyse firmware binaries, sign boot images, manage device fleets or check what runs at EL3 on a board. The fit here is indirect, and it is about the software around the firmware. A TF-A build is itself a supply chain: it vendors Mbed TLS, libfdt and compiler runtime code, its host tools depend on OpenSSL, and the BL33 and OP-TEE images you pair it with carry their own open source dependencies. The repositories, build containers and signing services that produce your firmware are ordinary software projects. Safeguard can scan those repositories, Dockerfiles and container images for known vulnerable components, record an SBOM for them, and evaluate policies and gates in CI, so the build environment that signs your FIP is held to the same standard as your application code.

Firmware has the longest update chain in computing, which makes the parts you control worth keeping clean. The cross compilers, OpenSSL linked host tools, build containers and BL33 and trusted application source that feed a TF-A build are open source dependencies, and they can be patched on your schedule even when the silicon vendor's firmware cannot; the vendor's TF-A fork itself still has to come from the vendor.

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 first demo is a real Safeguard CLI session in a repository: it reads a vulnerability finding, asks before each command, edits the dependency, runs the install and tests with your approval and pushes nothing. The same flow applies to the build tooling repository behind a firmware image, for example a Python based signing helper or the container that hosts your cross compiler.

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

The second demo sets up the Safeguard runner on your own machine, approves it with a device code and scans from the terminal. Firmware build hosts are often kept off shared CI for good reason, and a local runner lets you scan the build tree where it already lives.

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

The third demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. A firmware engineer can then ask questions about the dependencies in a build repository from the assistant they already use, without granting it more access than they choose.

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

Download the apps at https://safeguard.sh/download and read the CLI documentation at https://docs.safeguard.sh/docs/cli .

Quick check

Which TF-A stage stays resident after the operating system boots, and at which exception level?

BL31, the EL3 Runtime Software. It stays in trusted SRAM at EL3, provides PSCI and other SMC services, and switches between the normal and secure worlds. A BL32 trusted OS such as OP-TEE also stays resident, in the secure world.

In Trusted Board Boot, what is the difference between a key certificate and a content certificate?

A key certificate carries a public key used to verify the next certificate. A content certificate carries the hash of a boot image and its configuration. An image is accepted when its computed hash matches a content certificate whose signatures chain back to the ROTPK.

Sources

Last reviewed: 24 October 2026. TF-A build options, platform support and the advisory list change with every release; check the documentation for the release or LTS branch your firmware is built from.

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.