Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prototype pollution protection breaks decorator functionality #5131

Open
holgerkoser opened this issue Aug 16, 2024 · 2 comments
Open

Prototype pollution protection breaks decorator functionality #5131

holgerkoser opened this issue Aug 16, 2024 · 2 comments
Labels
good first issue help wanted type/enhancement Features or improvements to existing features

Comments

@holgerkoser
Copy link

holgerkoser commented Aug 16, 2024

I'm trying to implement protection against prototype pollution in my SinglePageApp that uses xterm.js. I'm using the following code at initialization:

[
  Object,
  Object.prototype,
  Function,
  Function.prototype,
  Array,
  Array.prototype,
  String,
  String.prototype,
  Number,
  Number.prototype,
  Boolean,
  Boolean.prototype,
].forEach(Object.freeze)

However, this causes an error when xterm.js tries to create a decorator:

TypeError: Cannot assign to read only property 'toString' of function 'function(e4, t3, n) {
            if (3 !== arguments.length) throw new Error("@IServiceName-decorator can only...<omitted>... }'
    at t2.createDecorator (@xterm_xterm.js?v=0e3f3914:5833:29)

The error seems to originate from this line in ServiceRegistry.ts:
https://github.com/xtermjs/xterm.js/blob/master/src/common/services/ServiceRegistry.ts#L36
It appears that the decorator creation is trying to modify Function.prototype, which is no longer allowed due to the Object.freeze() call.

To reproduce the problem more simply:

Object.freeze(Function.prototype)
const decorator = function () {}
decorator.toString = () => 1

This returns the same error.

decorator.toString = () => 1
                   ^

TypeError: Cannot assign to read only property 'toString' of function 'function () {}'

Proposed solution:
Instead of using toString to store the id, consider using a different property name (e.g., decorator._id = 1) or a Symbol. This would allow the decorator to function without modifying Function.prototype.
Is it possible to implement the decorator functionality using one of these alternative approaches? This would allow users to implement stronger prototype pollution protections without breaking xterm.js functionality.

@Tyriar
Copy link
Member

Tyriar commented Aug 16, 2024

If the alternate works, sounds good to me.

@Tyriar Tyriar added type/enhancement Features or improvements to existing features help wanted good first issue labels Aug 16, 2024
@holgerkoser
Copy link
Author

I would also like to add that freezing the constructors and prototypes after xterm.js is loaded is not an option for me. Since xterm.js is a relatively large library, I only want to load the code when a terminal window is actually opened by the user. In most cases, this doesn't happen, so it would be inefficient to include xterm.js in the initial bundle.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue help wanted type/enhancement Features or improvements to existing features
Projects
None yet
Development

No branches or pull requests

2 participants