Epic Games PIN Bypass: When the Server Lets the Client Decide Whether It Was Right
V-Spot identified a parental controls bypass on Epic Games where the server enforced a rate-limited PIN check, but a client-side manipulation of the response body was sufficient to convince the client that a wrong PIN had succeeded. The finding is small in the specific case and large in its implications. Any authentication mechanism that trusts a client-modifiable response as the authoritative record of its own outcome carries this bug by construction.
While assessing Epic Games' parental controls flow, V-Spot's research division identified a bypass on the PIN verification endpoint. The server correctly rate-limited failed PIN attempts and returned a JSON response indicating success or failure. The client used the boolean in that response to decide whether to unlock the parental controls panel. Flipping the boolean from false to true in an intercepted response was sufficient to convince the client that a wrong PIN had succeeded, and the panel unlocked without any further server-side authorisation check.
The bypass is small. The class of problem is not. This is V-Spot's writeup of the specific finding and the wider lesson on client-side trust boundaries in modern authentication design.
What actually happened
The reproduction is short. Any Epic Games account with parental controls configured can be used to reproduce it end to end.
The parental controls PIN check works as follows. The client sends the entered PIN to a server endpoint. The server verifies the PIN against the account, returns a JSON response containing a success boolean, and applies rate-limiting to unsuccessful attempts. On repeated wrong attempts, the server returns a "too many attempts" error and denies further PIN checks for a short window. This is the intended flow.
To identify the bypass, V-Spot researchers ran a controlled sequence:
1. Log into an account with parental controls enabled and a PIN configured.
2. Navigate to the parental controls panel and initiate a PIN check.
3. Submit 100 to 300 wrong PIN attempts to trigger the rate-limit response.
4. Wait 15 to 30 seconds for the rate-limit backoff to reset the server-side counter enough to return a substantive PIN-check response rather than a bare error.
5. Submit a further wrong PIN.
6. Intercept the server response with a proxy.
7. Modify the response body to change the success value from false to true.
8. Forward the modified response to the client.
The client received a response consistent with a correct PIN, treated the account as authenticated for the parental controls panel, and rendered the panel. No further server-side check occurred before sensitive account settings became modifiable.
Why this is a design bug, not a bug bug
The specific behaviour reads like a coding error, but the underlying cause is architectural. The server did its job. It correctly verified the PIN, correctly returned false, and correctly rate-limited the flow. The client also did its job. It read the response and unlocked the panel. What broke is that the client's decision to unlock the panel was based on the client's own copy of the response, which a determined attacker could modify before the client read it.
The correct design places the authorisation decision on the server. In a server-authoritative model, the client's role after PIN verification is not "read the response and decide what to unlock." It is "ask the server, for each subsequent sensitive action, whether the user has an active elevated session." The server tracks whether a valid PIN check has recently succeeded, and every sensitive action either includes that session context or is denied.
The client-authoritative model, where the client reads a success flag and self-elevates, is common because it is fast to implement, works cleanly in web SPAs, and produces a smooth UX when everyone plays by the rules. It is also structurally unable to defend against an attacker who controls their own browser, which is every attacker.
This class of design bug appears across many product surfaces. V-Spot has separately documented the same class in a two-factor authentication flow, where the client flipped a requires_2fa field to null in the response and skipped the 2FA prompt entirely. The parental controls and 2FA cases are the same bug wearing different clothing.
The impact on the specific product
Parental controls exist to give guardians control over what child accounts can access, spend, or install. When the PIN check can be bypassed, the intended access-control model is inverted. A child account holder who is technically inclined enough to install a browser proxy (which is well within the capability of many teenagers) can unlock the panel and modify their own restrictions. In-app purchase caps become editable, chat restrictions become removable, and mature-content filters become toggleable. The parental controls exist, but the enforcement layer has been removed.
The specific finding was reported responsibly to Epic Games. The wider parental controls product category has structural exposure to this class of bug across the industry, because parental controls typically receive lower security-engineering priority than user-account authentication despite serving a comparable trust function.
Why parental controls attract this bug class
Two factors make parental controls particularly susceptible. The first is that they sit inside an already-authenticated session. The user is logged in. The extra check is a PIN, not a full re-authentication. That framing invites developers to model the PIN as a lightweight ceremony rather than as a security boundary. Lightweight ceremonies get lightweight implementations, and lightweight implementations tend to trust the client.
The second is that the threat model for parental controls is uncommon relative to other security boundaries. The attacker is inside the household. They have credential access. They have physical access to the device. In every other product category, an attacker with credential access and physical access is already the account owner, and the security architecture assumes the boundary has already been crossed. Parental controls are one of the few product categories where the threat model requires defending against exactly that attacker. Most security-engineering intuition is trained against a different profile, and the resulting designs reflect the mismatch.
Seven concrete moves for teams shipping in-session privilege elevation
If your product uses a PIN, a re-authentication prompt, or any similar client-side privilege elevation, the moves below are the ones V-Spot researchers would prioritise:
1. Model the elevation server-side. After a successful PIN check or re-authentication, the server records that the session has an elevated capability, with an expiry time. Every subsequent sensitive action confirms the elevation server-side rather than trusting a client flag.
2. Never rely on a client-inspectable response to gate a sensitive action. If the client can read the response, the client can modify the response. The client's read is not a security boundary.
3. Apply the same rate-limit discipline to the successful response path as to the failure path. Many elevated actions become uneconomical for attackers when the server enforces a low ceiling on how quickly successive elevation-required actions can occur.
4. Log every elevation attempt server-side, including the ones that succeeded. Anomalies in the elevation pattern (successful elevation from an unusual IP, elevation followed immediately by high-privilege actions, elevation attempts clustered around known credential-stuffing waves) are the leading indicators of exactly this bypass class.
5. Include a server-side re-verification on high-value actions inside an elevated session. Adding a payment method, changing an email address, disabling parental controls, and comparable high-value actions should re-verify the PIN or re-authenticate rather than trusting the ambient elevation state.
6. Treat parental controls as authentication. The design discipline applied to primary account authentication should be applied to parental controls. The threat model is different, but the design principles are the same.
7. Audit the client-server contract for authorisation decisions specifically. Any point where the client decides its own permissions based on the content of a response is a candidate for this bug class, whether or not the specific flow has been probed by researchers.
The V-Spot lens
Client-side trust boundaries are one of the most persistent design mistakes in modern product engineering. The pattern of "server returns a flag, client reads the flag, client decides its own state" is deeply embedded in the SPA-plus-JSON-API stack that most consumer products are built on. It is also structurally indefensible against an attacker with proxy access to their own browser.
The Epic Games finding is a specific example of the class. It is not the only example, and it is not the most consequential example V-Spot has documented. The consequential examples are the ones where the elevated capability protects something more sensitive than parental controls. The specific finding here matters because it demonstrates the class on a product where the intended defender (the parent) is unlikely to know the bypass exists, and where the intended attacker (the child) is likely to encounter documented instructions for the bypass within minutes of searching for them.
If your product uses any form of in-session privilege elevation, or you are auditing an existing flow for this class of bug, V-Spot's research division and offensive security team can help. This bug class is quick to spot when you know what to look for. Finding it before an attacker does is the point.