Join our Newsletter — 33% off our NHI Course

What happens when PAC is used without complementary controls like BTI?

The attack surface narrows, but control flow protections remain incomplete. PAC verifies pointer authenticity, while Branch Target Identification constrains where indirect branches may land. Used alone, PAC can slow exploitation, yet valid targets and usable gadgets may still exist. The practical lesson is to combine pointer authentication with branch target controls and secure coding.

Why Pointer Authentication Alone Does Not Close the Control-Flow Gap

Pointer Authentication Codes, or PAC, raise the cost of control-flow hijacking by making selected pointers harder to forge, but they do not by themselves prevent every indirect branch abuse pattern. Without complementary branch-target hardening such as BTI, an attacker may still steer execution toward valid landing sites or reuse existing code paths that remain acceptable to the processor. That matters because control-flow integrity is only as strong as its weakest remaining transition point.

The distinction is important for defenders because PAC protects authenticity of some pointers, while BTI constrains where indirect branches may legally land. Those are related but different assurances, so treating PAC as a complete substitute for branch-target validation creates an incomplete mental model of exploit resistance. In practice, many security teams discover the gap only after seeing a partially blocked exploit still find a usable path through legitimate targets rather than through forged pointers.

For a broader control perspective, NIST SP 800-53 Rev 5 describes how layered safeguards work best when one control does not carry the whole assurance burden, and the same principle applies here even though the mechanism is architectural rather than policy-driven. The lesson is not that PAC is ineffective, but that its value depends on the surrounding code-generation and hardening model.

How PAC Behaves in Real Exploitation Chains

PAC is designed to bind a pointer to a signing context so that tampering becomes detectable when the pointer is later reused. That is most useful against straightforward pointer corruption, return-oriented manipulation, and some forms of control-data abuse. BTI addresses a different problem: whether an indirect branch can land at a given instruction boundary at all. When BTI is absent, the set of acceptable landing points is wider, which means valid code sequences may still be reachable even if some pointers are authenticated.

In practical terms, the security outcome depends on what the attacker can still control after PAC enforcement. If a forged pointer fails authentication, the attacker may pivot to an already-authenticated object, a valid function pointer, or a sequence of gadgets that does not require pointer forgery in the first place. This is why PAC often reduces exploit reliability rather than eliminating exploitability. It can force attackers to work harder, but it does not necessarily remove the usable control surface.

  • PAC is strongest when the protected pointer is both difficult to predict and difficult to replace with an authenticated equivalent.
  • BTI adds value by shrinking the executable landing zone for indirect branches, which reduces the number of viable reuse targets.
  • Secure coding still matters because memory corruption that reaches adjacent objects, callbacks, or vtables can bypass a single hardening layer.

That combination is why defenders should think in terms of layered control-flow protections, not isolated mitigations. Where a platform or build configuration uses PAC without BTI, exploit chains may shift rather than disappear, and the remaining paths tend to be the ones most exposed by legacy code, broad gadget availability, or inconsistent compiler hardening.

Where the Single-Control Approach Breaks Down

Tighter control-flow protection often increases implementation complexity, requiring organisations to balance exploit resistance against compatibility and performance constraints. That tradeoff becomes visible when codebases include mixed compilation settings, hand-written assembly, third-party binaries, or paths that were never designed for strict branch-target enforcement.

There is also an important consensus point: the industry broadly agrees that pointer authentication and branch-target constraints are complementary, but there is not universal agreement on how much residual risk remains in any specific application without deeper code review. The real exposure depends on the attack surface, the quality of memory-safety practices, and whether the application exposes enough reusable logic for an attacker to build a working chain.

Where teams get into trouble is assuming that one architectural control can compensate for weak memory-safety discipline everywhere else. PAC can make exploitation less reliable, but if the application still exposes predictable call sequences, broad reuse opportunities, or unsafe object lifetimes, the remaining paths may still be practically exploitable.

Standards & Framework Alignment

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

MITRE ATT&CK address the attack and risk surface, while CIS Controls v8 and NIST CSF 2.0 set the governance and control requirements practitioners need to meet.

Framework Control / Reference Relevance
CIS Controls v8 8 — Audit Log Management Control-flow hardening needs observable validation and review points.
Recommendation — Verify and monitor hardening states so missing branch protections are detected early.
MITRE ATT&CK T1211 — Exploitation for Defense Evasion Attackers may still abuse legitimate execution paths despite pointer signing.
Recommendation — Hunt for exploit chains that reuse valid code paths rather than forged pointers.
NIST CSF 2.0 PR.IP-1 — Baseline Configuration PAC-only deployment leaves an incomplete hardening baseline.
PR.DS-5 — Data, Hardware, and Software Integrity PAC protects integrity of pointers but not every branch destination.
Recommendation — Define a hardened baseline that includes both pointer and branch-target protections. Treat pointer integrity as incomplete unless branch destinations are also constrained.

Practitioner Guidance

What to verify: Confirm whether PAC is being used as part of a broader control-flow hardening posture or as a stand-alone mitigation. The useful question is not whether PAC is enabled, but whether the code base still allows indirect branches, callbacks, or object reuse paths that remain reachable without a forged pointer.

What practitioners underestimate: Teams often overvalue pointer authenticity and undervalue landing-point restrictions. That mistake matters because exploitability is determined by the full chain, not by the strongest single link.

Decision rule: If the application contains high-value control-flow targets or memory-corruption exposure, treat PAC-only deployment as partial protection and prioritize branch-target hardening plus secure coding review. If those conditions are absent, the residual risk may be lower, but it is still not zero.

Practitioner takeaway: PAC without BTI usually improves resilience, but it does not deliver full control-flow integrity, so security teams should judge it as a risk-reduction layer rather than a complete answer.