An app can be inside a sandbox and still reach a service that makes decisions on its behalf. The interesting question is what that service believes about its caller.
While reviewing macOS, I followed that question into PPPController, the component inside configd that manages legacy PPP connections. The investigation reached a privileged VPN process from App Sandbox. Separate tests also redirected L2TP connection attempts to a listener I controlled.
Apple credits this work under CVE-2026-112542 in its macOS Sequoia 15.8.2 security advisory. Apple describes a permission issue with potential network interception impact and says it added restrictions. This note explains the historical tests behind my report, including the limits that matter when describing the blast radius. Apple’s advisory
- The case
- CVE-2026-112542
- System boundary
- App Sandbox → VPN controlExisting PPP/L2TP service required
- Public advisory
- Apple · pppmacOS Sequoia 15.8.2
The assumption at the boundary
The boundary I wanted to test was simple: being able to contact a system service should not give an app authority to control an existing VPN connection.
PPPController exposed two routes into that decision. One was the UNIX socket at /private/var/run/pppconfd. The other was the Mach service com.apple.SystemConfiguration.PPPController, reachable through SCNetworkConnectionStart.
The socket path made the trust problem especially clear. The implementation obtained the peer’s credentials using getsockopt with LOCAL_PEERCRED, but the client-creation call used zero values for the identity fields instead. The identity was available at the boundary; it was not carried through the decision that followed. The runtime record later attributed a start request to (0) kernel_task rather than the application that sent it.
There was an important prerequisite: a configured PPP/L2TP service had to exist already. The service lookup rejected an unknown service. This was control over an existing connection, not evidence that an app could create arbitrary system VPN configurations.
From a sandboxed app to a privileged service
The first useful result was not just a successful socket connection. In the 26 August 2026 test on macOS Tahoe 26.6, build 25G72, the start request was accepted and a pppd process appeared under configd with UID 0.
The app was running with App Sandbox enforced. Its entitlement file included both com.apple.security.app-sandbox and com.apple.security.network.client. Controls in the record showed other local socket destinations denied, and a file write outside the container was blocked. Those checks matter: an unrestricted command-line process would not establish the same boundary crossing.
The captured response to the socket start request was:
RESPONSE: type=0x0003 result=0x00000000 cookie=0xdead9001 link=0x00050000
The process snapshot recorded the resulting service:
PID PPID USER UID GID STAT COMMAND
12230 369 root 0 0 Ss pppd serviceid B53A0B91-EF59-414B-8206-680F8E27ADC7 controlled
This established a concrete privileged effect: an app confined by App Sandbox could cause this system service to start. It did not establish arbitrary command execution as root. The process was Apple’s pppd, carrying out the connection workflow.
Blast radius: what we actually reached
The evidence spans different entry points and different runs. Treating them as one uninterrupted exploit would hide the conditions under which each result occurred. The map below keeps those conditions attached to the result.
How far did it reach?
Follow each test to its last demonstrated effect.
A privileged service,
started.
- Sandboxed appApp Sandbox
+ network.client - Legacy socketpppconfd
Start accepted - configdRequest attributed
to kernel_task - pppdUID 0
Service launched
Reached: a privileged VPN service action from App Sandbox. Starting this daemon did not establish arbitrary root code execution.
A destination,
redirected.
- Local processOutside
App Sandbox - PPP optionsNew destination
127.0.0.1 - L2TP serviceSupplied test
credentials - 54 packetsLoopback listener
Control traffic
Reached: the chosen network destination. This capture did not demonstrate a completed tunnel or intercepted user traffic.
The credential chain
stops here.
- Sandboxed appStored username
Four attempts - Start APIRequest accepted
pppd started - Keychain APILookup invocation
Recorded in log - 0 packetsNo dial
No credential capture
Limit: credential handling was reached, but delivery was not. The receiver recorded no traffic in these four attempts.
Each view is a separate test. The observations are not combined into a single end-to-end exploit.
The practical reach was into an existing legacy VPN service: accepting a start request, launching its process, reaching credential-handling code, and — in a separate API test — changing where its L2TP connection attempt went.
For a machine that uses that service, these are consequential authority decisions. The affected resource is the configured VPN connection and its system-managed workflow. The tests do not establish control over every VPN product, all network traffic on the Mac, or other users’ keychain items.
Following the destination onto the wire
To test destination control, I set CommRemoteAddress to 127.0.0.1 and listened on the loopback interface. This kept the observation on my own machine. The API returned success, and the listener captured 54 L2TP control packets on 26 August.
These are selected lines from that capture. The process was outside App Sandbox for this run and supplied test credentials; that context stays with the result.
[15:37:18.487] sandbox_check = 0 (NOT SANDBOXED)
[15:37:18.493] SCNetworkConnectionStart returned: TRUE
[15:37:18.699] *** CAPTURED PACKET #1: 20 bytes from 127.0.0.1:60636 ***
[15:37:24.033] Total packets captured: 54
The first captured packet contained these bytes:
0000: c8 02 00 14 00 00 00 00 00 00 00 00 80 08 00 00
0010: 00 00 00 06
The receiver established that the connection attempt reached the chosen destination. These were control packets. They do not, by themselves, demonstrate a completed VPN tunnel, intercepted application traffic, or a password arriving at the listener.
Credential-theft path: System Keychain to PPP authentication
The credential path is the most consequential part of the report. The question was whether an app could choose a new VPN destination while the system supplied a credential belonging to an existing connection.
PPPController looked for a password in the caller’s options and then fell back to the stored service configuration. When that configuration selected Keychain-backed storage, the controller passed a keychainpassword reference into pppd. The destination and the credential could therefore come from different trust sources: the caller selected the address, while the existing service supplied the password reference.
The password’s route.
A code path, with its evidence attached.
- 01Choose a new VPN destinationObserved in a separate API test
CommRemoteAddress → a listener under my control.
- 02Reach stored-credential handlingAPI invocation observed
Existing service → Keychain lookup by pppd.
- 03Copy the returned passwordStatic binary trace
On lookup success → memmove → buffer 0x10004964c.
- 04Pass that buffer to PAPStatic binary trace
The same address → _upap_authwithpeer.
- 05Receive the credential at the endpointNot captured
Requires a completed tunnel and authentication exchange.
The first two observations came from the named test runs. The final delivery step was not demonstrated; the later stored-account retest stopped before dialling.
The binary trace connected the password-retrieval code to PPP authentication through the same buffer address, 0x10004964c. On a successful Keychain lookup, pppd copied the password into that buffer. Its PAP path later passed that buffer to _upap_authwithpeer. These addresses identify the historical binary analysed in the report; they are not universal offsets for other macOS builds.
Selected instructions from the archived disassembly:
100003efc: bl SecKeychainFindGenericPassword
100003f00: cbz w0, 0x100003e2c
100003e44: add x20, x20, #0x64c
100003e48: mov x0, x20
100003e4c: bl memmove
100001320: add x2, x2, #0x64c
100001328: bl _upap_authwithpeer
The runtime record reached the retrieval API too. This raw line belongs to the socket-path process:
2026-08-26 14:14:40.630 A pppd[12230:152b068] (Security) SecKeychainFindGenericPassword
What was achieved: sandbox access to the connection-start operation and privileged daemon startup; a separate destination-override test delivered L2TP packets to my listener; runtime logs reached the credential API; and the binary trace linked a successful retrieval to the PAP password buffer.
What the archive does not establish: a stored password arriving at the receiver. A function invocation is not a dump of its returned bytes, and the captured L2TP control packets are not PPP authentication packets. The credential-delivery step was traced in code, not captured end to end on the wire.
If a hostile endpoint completed the required tunnel and negotiated PAP along that path, it could receive the VPN username and password. PAP supplies the password to its peer; that does not imply an IPsec pre-shared key is itself transmitted in plaintext. The recorded tests did not complete this credential-capture scenario.
The possible downstream blast radius would then depend on where that VPN credential is accepted and what additional authentication is enforced. VPN-user impersonation is a consequential risk; corporate-network access, lateral movement, and compromise of internal services were not demonstrated here.
What the later retest changed
On 2 October 2026, the test machine was running macOS 27.0.1, build 26A434. The later record reproduced sandbox access to both entry points, but it also made the limits more specific.
- The socket path still started a root
pppd. The request was accepted and keychain API activity followed, but this attempt did not dial the listener. - The API path was now measured inside App Sandbox. It returned success and launched
pppdthroughnesessionmanager. That process had real UID 501 and saved UID 0. Calling every API-path instance a “root process” would lose that distinction. - The stored-account attempts stopped before network delivery. Across four sandboxed attempts with the real stored username and an attacker-selected shared secret, the listener received zero packets. Keychain API activity was recorded, but there was no dial and no captured credential.
- A separate test with supplied credentials still dialled loopback. An unsandboxed run captured 55 control packets before the IPsec connection failed. Another variant with an invented username produced a visible VPN credential prompt; its responder failed before authentication completed.
Those results narrow the claim. They do not justify a silent credential-theft demonstration, and they do not establish a complete phishing chain. They also should not be read as a statement about today’s patched macOS releases: these are observations from the named historical builds, while Apple’s public advisory separately identifies its Sequoia fix.
Remediation: keep the caller and credential bound together
The architectural lesson is to bind a service action to the caller who requested it. On the socket path, that means preserving and checking the peer identity before starting or changing a connection. Equivalent actions through the Mach interface need an equivalent authorization decision.
Connection options need their own trust boundary too. A caller’s ability to reach an API should not silently grant permission to combine a new destination with credentials belonging to an existing system-managed service.
These are recommendations derived from the observed implementation. Apple’s advisory describes additional restrictions; this note does not claim to reconstruct Apple’s exact patch. Security content of macOS Sequoia 15.8.2
Affected setup, update, and researcher credit
For the path described here, a local application needs to run on a Mac with an existing configured PPP/L2TP service. The sandbox tests used the normal outgoing-network entitlement as well as App Sandbox. The results do not describe every VPN implementation.
Apple documents the fix in macOS Sequoia 15.8.2, released on 26 October 2026. Install the current security updates for your macOS release; the historical builds used in the research are not a recommendation to remain on them. Apple’s release advisory
CVE: CVE-2026-112542 · Apple component: ppp
Reported finding: Unauth PPPController interfaces in configd allow cred theft and traffic redirect from App Sandbox
That is the report title. The evidence distinctions above apply to its credential-theft wording.
Apple credits Gabriel ‘0xv1n’ Cardona, Mrunal Chawda, Kujtim Kryeziu (Sentry), and Tristan Madani (Talence Security). The public fix is documented in Apple’s macOS Sequoia 15.8.2 advisory.
This article draws on my original PPPController report, the archived packet and process records, and the later rogue-server retest. The central finding is the authority decision: an App Sandbox caller reached an existing VPN’s system-managed workflow. The credential path explains why that boundary matters, while the recorded outcomes define how far the demonstration reached.
Thanks for following the question.
Continue the conversation on X ↗