Securitylab•September 11, 2026•🇷🇺Translated from Russian

PKCE Becomes Mandatory for OAuth Public Clients as RFC 9700 and OAuth 2.1 Close Authorization Code Interception Risks

The OAuth authorization code grant was designed to avoid exposing user passwords to applications by issuing short-lived codes instead of tokens directly. However, public clients such as native mobile apps and single-page applications cannot securely store a client_secret, leaving intercepted codes vulnerable to exchange for tokens.

PKCE (Proof Key for Code Exchange), defined in RFC 7636, solves this by requiring the client to generate a high-entropy code_verifier (43–128 characters) and send its SHA-256 hash as code_challenge during the initial authorization request. The authorization server stores the challenge and later verifies it against the verifier supplied at the token endpoint.

Why mobile apps cannot rely on client secrets

Server-side applications keep secrets in environment variables, but native Android or iOS apps can be decompiled and browser-based applications expose all source code. Even protected storage like iOS Keychain or Android Keystore can be bypassed on jailbroken or rooted devices, making any embedded secret effectively public.

The attack PKCE was created to stop

Multiple applications can register the same custom URI scheme such as myapp://callback. When the authorization server redirects the code, the operating system may deliver it to a malicious app that quietly declared the same scheme in its manifest. RFC 7636 notes that such code interception attacks have been observed in the wild.

How PKCE works in practice

The client creates a code_verifier using a cryptographically secure random generator, computes the code_challenge as BASE64URL(SHA256(verifier)), and includes it with code_challenge_method=S256. At token exchange the original verifier is sent over a secure channel; the server recomputes the hash and rejects any mismatch with an invalid_grant error.

The plain method offers only limited protection and is deprecated in favor of S256, which is mandatory to implement on servers. Omitting the method parameter defaults to plain, silently weakening security.

Three distinct threats often confused

  • Code interception: malicious app steals the real user code via URI scheme collision.
  • Code injection: attacker supplies its own code to bind a victim session to the attacker account; PKCE blocks this even for confidential clients.
  • Downgrade: server accepts requests without a challenge, disabling verification entirely.

PKCE does not replace other safeguards

The state parameter still protects against CSRF, and nonce in OpenID Connect ensures ID token freshness. RFC 9700 allows relying on PKCE for CSRF protection only after confirming server support. PKCE also does not protect issued access tokens; sender-constrained mechanisms such as DPoP (RFC 9449) or mutual TLS (RFC 8705) address that layer.

Current status in 2025–2026

RFC 9700 (BCP) already requires PKCE for public clients and recommends it for confidential clients. The OAuth 2.1 draft (draft-ietf-oauth-v2-1-15) integrates PKCE into the core flow and removes implicit and ROPC grants. Providers differ in defaults: Auth0 and Okta enforce S256, while Microsoft Entra ID still documents both methods.

Even AI agent authorization frameworks such as the Model Context Protocol are adopting OAuth 2.1 with PKCE for HTTP transports where static secrets are impractical.

Related articles

Habr•Vulnerabilities & Exploits

Six Months After tun0 Leak: Which Android VPN Clients Fixed Server Address Exposure and Which Ignored It

A detailed investigation reveals that Android VPN clients suffer from two distinct server address leaks when split tunneling is enabled. The first leak, tied to an unprotected local SOCKS proxy on 127.0.0.1, was quickly mitigated by most Xray and sing-box based clients through random ports and passwords. The second, more persistent leak allows excluded applications to bind sockets directly to the tun0 interface and discover the VPN server IP without root or special permissions. Only TeapodStream and OlConnect implemented owner-UID checks using ConnectivityManager.getConnectionOwnerUid, yet both initially mishandled the INVALID_UID response returned for excluded apps. AmneziaVPN has unmerged pull requests that correctly reject unknown owners, while sing-box offers a manual package_name_regex rule. v2rayNG closed the report as not planned, and major clients including WireGuard for Android, Mullvad, Proton VPN and others have issued no statements.

Habr•Vulnerabilities & Exploits

Part 2: How Third-Party Developers Closed the tun0 Leak in AmneziaVPN on Android

Third-party contributors to AmneziaVPN have detailed their fix for a VPN tunnel bypass affecting excluded applications on Android. The vulnerability allows any app, even those disallowed from the VPN, to bind sockets directly to the tun0 interface using SO_BINDTODEVICE and thereby discover the VPN server address. The team implemented a packet filter inside the client that queries Android via ConnectivityManager.getConnectionOwnerUid to determine packet ownership and drops traffic from unknown UIDs. The solution was integrated into both the Xray and AmneziaWG traffic paths, with the AmneziaWG hook placed inside amneziawg-go after packet parsing. Testing with leak_probe.py showed zero successful bypass attempts out of six methods when the filter was active, compared to six out of six without it. The developers submitted three pull requests and released a side-loaded test build, while noting remaining limitations such as raw sockets and tethering scenarios.

BoletimSec•Vulnerabilities & Exploits

Cisco Confirms Active Exploitation of CVE-2026-76504 in Catalyst SD-WAN Manager

Cisco has confirmed that the critical vulnerability CVE-2026-76504 in Catalyst SD-WAN Manager has been exploited in attacks throughout September. The flaw carries a CVSS score of 9.8 and allows attackers to gain full administrator access without any credentials by bypassing API authentication through malformed URI encoding. The issue affects the login session handling mechanism, enabling forged requests to grant netadmin privileges by default. Similar URI manipulation techniques were observed earlier this month in Oracle PeopleSoft attacks. Patches are available across multiple release trains including 20.9.10.1, 20.12.8.2, 20.15.6.1, 20.18.4.1, 26.1.2.1 and 26.2.1, while older installations must migrate to supported versions. Cisco recommends restricting access to trusted hosts and placing the Manager behind firewalls until updates are applied. The vulnerability was discovered during routine support operations and verified by Cisco's Product Security Incident Response Team.

BoletimSec•Vulnerabilities & Exploits

Zero-Days in PaperCut MF Chained to Compromise Active Directory in Education Sector

Analysts at eSentire investigated an attack that chained two zero-days in PaperCut MF, tracked as CVE-2026-81578 and CVE-2026-82078, to move from an internet-exposed print server to a domain controller in an education sector client in under two days. Attackers gained initial access through the card or badge query field, delivering malicious Java code that allowed unauthenticated configuration changes and arbitrary bytecode execution on version 24.0.2. The first stage loader reassembled payload fragments in memory, launched the next stage, and deleted its own files while remaining compatible with multiple Tomcat versions. A web shell followed, accepting commands via a custom HTTP header, reading configurations, and erasing log traces while positioning itself early in the request processing chain. The command-and-control implant was AdaptixC2, hidden inside a modified Microsoft Copilot binary downloaded from Alibaba Cloud infrastructure. Privilege escalation was achieved without passwords by locating a domain-privileged service account, stealing its access token, and relaunching the implant under those rights. On the domain controller the payload arrived via administrative share and was executed by modifying the Windows PlugPlay service, after which the legitimate path was restored to minimize traces. The operators extracted credentials from memory and registry, enabled Restricted Admin mode, used an NTLM hash for RDP access, and copied the full Active Directory database containing passwords for all domain accounts.