Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
proposal-symbol-proto — TC39 proposal for mitigating prototype pollution | Kitploit
Tools/GitHubGitHub/tc39/proposal-symbol-proto
Vulnerability AnalysisWeb SecurityPapers & ResearchLearning & Education
GitHubtc39/proposal-symbol-proto

proposal-symbol-proto

TC39 proposal for mitigating prototype pollution

View Repository
532193 years agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Prototype Pollution Mitigation / Symbol.proto

Authors: Santiago Díaz (Google)

Champion: Shu-yu Guo (Google)

Stage: 1

TOC

  • Problem Description
    • Spooky action at a distance
    • Data-only attacks
  • Issues with freeze, seal and preventExtensions
    • The override mistake
    • Coarse granularity
    • Freezing points
    • Application types
  • Proposed solution
    • Provide reflection APIs
    • Opt-in feature
      • Automatic refactoring
    • What does delete mean?
  • Incompatible code bases
  • Appendix
    • What about constructor pollution?
    • Computed access in minimized JS
    • Example vulnerabilities

tl;dr

This proposal seeks to mitigate a language-level vulnerability known as prototype pollution with a mechanism that complements freeze primitives and a mechanism to make most code bases compatible with it. It describes an opt-in feature that makes prototypes available only through reflection APIs. By doing so, the statement obj[key] can't access prototypes anymore. Code bases compatible with this feature are more intentional about the way they use prototypes.

Problem Description

Spooky action at a distance

PP vulnerabilities allow attackers to manipulate objects they don't control or don't have access to at runtime. This 'spooky action at a distance' primitive can be used to change the shape of other objects and override their properties, thereby tainting objects in the runtime.

Tainted objects invalidate the underlying assumptions of code that would otherwise be safe/correct and can lead to arbitrary code execution and a wide range of other security issues in JS code bases. Prototype pollution bugs express themselves often in web applications, but also affect non-web JS runtime.

Object properties in JS are writeable by any code that can reference them. In particular, if many objects rely on a shared property, any one of them can enact changes on all others.

Data-only attacks

A special property of PP is that it is a data-only attack, allowing code execution to be attained purely through data. For instance, see the following vulnerable code and a corresponding exploit:

// source is attacker-controlled
function merge(target, source) {
  for (let key in source) {
    if (typeof source[key] === 'object')  {
      if(target[key] === undefined) {
        target[key] = {};
      }
      target[key] = merge(target[key], source[key]);
    } else {
      target[key] = source[key];
    }
  }
  return target;
}

// User input comes as a string
const userSuppliedObj = JSON.parse('{"__proto__": {"polluted": true}}');
// Trigger prototype pollution
merge({}, userSuppliedObj);
// Create a brand new object
const newObj = {};
// Has polluted property
console.log(newObj.polluted); // true

Note that the exploit is able to taint the creation of new objects without injecting any foreign code.

Because of this special property, modern mitigations against code execution issues -like the Content Security Policy or Trusted Types- fall short of protecting against PP, as they focus on enforcing code provenance.

Note that data-only attacks are relevant to situations where the code running on the VM is trusted and arbitrary code execution has security impact.

Issues with freeze, seal and preventExtensions

Existing freezing primitives suffer from significant design issues that make them unlikely to be widely adopted. They can be useful to expert users, but are not suitable to be deployed by the majority of developers, who reasonably expect prototypes to be mutable:

The override mistake

Freeze APIs suffer from the override mistake and other inconsistencies which introduce bugs in existing code bases, making them throw or worse, silently fail in sloppy mode. A previous investigation of the override mistake concluded that the override mistake triggers on ~10% of code bases in strict mode and 20% in sloppy mode. The investigation was dropped shortly after.

Coarse granularity

Freeze APIs give developers the heavy responsibility of knowing which prototypes should be frozen to maintain a secure code base, assuming that developers are security experts. These APIs describe the what but not the how of security. Freezing Object is certainly not good enough, as many exploits abuse Array. What about Error, Date, Reflect or Proxy? Or future built-in types? Freeze APIs provide no answers to these questions.

Freezing points

Freeze APIs assume a stable freezing point: a fixed moment at runtime where prototypes have settled and can be frozen. In practice, this point is volatile and changes over time in code bases that are actively developed. While one can find such a point in many applications today, the addition of new dependencies, polyfills, code structure changes and power features like hotswapping and developer tools make freezing points a moving target.

Application types

Freeze APIs can't protect the full prototype chain. In JS, objects can be added or removed from the prototype chain at any point in time. To protect the full chain, one should always remember to freeze objects that are added to the chain, an error-prone process. When they are removed from the chain, they cannot be made unfrozen anymore.

Proposed solution

In a nutshell: a feature that exposes prototypes only to reflection APIs. If prototypes weren't made available through properties like __proto__ or prototype, they would not be exposed to data-only issues.

This is better understood through an example: the statement obj[one][two] = value is vulnerable to PP through obj.__proto__.polluted. If one deletes the Object.prototype.__proto__ property, the same statement is no longer vulnerable because it can't fit the only other way to reach prototypes, which is obj.constructor.prototype.polluted. Note that prototype can't be deleted.

This proposal can be implemented by providing reflection APIs and creating a new opt-in encapsulation feature that deletes prototype properties. A description of each step follows.

Provide reflection APIs

__proto__ is a legacy property name that can be deleted, but the internal slot behind it can still be read through Object/Reflect.getPrototypeOf and written through Object/Reflect.setPrototypeOf, which will simply continue to make this property accessible to code that is already running.

We propose the creation of new APIs for prototype, for example getClassPrototypeOf and setClassPrototypeOf, which would allow this property name to be deleted without changing in any way how this special property works and supports the VM.

Reflection APIs can be polyfilled, which allows hardened code bases to work in all browsers, including older versions.

Opt-in feature

A new opt-in 'encapsulation feature' where no property names are created for the getter and setter function of prototype slots, which is now possible because references to those properties can use reflection APIs instead.

The feature is enabled through an out-of-band flag:

Download Tool