Join our Newsletter — 33% off our NHI Course

Pointer Authentication Codes (PAC)

Pointer Authentication Codes, or PAC, are cryptographic tags attached to pointers on supported processors. The CPU checks the tag before using the pointer, which helps detect tampering with return addresses, function pointers, and similar control-flow data in memory.

What Pointer Authentication Codes Change About Control Flow

PAC strengthens memory safety by giving the CPU a way to verify that a pointer has not been altered before it is used. That matters most for return addresses, function pointers, and other control-flow targets that attackers often try to corrupt.

In practice, PAC does not remove memory corruption bugs, but it can make them much harder to turn into reliable code execution. If an attacker can overwrite a signed pointer without also producing a valid tag, the processor should reject the corrupted value rather than following it.

Where PAC Fits in Modern Defences

PAC is best understood as a hardware-backed integrity check for control-flow data, not as a full replacement for memory-safe design. It is strongest when paired with compiler hardening, exploit mitigation, and good code hygiene, because it only protects the pointers that are actually signed and checked by the platform.

Because PAC is implemented in the processor, its protection depends on the architecture and the software stack using it correctly. The security value is highest in code paths where pointer corruption would otherwise provide a direct route to hijacking execution.

How Attackers Try to Work Around PAC

Adversaries generally do not need to defeat PAC everywhere at once. They look for fallback paths, unsafely handled pointers, or adjacent bugs that let them redirect execution without relying on a protected control-flow target. If a program mixes signed and unsigned pointers, the weaker path can become the practical entry point.

PAC also does not stop attacks that abuse already-authorised logic, data-only manipulation, or other forms of compromise that never need to tamper with the protected pointer itself. That is why it should be treated as one layer in a defence-in-depth stack rather than a standalone guarantee.

Operational Meaning for Developers and Security Teams

For developers, PAC changes the payoff of memory corruption: some classes of overwrite become less useful to an attacker, but insecure pointer handling still remains a defect. For security teams, the main question is whether the target platform supports PAC, whether critical code paths benefit from it, and whether the application still has exploitable control-flow sinks outside those protections.

That is also why PAC should be discussed alongside secure coding, compiler settings, platform hardening, and exploit testing. A design that assumes PAC will save unsafe code usually underestimates how attackers pivot to the weakest available target.

For a broader primer on the underlying cryptographic idea, see Cryptography Basics Guide.

When evaluating deployment and hardening choices, it is also useful to compare PAC with the broader control and recovery lessons in Workforce Identity Security Guide and the authentication hygiene patterns in NIST SP 800-63 Digital Identity Guidelines.

Risk and Threat Considerations

PAC raises the bar for control-flow hijacking, but it does not eliminate the underlying risk from memory corruption. If attackers can corrupt pointers, combine bugs, or fall back to an unprotected execution path, they may still achieve code execution or persistence without breaking the tag check directly.

Failure mechanism: exploitation succeeds when an attacker finds a pointer, code path, or corruption primitive that is not protected by PAC, or when the software fails to apply PAC consistently across the places where control-flow data matters.

Impact: the likely consequence is reduced exploit reliability rather than no risk at all, with the remaining exposure shaped by other hardening layers, the quality of pointer signing, and the presence of adjacent memory-safety bugs.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

MITRE ATT&CK addresses the attack surface, NIST SP 800-53 Rev 5 sets the technical controls, and ISO/IEC 27001:2022 defines the regulatory obligations.

Framework Control / Reference Relevance
NIST SP 800-53 Rev 5 SC-39 — Process Isolation PAC is a hardware control-flow integrity aid that strengthens isolation of execution paths.
Recommendation — Use SC-39 to reinforce hardening where control-flow integrity and process separation matter most.
ISO/IEC 27001:2022 A.8.9 — Configuration management PAC deployment depends on secure build and platform configuration choices.
Recommendation — Control platform settings so PAC hardening is enabled and consistently maintained.
MITRE ATT&CK T1055 — Process Injection PAC addresses tampering with execution flow that attackers often seek through memory corruption.
Recommendation — Map execution-flow tampering attempts to T1055 and hunt for code paths that enable hijack.

Practitioner Guidance

What to watch for: treat PAC as a platform control that should be validated, not assumed. Verify that supported targets actually compile and run with the intended pointer-authentication protections enabled, and confirm that critical code paths are not silently bypassing them through legacy build settings or incompatible components.

Governance implication: teams should decide which applications and device classes rely on PAC as part of their exploit-mitigation posture, then test that assumption during secure development review and regression testing. PAC is most useful when it is treated as one measurable hardening feature inside a broader memory-safety strategy.