You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There are many ways to mitigate these errors in your application. First, please let us know if you’ve found a new problem by leaving a comment on our ecosystem compatibility tracking issue.
If you’re in a rush, the fastest mitigation is to set the “override taming” to “severe”. If you’re handling the lockdown procedure directly, you can do that with an option.
lockdown({overrideTaming: 'severe'});
In Node.js, lockdown will pick up LOCKDOWN_OVERRIDE_TAMING=severe from the environment.
> export LOCKDOWN_OVERRIDE_TAMING=severe
This also works on the web by setting up process.env.LOCKDOWN_OVERRIDE_TAMING = 'severe'.
If you’re using @endo/init to set up Hardened JavaScript, using @endo/init/legacy.js instead will set up severe override taming, but beware that it also disables error stack redaction and frame filtering.
Solution
You can help the Hardened JavaScript community patch any library that introduces a breaking change for Hardened JavaScript. We have had a fair amount of success getting packages to change.
Hello, we found that this library is not compatible with applications that freeze prototypes to defend against prototype pollution due to the JavaScript property override mistake. Would you accept a patch that changes object.constructor = constructor to Object.defineProperty(object, 'constructor', { value: constructor })?
Applications (but not libraries) can use patch-package to both mitigate the property override for their own use but also generate a patch to send the library’s authors.
Libraries do not benefit from patches because they have to be adopted at the level of an application’s lock-file. You can recommend that all users of a library adopt a patch, but all other usage will remain broken. For libraries, the same effect can only be obtained by getting the dependency to release a patch, or fork or subsume the dependency. Forking is a bridge too far for most libraries!
Prevention
We invite every JavaScript library to consider adding Object.freeze(Object.prototype) to the top of all their tests, with a comment pointing to this discussion. If especially generous, consider also freezing Function.prototype. This would serve as a highly reliable canary for compatibility with any technology that freezes prototypes to prevent prototype pollution mistakes or attacks. JavaScript may never be able to fix the prototype-override-mistake, but this one practice could obviate the harm it has caused.
Background
We like to think of Hardened JavaScript as the JavaScript that you already know. We treat shims as special and modifying prototypes you don’t own is otherwise taboo. Hardened JavaScript is just enforcement for this division. Any library designed for JavaScript also works under Hardened JavaScript. Almost.
Around 2009, the designers of JavaScript committed the “property override mistake”. If you freeze the prototype of an object, assigning a value to any property of the object that exists on its prototype will throw an exception. Consider:
There are cases that will break due to the property-override-mistake, but they’re outside what we would consider “The JavaScript you already know”. Objects should not be used as mutable maps. Assigning a key to of an object obtained by parsing user data is…fraught.
But a number of libraries, including some important and powerful libraries that are often tucked away in the transitive dependencies of many other libraries, assign to properties like constructor and consequently break under Hardened JavaScript. The second-most common errors from the property-override-mistake is assignment to toString. There are other cases but they are vanishingly rare.
Because of the property-override-mistake and because most JavaScript libraries do not test under Hardened JavaScript, a patch or feature release might be backward-compatible for JavaScript but be a breaking-change for Hardened JavaScript.
Known Compatibility Issues
We track Hardened JavaScript library compatibility in various places.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
When you adopt or upgrade a library in a Hardened JavaScript project, you may encounter errors like:
Or:
These are symptoms of the “property override mistake”.
Mitigation
There are many ways to mitigate these errors in your application. First, please let us know if you’ve found a new problem by leaving a comment on our ecosystem compatibility tracking issue.
If you’re in a rush, the fastest mitigation is to set the “override taming” to “severe”. If you’re handling the
lockdown
procedure directly, you can do that with an option.In Node.js,
lockdown
will pick upLOCKDOWN_OVERRIDE_TAMING=severe
from the environment.> export LOCKDOWN_OVERRIDE_TAMING=severe
This also works on the web by setting up
process.env.LOCKDOWN_OVERRIDE_TAMING = 'severe'
.If you’re using
@endo/init
to set up Hardened JavaScript, using@endo/init/legacy.js
instead will set up severe override taming, but beware that it also disables error stack redaction and frame filtering.Solution
You can help the Hardened JavaScript community patch any library that introduces a breaking change for Hardened JavaScript. We have had a fair amount of success getting packages to change.
Applications (but not libraries) can use
patch-package
to both mitigate the property override for their own use but also generate a patch to send the library’s authors.Libraries do not benefit from patches because they have to be adopted at the level of an application’s lock-file. You can recommend that all users of a library adopt a patch, but all other usage will remain broken. For libraries, the same effect can only be obtained by getting the dependency to release a patch, or fork or subsume the dependency. Forking is a bridge too far for most libraries!
Prevention
We invite every JavaScript library to consider adding
Object.freeze(Object.prototype)
to the top of all their tests, with a comment pointing to this discussion. If especially generous, consider also freezingFunction.prototype
. This would serve as a highly reliable canary for compatibility with any technology that freezes prototypes to prevent prototype pollution mistakes or attacks. JavaScript may never be able to fix the prototype-override-mistake, but this one practice could obviate the harm it has caused.Background
We like to think of Hardened JavaScript as the JavaScript that you already know. We treat shims as special and modifying prototypes you don’t own is otherwise taboo. Hardened JavaScript is just enforcement for this division. Any library designed for JavaScript also works under Hardened JavaScript. Almost.
Around 2009, the designers of JavaScript committed the “property override mistake”. If you freeze the prototype of an object, assigning a value to any property of the object that exists on its prototype will throw an exception. Consider:
This is almost never a problem because. All of the following cases work without issue:
Properties can be redefined if they are “configurable”.
Object literals are defined, not assigned.
Classes are defined, not assigned.
JSON.parse defines properties and isn’t subject to the limitations of assignment.
Objects with a null prototype aren’t subject to the configurability of properties on Object.prototype.
And, object literals can be defined with a null prototype inline too.
There are cases that will break due to the property-override-mistake, but they’re outside what we would consider “The JavaScript you already know”. Objects should not be used as mutable maps. Assigning a key to of an object obtained by parsing user data is…fraught.
But a number of libraries, including some important and powerful libraries that are often tucked away in the transitive dependencies of many other libraries, assign to properties like
constructor
and consequently break under Hardened JavaScript. The second-most common errors from the property-override-mistake is assignment totoString
. There are other cases but they are vanishingly rare.Because of the property-override-mistake and because most JavaScript libraries do not test under Hardened JavaScript, a patch or feature release might be backward-compatible for JavaScript but be a breaking-change for Hardened JavaScript.
Known Compatibility Issues
We track Hardened JavaScript library compatibility in various places.
Beta Was this translation helpful? Give feedback.
All reactions