5 ms·
Oh! Ha ha! Nice! I'm glad you like the code! I'd love to tell you it was the product of a journey of discovery that embedded deep magics in a (possibly) one-lin
by catapart 3y ago
Oh! Ha ha! Nice! I'm glad you like the code! I'd love to tell you it was the product of a journey of discovery that embedded deep magics in a (possibly) one-liner... but it's actually recommended (for the most part) on MDN's documentation about eval (and why not to use it).
On that topic, though, my concerns about eval are this:
Developer A is using my web components along with advertising that uses library X. Library X is actually malware that tries to harvest user data, but it does provide analytics, so it is silent malware that the advertisers nor Dev A can account for. Since Library X is loaded in an iFrame, it can't execute any code that will be local to Dev A's domain; everything will originate from the ad's domain. But since Dev A is using my web components, which use eval, he can query the dom of the iFrame's parent, get a reference to my component, and then inject the attack in a place that will trigger a re-render. The re-render runs the eval which still creates the html, but it also executes code to harvest user data both from localstorage/browser storage and using any tokens that Dev A's app provides for server access. It then stores a string of malware in the browsers local storage to execute every time the page refreshes.
Now, to be clear, I haven't tested this scenario in over a decade. There may be protections, now, that prevent this kind of thing. But that's what my functional testing would be based around: whether or not a third-party can start executing code from my domain. If you can prove that doesn't happen, then I would have much less concerns about security.
That aside, I understand your concerns about edge-cases. I can tell you that I haven't done any rigorous testing, in that regard. I used that method for my web components, but I was specifically trying to "not do anything fancy". Where that took me was trying to write loop executions and extracting object properties (like you mention; it's an operation in order to get the [correct] property values out of an object, instead of just the member variables). So even while getting somewhat robust, I didn't have any issues, but there are definitely some annoying things and some stuff to work around.
Something that jumps out at me is a weird issue with getting raw DOM text. What I would like to do is query my components for a template element, read the contents of that template element as raw text, and then provide injections for any of the string template variables that are present. The problem, though, is that there is no way to get the RAW text from a DOM element (at least that I could find), without something crazy like a direct text import (heavy cost; latency/bandwidth). If you try to read the text (innerHTML/textcontent/etc) of an element whose content is "My variable name is ${var1}, today.", you will get the string "My variable name is , today."
So my work-around was to leave off the $, and just regex for "handlebar" notation (ex: "{var1}"), which I would then prefix just before the template rendering. Not exactly a cheap solution, but fast enough for my work, anyway.
As far as contribution, I'm not saying "no", but I'm sure you can imagine I'm working on my own projects. To that end, I'll ping you when the results of my tortured process are public, just in case it's helpful to you (but, again, this project doesn't have a web-component wrapper lib; it's just pure native components). But that's just to say that I don't have a ton of bandwidth, at the moment, to actually contribute code in any standard worth receiving it. That said, it's obviously an area which I'm interested in, so I'm certainly open to being productive! As long as you're good with a slow pace, I'm happy to make some pull requests.
In the meantime, though, I did go ahead and upload some of my attempts as a gist: https://gist.github.com/catapart/64c993533b64089f337825d33a5a89bb https://gist.github.com/catapart/64c993533b64089f337825d33a5...
In the TS version, you can see the code where I extract the property values, as well as the (pretty buggy) loop functionality. I'm happy to discuss any of it, so if there's an app you're more real-time active on (it's Discord for my default, but I'm open to most apps), just let me know and we can get into it.
Anyway, thanks for the high-quality response! Easy to take criticism poorly, so I appreciate that you found it useful or informational in some way! Definitely helps me to have a good day, so I hope you do the same!
Edited to add: sorry! I meant to be explicit about this: you are more than welcome to harvest any code from that gist! If any of it is checked in, anywhere, it's licensed under CC0 so you are way in the clear to use it. Just because I might be too busy for a PR doesn't mean I don't want you using "my" code. Let's be real honest - it's a melting pot of stack overflow answers and HN comments. I can't really take particular credit for any of it. So by all means copy and paste or chop and screw to your heart's content! And, of course, if you have any questions about the whys or hows for any of it, just let me know!
- keepamovin 3y agoYour answer is fantastic! You're a really cool person. I like how you handle each point comprehensively and informatively and maintain a friendly tone throughout. And very funny about the: Oh! Ha ha! Nice! I'm glad you like the code! I'd love to tell you it was the product of a journey of discovery that embedded deep magics in a (possibly) one-liner... but it's actually recommended (for the most part) on MDN's documentation about eval (and why not to use it). Haha! You totally got my meaning. Thanks for telling me that. Yeah the MDN docs contain hidden gems, I'll check it out. Regarding the eval situation you describe, JavaScript running inside an iframe from a different origin (like BIGCLICK.NET) cannot access the DOM of the parent page (like NYTIMES.COM) due to the Same-Origin Policy enforced by web browsers. They could communicate over postMessage, but you can check the origin of the message and discard it if it's from an untrusted origin. The main risk with eval I think is that is can turn any string into code, so user input can be misused by an attacker. I'm not sure it's an issue here, because: eval(`(function ${this.template.toString().replace(/^\s*function\s+/,'')}())`); Simply evals the template function's string, which creates your template. The options for manipulating user input are potentially every template replacement variable, but, none of these will be treated as code by eval, as they are located in the template slots. Also, as the cooked template is injected into the DOM, this vulnerability exists independently of eval here. For example .template() { return `<h1>${myHeader}</h1>` } If an attack tries to set myHeader = `;alert('evil');<script>alert('big evil');</script>` It will not work because: 1) the first alert will not be executed as code, just as a string to insert into the template slot; and, 2) the second alert will not run because scripts injected via .innerHTML are not run. However, if an attacker sets myHeader = `<a href=# onpointermove=alert('evil')>Oh No</a>` It will work when you pointer over it. I suppose the real risk then is from allowing unsafe-inline. Crucially tho "myHeader" can never be executed as code, its variable is simply replaced. This is just a quick analysis, it could be patchy. As long as you're good with a slow pace, I'm happy to make some pull requests. Yes! I am totally fine with a slow pace. I completely understand and agree with the idea of going to your own limit, knowing how much bandwidth you have, and managing your workload for productivity and self care. Super important, it's the main thing--stay comfortable, no stress! Also, if you're just too overloaded or don't feel an interest at the time, don't worry about it. No pressure, merely an invitation, you're free to take that up if it's something you feel like, or if not, for any reason, there's no disappointment or judgement at all. It's ok, we just value your contribution so far! And I appreciate you linking some code, and clarifying any license on it, let me take a look at it! :)