> ## Content Index
> Fetch the complete content index at: https://debugly.dev/llms.txt
> Use this file to discover other available public pages before exploring further.

# Google's $90K Pickle: One Key, Seven Properties, Zero Excuses
- URL: https://debugly.dev/google-devsite-pickle-rce/
- Published: 2026-10-13T15:00:00.000Z
- Updated: 2026-10-13T15:00:00.000Z
- Description: A session cookie became RCE on developers.google.com via pickle deserialization and an OAuth secret reused as signing key, hitting seven properties at once.
- Author: Rohit Bhadani
- Tags: Security, DevOps

The payout was $90,000, and the write-up reads like three separate bugs, but it is really one design failure repeated until the researcher could turn a session cookie into code execution on developers.google.com. The chain was: read the cookie, learn the signing key from it, forge a session with arbitrary Python pickle payloads, deliver them to the OAuth callback, and watch the server deserialize them. The blast radius was not one property, it was seven, because the signing key was shared across the DevSite platform, including firebase.google.com, developer.android.com and source.android.com. The bug is fixed, the payout is confirmed, and the lessons are the ones every Flask team should have learned years ago, except the class was taught on a shared Google platform and graded at $90,000.

The details here come from the researcher's own public account, cross-referenced with the confirmed payout and fix as reported in daily developer security briefings covering the week of 13 October 2026.

## The cookie was not the problem

Session cookies are supposed to be opaque. The failure in the chain was that the cookie's signing key was not only guessable, it was the same OAuth client secret that the platform used for authentication flow. That means anyone who could read the cookie's signing parameters, which is what the researcher did first, could then use that key to forge new sessions with payloads the server would trust. This is not a novel bug class, but it is a novel place to find it: a Google-shared developer documentation platform with a single signing secret across seven properties.

Once the forged session was valid, the OAuth callback accepted it and fed the cookie's payload to `pickle.loads`, the Python function that deserializes an arbitrary object graph. Pickle is not a data format, it is a code execution format, and calling `pickle.loads` on a client-supplied boundary is the same as calling `eval` with extra steps and a longer stack trace. The researcher demonstrated execution with `time.sleep` timing tests and negative controls, which is the responsible way to show a server will run your code without actually running your code.

The anti-patterns in this chain are the ones I keep in a checklist. I have watched [a URL fetcher trust metadata it should not have](https://debugly.dev/url-fetcher-read-the-metadata/), and the DevSite flaw is the same class of trust mistake: the server trusted the cookie's signature because the key was right, and it trusted the payload because pickle is Python's built-in format, and the two trusts combined into one RCE.

## One key across seven properties

The blast radius is the part that makes the $90,000 feel low. The DevSite platform is shared infrastructure, which means the signing key the researcher extracted was valid for at least seven Google developer properties. That is a design decision that turns a single-property RCE into a platform-wide RCE, and it is the design decision that made the payout a multiplier rather than a flat fee.

Shared signing keys are a cost-saving move that works until one property has a readable cookie, at which point the key is not shared, it is leaked. The right model is per-property or per-environment signing keys, rotated on their own schedule, with the OAuth client secret kept in a separate key hierarchy that never touches a session cookie's signing material. That is not a hard design, it is a boring design, and boring designs are the ones that do not appear in $90,000 bounty write-ups.

The comparison I keep coming back to is the way [a permission set inherits downward](https://debugly.dev/agent-inherited-the-engineers-permissions/) and turns a scoped mistake into a broad one. A shared signing key does the same inheritance: the mistake is scoped to one OAuth callback, but the key is inherited across every property that trusts it.

## Flask, pickle and the lessons that do not expire

The anti-patterns in this chain are not Google-specific. They are the patterns I have seen in internal tools, customer-facing dashboards, CI/CD consoles and dev-portal stacks across a decade of code review.

Never deserialize pickle across a client boundary. This is the single sentence that would have prevented the RCE. `pickle.loads` on a cookie value, a form parameter, a query string or a webhook body is code execution by design, and the fact that Python ships it as a standard library function does not make it safe, it makes it common.

Never reuse an OAuth secret as a session signing key. The OAuth client secret has a different lifecycle, a different trust boundary and a different compromise model than a session signing key. Reusing it as a signing key gives every session the same trust as an authentication flow, which is the wrong trust for a cookie.

Keep flow state server-side. The session cookie should be a random identifier that the server maps to state, not a container that carries serialized state across the wire. The moment the client carries the state, the client carries the code.

## What I now do

Every Flask app I review gets the same three checks on the first pass. First, find every `pickle.loads`, `yaml.load` and `marshal.loads` call and confirm the input source is server-side-only, because these are code execution entry points by design. Second, find the session signing key and confirm it is not shared with any OAuth, CSRF or API key material, and that the key is per-environment at minimum. Third, find every callback endpoint that accepts a signed cookie and confirm the signature validation is not the same key that signs authentication tokens.

These are not deep checks, they are surface checks, and the DevSite chain is the proof that surface checks matter when the surface is a shared platform. The $90,000 is Google's cost to learn it. The checklist is your cost to avoid it.