Follow My Flow: Unveiling Client-Side Prototype Pollution Gadgets from One Million Real-World Websites
Zifeng Kang, Muxi Lyu, Zhengyu Liu, Jianjia Yu, Runqi Fan, Song Li
IEEE Symposium on Security and Privacy 2025 · Day 1 · Web Security
Overview
This talk introduces "Follow My Flow," a groundbreaking research effort to identify and analyze client-side prototype pollution gadgets across a vast dataset of real-world websites. Presented by Sungcom from Johns Hopkins University, this work addresses the critical challenge of discovering exploitable vulnerabilities stemming from prototype pollution, a JavaScript flaw that allows attackers to inject malicious properties into built-in prototypical objects. While prototype pollution itself is a known vulnerability, its true impact materializes only when a "gadget"—a seemingly benign code snippet—unknowingly processes these polluted properties, altering program flow to a sensitive location and leading to severe consequences like cross-site scripting (XSS), cookie manipulation, or URL manipulation. The paper detailing this research was recognized with a distinguished paper award, underscoring its significance in the field of web security.

Key moments
- 0:00 Introduction to prototype pollution and gadgets
- 1:30 Real-world impact: Meta/assc.com cookie manipulation example
- 2:15 Technical deep dive into the assc.com vulnerability
- 4:00 Core challenge: complex format checking constraints
- 4:45 Gala's novel solution: borrowing values from reference websites
- 6:10 Gala framework: three-phase automatic detection process
- 7:00 Detailed system architecture of the Gala tool
- 9:00 Evaluation results: 133 zero-day gadgets discovered
Follow My Flow: Unveiling Client-Side Prototype Pollution Gadgets from One Million Real-World Websites
Speakers: Zifeng Kang, Muxi Lyu, Zhengyu Liu, Jianjia Yu, Runqi Fan, Song Li
Conference: IEEE S&P
YouTube: https://www.youtube.com/watch?v=gzQDFARUkfQ
Overview
This talk introduces "Follow My Flow," a groundbreaking research effort to identify and analyze client-side prototype pollution gadgets across a vast dataset of real-world websites. Presented by Sungcom from Johns Hopkins University, this work addresses the critical challenge of discovering exploitable vulnerabilities stemming from prototype pollution, a JavaScript flaw that allows attackers to inject malicious properties into built-in prototypical objects. While prototype pollution itself is a known vulnerability, its true impact materializes only when a "gadget"—a seemingly benign code snippet—unknowingly processes these polluted properties, altering program flow to a sensitive location and leading to severe consequences like cross-site scripting (XSS), cookie manipulation, or URL manipulation. The paper detailing this research was recognized with a distinguished paper award, underscoring its significance in the field of web security.
The core contribution of this research is Gala, an open-source dynamic analysis framework designed to automatically detect these elusive client-side gadgets. Gala employs a novel technique to overcome the complex format checking constraints often present in client-side JavaScript, a major hurdle for prior detection methods. By "borrowing" valid execution values from reference websites, Gala can effectively bypass these constraints and demonstrate exploitability. The team's findings are substantial, revealing 133 zero-day gadgets across more than 5,000 real-world websites, highlighting the widespread nature and potential impact of this class of vulnerabilities.
The work presented by the team from Johns Hopkins University and Jiang University not only sheds light on a significant, under-explored attack surface but also provides a practical framework for its detection. The responsible disclosure of discovered vulnerabilities, including a bug bounty from Meta and a CVE identifier for a vulnerability in V 2.6, further validates the real-world applicability and impact of their methodology. This talk is crucial for security researchers, web developers, and anyone interested in advanced client-side vulnerability analysis and mitigation.
Background
▶ Watch: Introduction to prototype pollution and gadgets (0:00)
Prototype pollution is a JavaScript vulnerability rooted in the language's prototypical inheritance model. In JavaScript, objects can inherit properties and methods from other objects through their prototype chain. At the top of this chain sits Object.prototype, which serves as the base for almost all JavaScript objects. A prototype pollution vulnerability occurs when an attacker can inject arbitrary properties into Object.prototype or other constructor prototypes. Once polluted, any object that inherits from Object.prototype (which is most objects) will unknowingly acquire these injected properties. This can lead to unexpected behavior and, critically, security vulnerabilities.
However, prototype pollution alone is often not sufficient for a practical exploit. It requires a gadget. A gadget is a piece of code that, while appearing harmless under normal execution, becomes malicious when specific properties are polluted. These gadgets typically involve operations that access object properties without proper validation or sanitization, leading them to process the attacker-controlled data from the polluted prototype. For instance, a gadget might concatenate strings, assign values to sensitive properties, or dynamically load scripts using the polluted input, thereby changing the normal program flow to a sensitive location or sink. Common sinks include document.cookie for cookie manipulation, eval() or innerHTML for XSS, or location.href for URL manipulation.
The problem of detecting client-side prototype pollution gadgets is particularly challenging due to the dynamic nature of JavaScript and the complexity of modern web applications. Prior work in this area has faced significant limitations. For client-side gadget detection, tools like props_the_proto primarily rely on predefined values for exploitation, making them ineffective against gadgets with complex format checking constraints. For example, if a gadget expects an input string with a specific number of dots or segments (e.g., F.1.cookie value), props_the_proto cannot generate such a complex payload. Similarly, server-side gadget detection tools, such as EOPF, which employ constraint solvers, struggle with the intricacies of client-side JavaScript, including complex string operations and dynamic features that are not easily modeled by these solvers. This gap highlights the need for a more sophisticated approach capable of understanding and bypassing these client-side specific challenges.
The talk illustrates this problem with a compelling real-world example: a vulnerability discovered in fbvents.js, a library developed by Meta, affecting a website named assc.com. In this scenario, assc.com was vulnerable to prototype pollution, and it also included the fbvents.js library which contained a gadget. An attacker could craft a malicious URL to trigger prototype pollution on assc.com, injecting attacker-controlled cookie data into Object.prototype. The fbvents.js gadget, designed to process certain values, would then unknowingly pick up this polluted data, leading to cookie manipulation where the victim's cookies could be controlled by the attacker. This specific vulnerability was disclosed to Meta, leading to a quick fix and a bug bounty, underscoring the real-world impact and the necessity of effective detection mechanisms.
Key Findings
▶ Watch: Technical deep dive into the assc.com vulnerability (2:15)
The research presented in "Follow My Flow" yielded a significant breakthrough in identifying client-side prototype pollution gadgets, demonstrating their widespread prevalence and potential for severe impact. The central finding is the discovery of 133 unique zero-day gadgets across an astonishing over 5,000 real-world websites. This scale of discovery highlights that prototype pollution, when combined with these exploitable gadgets, constitutes a pervasive and under-addressed threat in the modern web ecosystem.
These gadgets were categorized by their potential consequences, revealing a diverse range of attack vectors:
- Cross-site Scripting (XSS) Gadgets: 56 gadgets were found that could lead to XSS, allowing attackers to inject and execute arbitrary scripts in the victim's browser, enabling session hijacking, data theft, and defacement.
- Cookie Manipulation Gadgets: 27 gadgets facilitated the manipulation of victims' cookies, as exemplified by the
fbvents.jscase. This allows attackers to forge or steal session tokens, impacting user authentication and privacy. - URL Manipulation Gadgets: 50 gadgets were identified that could manipulate URL query strings in victim's requests. This type of vulnerability can be abused for phishing, redirecting users to malicious sites, or altering application behavior.
Beyond the sheer numbers, the research provided concrete examples of these gadgets, including those found in fbvents.js (specifically V2.6.6), and pify.js. Notably, the fbvents.js and V2.6 gadgets were demonstrated to be part of end-to-end exploits, confirming their practical exploitability.
The impact of these discoveries extends beyond academic interest. The research team engaged in responsible disclosure, reporting their findings to affected parties. This led to tangible security improvements, including a bug bounty awarded by Meta for the vulnerability in fbvents.js and the assignment of a CVE identifier for the vulnerability found in V 2.6. These outcomes underscore the practical value of the Gala framework and the methodology it embodies for enhancing web security. The widespread nature of these vulnerabilities, coupled with the success of responsible disclosure, reinforces the importance of adopting advanced dynamic analysis techniques to uncover hidden threats in complex client-side applications.
Technical Deep Dive
▶ Watch: Gala's novel solution: borrowing values from reference websites (4:45)
The core innovation of the "Follow My Flow" research lies in its novel approach to overcoming the significant challenges posed by client-side JavaScript's dynamic nature and intricate format checking constraints. Traditional methods, as previously discussed, falter when a gadget requires a specific, complex input value to trigger its malicious behavior. Gala's solution is to "borrow" such a value from a reference website, enabling it to bypass these constraints and demonstrate exploitability.
Let's revisit the motivating example of assc.com being vulnerable due to a gadget in fbvents.js. The key challenge was a format checking constraint within an unpack function: the input needed to have exactly four segments, split by three dots (e.g., F.1.cookie.value). Without this precise format, the check would fail, the function would return null, and the polluted value would never reach the sensitive document.cookie sink. Prior tools could not generate such a specific payload.
Gala's methodology, named "Follow My Flow," is structured into three distinct phases:
- Phase 1: Analyze Website O (Original Website)
- Objective: Identify potential prototype pollution vulnerabilities and the undefined properties that could be exploited.
- Process: A web crawler first fetches the HTML and JavaScript files from the target website (referred to as Website O, e.g.,
assc.com). These files are then fed into an instrumented JavaScript runtime. This runtime is crucial as it allows Gala to observe and record property accesses. Specifically, Gala monitors for attempts to access properties that are currentlyundefinedbut are later assigned values. If such an undefined property is accessed, it signifies a potential point where an attacker could inject a value via prototype pollution (e.g.,Object.prototype[0]). This phase identifies the "holes" in the prototype chain that an attacker could fill.
- Phase 2: Identify Website R (Reference Website)
- Objective: Find a reference website that uses the same vulnerable library as Website O and can provide a valid, constraint-satisfying value for the identified undefined property, leading to a sink.
- Process: Gala then crawls a vast number of other websites, looking for those that import the same JavaScript library (e.g.,
fbvents.js). For each potential reference website (Website R, e.g.,3w.wise.com), Gala again uses an instrumented JavaScript runtime to observe how the same property (which was undefined on Website O) is used and defined on Website R. Crucially, a dynamic taint engine is employed here. This engine tracks the flow of these defined property values. If a value, while being processed on Website R, satisfies the necessary constraints (like the "three dots" format check) and ultimately reaches a sensitive sink function (e.g.,document.cookie), then Website R is identified as a suitable reference. This phase effectively identifies a "working example" of how the gadget can be triggered.
- Phase 3: Follow the Flow (Exploit Validation)
- Objective: Validate that the borrowed value from Website R can successfully trigger the gadget on Website O and reach a sink.
- Process: In this final phase, Gala takes the specific value that was successfully observed flowing to a sink on Website R and inputs it into Website O. The simulation on Website O is configured to mimic the prototype pollution scenario, where the attacker's crafted value (derived from the borrowed value) is injected into
Object.prototype. Gala then observes if this injected, borrowed value can successfully navigate through Website O's program flow, bypass the same format checking constraints (which it now can, because the value has the correct format), and ultimately reach the intended sensitive sink (e.g.,document.cookie). This phase confirms the end-to-end exploitability.
The entire framework is underpinned by a robust system architecture involving a web crawler for data collection, multiple instances of an instrumented JavaScript runtime (likely a modified browser environment like Chromium or Node.js) for detailed execution tracing, and a dynamic taint engine for tracking data flow and identifying sensitive sinks. This combination allows Gala to perform deep, context-aware analysis that prior static or simpler dynamic methods could not achieve, making it uniquely capable of discovering these complex client-side prototype pollution gadgets.
Demo / Proof of Concept
▶ Watch: Gala framework: three-phase automatic detection process (6:10)
The talk's motivating example serves as a compelling proof of concept for Gala's capabilities, illustrating how the framework automatically discovers and validates a real-world client-side prototype pollution gadget. This demonstration involved a specific vulnerability affecting assc.com via the fbvents.js library developed by Meta, leading to cookie manipulation.
The scenario unfolds as follows:
- Initial State: The website
assc.comincludes thefbvents.jslibrary. Within this library, there are two functions,packandunpack, which process a variableA. The output ofunpackeventually flows intodocument.cookie, a critical sink for cookie manipulation. A specific challenge in theunpackfunction is a format checking constraint: the input must be a string divided into four segments by three dots (e.g.,F.1.attacker.cookie). If this format is not met, theunpackfunction returnsnull, preventing the value from reachingdocument.cookie. - Attacker Action: An attacker crafts a malicious URL. This URL is designed to trigger a prototype pollution vulnerability on
assc.com. The specific mechanism shown is through_protoc bracket zero, which, in essence, allows the attacker to inject a property[0]intoObject.prototype. The attacker embeds their desired cookie value (e.g.,fp.1.attacker.cookie) within the URL query string. - Prototype Pollution Triggered: When a victim clicks this malicious URL, the prototype pollution is activated. The attacker's cookie value is then stored directly into JavaScript's prototypical object:
Object.prototype[0] = "fp.1.attacker.cookie". - Gadget Activation - The "Borrowing" Mechanism in Action:
- The variable
Ainassc.comgoes through thepackfunction, and then its value (or a derived value) is passed to theunpackfunction. - Inside
pack, there's an operation involvingBracket Z0(likelyB[0]or a similar array/object access). Crucially,Bracket Z0is originally undefined in the normal execution flow ofassc.com. - However, due to prototype inheritance, when
Bracket Z0is accessed, JavaScript looks up the prototype chain. SinceObject.prototype[0]has been polluted withfp.1.attacker.cookie,Bracket Z0now resolves to this attacker-controlled value. - This is where Gala's "borrowing" technique becomes critical. The value
fp.1.attacker.cookiehas the precise "three dots" format required by theunpackfunction. Gala previously identified this specific format by observing its successful execution on a reference website (Website R), such as3w.wise.com, which uses the samefbvents.jslibrary and correctly defines this property.
- Flow to Sink: Because the borrowed value
fp.1.attacker.cookiesatisfies theunpackfunction's format checking constraint, the function processes it successfully. The value then flows through the rest of the program, eventually reachingdocument.cookie. - Consequence: The victim's browser, executing the JavaScript, now sets
document.cookieto the attacker's manipulated value. This leads to cookie manipulation, allowing the attacker to potentially hijack the victim's session or perform other malicious actions.
This end-to-end exploit demonstrates Gala's ability to not only identify the prototype pollution vulnerability and the gadget but also to craft a payload that bypasses complex client-side constraints, culminating in a concrete security impact. The responsible disclosure to Meta and subsequent bug bounty further validate the real-world effectiveness of this proof of concept.
Defensive Implications
▶ Watch: Evaluation results: 133 zero-day gadgets discovered (9:00)
The discoveries made by the "Follow My Flow" research have profound defensive implications for web developers, security engineers, and organizations maintaining web applications. The prevalence of zero-day prototype pollution gadgets across thousands of websites underscores the need for a multi-layered defense strategy.
For Web Developers and Application Security Teams:
- Input Sanitization and Validation: The most fundamental defense is rigorous input sanitization and validation. Developers must be extremely cautious when accepting user-supplied input, especially when it's used to dynamically set object properties, merge objects, or parse JSON. Avoid directly assigning user input to object properties without checking if the property name is
__proto__,constructor, orprototype. - Avoid Direct Property Access on
Object.prototype: While direct prototype pollution via__proto__is commonly understood, developers should be aware that properties can be polluted through array access (Object.prototype[0]) or other means if the application's logic allows. - Use
Object.create(null)for Maps: When creating objects intended to be used as hash maps or dictionaries, consider usingObject.create(null)instead of{}. Objects created withObject.create(null)do not inherit fromObject.prototype, making them immune to prototype pollution attacks on their own properties. - Audit Third-Party Libraries: A significant portion of these gadgets reside in popular third-party libraries (e.g.,
fbvents.js,V2.6). Developers must diligently audit these dependencies for prototype pollution vulnerabilities. Tools like Gala can assist in this, but manual code reviews focused on object merging, deep cloning, and property assignment logic are also critical. - Content Security Policy (CSP): For mitigating XSS gadgets, a strong Content Security Policy (CSP) is invaluable. By restricting script sources (
script-src), inline scripts, andeval()-like functions, CSP can significantly reduce the impact of successful XSS exploits, even if a gadget is triggered. - Subresource Integrity (SRI): To protect against compromised third-party libraries, implement Subresource Integrity (SRI) for all external scripts and stylesheets. SRI ensures that the files fetched by the browser match a cryptographic hash provided by the developer, preventing attackers from injecting malicious code into legitimate libraries.
- Secure Coding Practices: Adopt secure coding practices that minimize the use of dynamic property access, especially when dealing with data from untrusted sources. Be wary of functions that recursively merge objects without proper checks.
- Regular Security Audits and Penetration Testing: Integrate regular security audits and penetration testing specifically targeting client-side vulnerabilities, including prototype pollution and gadget detection, into the development lifecycle.
For Security Researchers and Tool Developers:
- Embrace Dynamic Analysis: The success of Gala highlights the power of dynamic analysis frameworks combined with instrumented JavaScript runtimes and dynamic taint engines. Future research and tooling should continue to explore and refine these techniques for detecting complex client-side vulnerabilities.
- "Borrowing" as a Paradigm: The "borrowing" technique to satisfy complex format checking constraints is a significant methodological advancement. This concept can be generalized and applied to uncover other classes of vulnerabilities where specific, hard-to-guess input formats are required to trigger a flaw.
- Focus on Library Ecosystems: The discovery of gadgets in widely used libraries emphasizes the need for security research to focus on the interconnectedness of the web ecosystem and the cascading impact of vulnerabilities in shared components.
- Automated Responsible Disclosure: The successful bug bounty and CVE assignment underscore the importance of automated systems not just for detection but also for facilitating responsible disclosure and collaboration with vendors.
By understanding the mechanisms of prototype pollution and the intricate nature of gadgets, defenders can implement more robust security controls and proactively identify and mitigate these pervasive client-side threats.
Key Takeaways
- Prototype pollution is a significant client-side vulnerability: When combined with specific "gadgets," it can lead to severe consequences like XSS, cookie manipulation, and URL manipulation.
- Gala's novel "borrowing" technique is a game-changer: By leveraging "reference websites" to obtain valid, constraint-satisfying values, Gala overcomes a major limitation of prior work in detecting complex client-side gadgets.
- Widespread zero-day gadgets were discovered: The research identified 133 zero-day gadgets across over 5,000 real-world websites, highlighting the pervasive nature of this threat.
- Client-side JavaScript's dynamic nature poses unique challenges: Complex string operations and dynamic features in JavaScript make it difficult for traditional static analysis or simple dynamic tools to find these vulnerabilities.
- Responsible disclosure leads to real-world impact: The team's responsible disclosure efforts resulted in bug bounties (e.g., from Meta) and CVE identifiers, demonstrating the practical value of their research.
- Developers must adopt proactive defenses: Implementing rigorous input sanitization, using
Object.create(null), auditing third-party libraries, and deploying strong CSP and SRI are crucial for mitigating prototype pollution risks.
About the Speaker(s)
The research presented in "Follow My Flow: Unveiling Client-Side Prototype Pollution Gadgets from One Million Real-World Websites" was a collaborative effort by Zifeng Kang, Muxi Lyu, Zhengyu Liu, Jianjia Yu, Runqi Fan, and Song Li. The primary presenter mentioned in the talk was Sungcom from Johns Hopkins University, indicating a significant contribution from the institution. The team collectively represents expertise from Johns Hopkins University and Jiang University. Their work in this area of client-side web security was recognized with a prestigious distinguished paper award, underscoring the innovative methodology and significant findings of their research. Their contributions highlight a deep understanding of JavaScript's intricacies and a commitment to advancing the state of web vulnerability detection.