Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for All your JavaScript code is polluted
Jan Küster 🔥
Jan Küster 🔥

Posted on

     

All your JavaScript code is polluted

Okay, maybe not all code and not always. This is just a short note on the prototype pollution as I have seen this issue again and again.

Photo byMaxim Tolchinskiy onUnsplash

What is this about?

If you use JavaScriptObject-bracket notation that accepts input from users then you may already have introduced Prototype pollution to your code. See this very simplified example:

constinternal={foo:{bar:null}}constacceptUserInput=(type,subtype,value)=>{internal[type][subtype]=value}
Enter fullscreen modeExit fullscreen mode

Applied:

// no problem so far, this is the expected inputacceptUserInput('foo','bar','I am so clever')// malicious inputacceptUserInput('__proto__','polluted','Bon jour 🐻‍❄️')
Enter fullscreen modeExit fullscreen mode

The result of the malicious input is, that all your newly created objects do now contain thepolluted property and the polar bear greets you:

constobj={}console.debug(obj.polluted)// 'Bon jour 🐻‍❄️'
Enter fullscreen modeExit fullscreen mode

Why is this a problem?

On the client this is somewhat to less problematic but on the server this can open doors to follow-up attacks.

Let's say an attacker knows, that you use a runtime-created Object wihtoutObject.create(null) during your checks for certain access privileges (which you should not do but I need an example here).

With the prototype pollution they could unlock privileges and gain more access on your system than they should:

constinternal={foo:{bar:null}}constacceptUserInput=(type,subtype,value)=>{internal[type][subtype]=value}// assume, this object// is constructed when reading// values from dbconstgetRoles=()=>({canAccessThat:true})constuserCanAccessThis=()=>{constme=getCurrentUser()// get from session etc.constroles=getRoles(me.id)returnroles.canAccessThis===true}// malicious inputacceptUserInput('__proto__','canAccessThis',true)// will now always return true for every useruserCanAccessThis()
Enter fullscreen modeExit fullscreen mode

This is, again, a simplified example but I hope you can see the severity it could introduce into your system.

What can I do to prevent it?

  • Reduce Object-bracket notation and use dot notation where possible
  • Alternatively use aMap or aSet, depending on your use-case
  • Beware of deep merging objects without checking that no properties of the prototype chain are affected
  • Validate inputs, especially if on the server
  • UseObject.create(null) to create Objects with no prototype

Thank you and please let me know, if you have any issues with the article or simply if you liked it and it helped you.

Top comments(15)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
adam_cyclones profile image
Adam Crockett 🌀
How’s it going, I'm a Adam, a Full-Stack Engineer, actively searching for work. I'm all about JavaScript. And Frontend but don't let that fool you - I've also got some serious Backend skills.
  • Location
    City of Bath, UK 🇬🇧
  • Education
    11 plus years* active enterprise development experience and a Fine art degree 🎨
  • Work
    Web Development Consultant at ForgeRock
  • Joined

Okay I can see a small potential risk here, thank you for showing me why automatic prototypical inheritance could be exploited.

My 2 cents:
I think that the prevention ideas may be idealism fodder for the developer who doesn't yet understand the significance and there is potential to just blindly add this sort of complexity to every single thing (trust me, I was that guy)

Could it be that the best way to prevent this sort of attack is a logical problem rather than a way of using js, for example some sort of 2 step permission system with a key that can only be issued from the server side to prove permissions

Better yet, don't role your own permission system and use Oauth and OpenID

CollapseExpand
 
jankapunkt profile image
Jan Küster 🔥
Graduated in Digital Media M.Sc. now developing the next generation of educational software. Since a while I develop full stack in Javascript using Meteor. Love fitness and Muay Thai after work.
  • Location
    Bremen, Germany
  • Education
    M.Sc.
  • Pronouns
    he/him
  • Work
    Scientific Employee at University of Bremen
  • Joined

I know the permission example is a bit drastic, but I also think it's a good way to especially show beginners how far this can get hypothetically.

I am also convinced, that this is indeed also related of how people use JS. For example: articles, I read about "why you should not useswitch", sometimes propose to use a dictionary-like Object as in the example above. It's also a very fast approach, compared to use am Map.

Maybe I also add, that many popular libraries (lodash, underscore) are known to habe introduced PP im prior versions?

CollapseExpand
 
adam_cyclones profile image
Adam Crockett 🌀
How’s it going, I'm a Adam, a Full-Stack Engineer, actively searching for work. I'm all about JavaScript. And Frontend but don't let that fool you - I've also got some serious Backend skills.
  • Location
    City of Bath, UK 🇬🇧
  • Education
    11 plus years* active enterprise development experience and a Fine art degree 🎨
  • Work
    Web Development Consultant at ForgeRock
  • Joined

The thing is I looked at your example and initially I was sceptical, the more I looked the more I saw this could happen. I like this post I ranked it as high quality so I hope you can have more discussions from that.

Oh yes, I know the pain that is lodash or similar, the security argument against a community authored std library is a juicy topic, worth writing about?

Poor misundrstood switch, I think there is some anti statement sentiment stemming from the FP community the myth that FP never uses statements, that and the similar looking branches I guess, again I had never considered this might be another reason why switch is the healthy choice.

Much food for thought here!

CollapseExpand
 
gottz profile image
Jan-Stefan Janetzky
gottz.de
  • Location
    Germany
  • Pronouns
    he/him
  • Work
    Self Employed and Gov contracted Platforms Engineer, Software Architect & Administrator
  • Joined

hasOwnProperty or "in" should be used here or indeed a set or map..
alternatively a lookup table.
why would I blindly trust user input.. that's trivial basic knowledge.. I always have to know all possible options a user might use and discard the excess.

CollapseExpand
 
jankapunkt profile image
Jan Küster 🔥
Graduated in Digital Media M.Sc. now developing the next generation of educational software. Since a while I develop full stack in Javascript using Meteor. Love fitness and Muay Thai after work.
  • Location
    Bremen, Germany
  • Education
    M.Sc.
  • Pronouns
    he/him
  • Work
    Scientific Employee at University of Bremen
  • Joined
• Edited on• Edited

You should, of course, never trust user input. But you should also not solely rely on validation, thus taking this scenario as seriously as other scenarios. Validation can fail and you never can cover all edge cases during validation.

Edit: note, thatin is not safe, either:

'__proto__'in{}// true
Enter fullscreen modeExit fullscreen mode

I summarized a few of these issues in one of my other articles:How to mess up your JavaScript code like a boss

CollapseExpand
 
gottz profile image
Jan-Stefan Janetzky
gottz.de
  • Location
    Germany
  • Pronouns
    he/him
  • Work
    Self Employed and Gov contracted Platforms Engineer, Software Architect & Administrator
  • Joined
• Edited on• Edited

for some reason that's precisely why I mentionedhasOwnProperty first, becausein CAN be used in cases you are checking against known keys.
also.. when validation fails, it should fail.
that's why it is called validation..

CollapseExpand
 
xiziliang profile image
xzl
  • Joined

Bingo~

CollapseExpand
 
wadecodez profile image
Wade Zimmerman
Code by day; blog by night
  • Location
    California
  • Education
    Networking/Software
  • Work
    Self Employed
  • Joined

Would like to see a breakdown of this topic on more common operations like saving user settings as a JSON object to the database. Like what would happen if prototype pollution was saved to the database by mistake then hydrated in the browser?

Devs tend to pay close attention to security features but forget about security on the random features like user settings, or repeatable fields.

CollapseExpand
 
jankapunkt profile image
Jan Küster 🔥
Graduated in Digital Media M.Sc. now developing the next generation of educational software. Since a while I develop full stack in Javascript using Meteor. Love fitness and Muay Thai after work.
  • Location
    Bremen, Germany
  • Education
    M.Sc.
  • Pronouns
    he/him
  • Work
    Scientific Employee at University of Bremen
  • Joined

Thanks that would be a great follow-up article. Let me check the next days what I can find.

CollapseExpand
 
htho profile image
Hauke T.
Usabilty Engineer and JavaScript/TypeScript Developer.On the path to become a Clean Code Developer.Also rediscovering OOP-Principals and Design-Patterns.
  • Location
    Würzburg, Germany
  • Work
    Usability Engineer & Frontend Developer
  • Joined

I never understood why one would use Object.create(null) now I do. Thank you.

CollapseExpand
 
maryannah profile image
Maryannah
  • Joined

"all your js code is polluted"

Proceeds to explain a very specific use-case, which literally no-one in their right mind would implement.

Clickbait much ?

CollapseExpand
 
jankapunkt profile image
Jan Küster 🔥
Graduated in Digital Media M.Sc. now developing the next generation of educational software. Since a while I develop full stack in Javascript using Meteor. Love fitness and Muay Thai after work.
  • Location
    Bremen, Germany
  • Education
    M.Sc.
  • Pronouns
    he/him
  • Work
    Scientific Employee at University of Bremen
  • Joined

You literally got me on this one. Now please take a few minutes and review my other articles that contain hours of research and writing effort and compare their likes with this one. Something is really broken here. Still, I tried to deliver on the topic as good as possible!

CollapseExpand
 
maryannah profile image
Maryannah
  • Joined

No thanks, given the poor quality of this article, your attention seeking behavior, and passive agressive answer, I'll just pass your offer.

Thread Thread
 
jankapunkt profile image
Jan Küster 🔥
Graduated in Digital Media M.Sc. now developing the next generation of educational software. Since a while I develop full stack in Javascript using Meteor. Love fitness and Muay Thai after work.
  • Location
    Bremen, Germany
  • Education
    M.Sc.
  • Pronouns
    he/him
  • Work
    Scientific Employee at University of Bremen
  • Joined

I think you misunderstood completely. Sorry.

CollapseExpand
 
mohanramphp profile image
Mohan Ram
I am passionate JavaScript Practitioner
  • Location
    Chennai
  • Work
    JavaScript Developer at Citicorp Services India Pvt Ltd
  • Joined

Brilliant article on prototype pollution.

Thank you for coming up with simple usecases to understand it.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Graduated in Digital Media M.Sc. now developing the next generation of educational software. Since a while I develop full stack in Javascript using Meteor. Love fitness and Muay Thai after work.
  • Location
    Bremen, Germany
  • Education
    M.Sc.
  • Pronouns
    he/him
  • Work
    Scientific Employee at University of Bremen
  • Joined

More fromJan Küster 🔥

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp