3 ms·
You're getting downvoted because you're equating Angular 1, React and Vue. React has one huge difference: its "template language" is (almost) never compiled at
by spion 9y ago
You're getting downvoted because you're equating Angular 1, React and Vue.
React has one huge difference: its "template language" is (almost) never compiled at run time. Its not HTML at all. This makes it difficult to coerce it to interpret any random string as an expression. That annoying "build step" that everyone hates, that is the convenience for which people are sacrificing security.
When you have no build step, your template compiler must accept expression strings at run-time, and it will inevitably process user input at some point unless you're very careful all the time. "Escaping" things is a stop-gap that doesn't work.
You could just use fully static HTML/JS endpoints (react based) combined with fully JSON based RPC endpoints and it will be safe. Then you can combine that into server-side rendering, and it will stay safe (unless renderToString has a problem). No escaping required if you are not sending code strings to a compiler at runtime.
- EGreg 9y agoI get your point about precompilers. LESS, SASS, JSX and so on. But that's only one thing, my main point was "don't put executable code into your HTML". I would say, btw, that a Template Engine is what you need, such as Handlebars. They compile stuff too. What is wrong with escaping? That is what you do when you dynamically interpolate stuff. Of course interpolating stuff where it doesn't belong can lead to this: https://medium.com/dailyjs/exploiting-script-injection-flaws-in-reactjs-883fb1fe36c1 https://medium.com/dailyjs/exploiting-script-injection-flaws...
- spion 9y agoYou need escaping only when you're sending strings to a compiler (which is what you do when you do server-side rendering), and its a never ending source of bugs. You basically need to re-implement the entire logic of a full blown parser for the target language to guarantee successful escaping. E.g. see `mysql_real_for_real_this_time_escape_string` versus just supporting parameterized queries. Parameters don't need to be escaped; they will never be interpreted as SQL code. This list is also fun: https://gist.github.com/JohannesHoppe/5612274 https://gist.github.com/JohannesHoppe/5612274 - will your framework escape implementation cover all of them? Are you sure? If you serve a static html (no templates) + css + JS (pre-compiled JSX templates) client with all dynamic content being served as e.g. JSON, you're getting rid of a large number of attack vectors from the start. You are down to a handful of attributes, of which only dangerouslySetInnerHTML is a React-originating attack vector because similarly to all other template languages it sends a string to a compiler. It should probably be a symbol, too, especially now that we have spread syntax for props. https://github.com/facebook/react/issues/10506 https://github.com/facebook/react/issues/10506 - until then, you can simply forbid spread syntax for props and/or dangerouslySetInnerHTML. Any other HTML attributes that have a string-to-compiler behaviour remain a problem, regardless of whether you are using jquery or react or whatever. (e.g. href). Its sad but for some of them the only recourse we have is escaping. Still, thats a huge improvement over escaping everything.
- EGreg 9y agoExactly. You make a very good point. Passing PARAMETERS to a string based query or command should be done by reference whenever possible. The CALLER shouldn't be responsible for the escaping and interpolation. That is for the DRIVER or API or whatever. That just further proves my point. When you call SQL commands from PHP you should use PDO and parametrized queries always. Values should always be passed by reference. Same goes when you are outputting some HTML. You should have a hash of { attributeName: value } and it should be up to the HTML RENDERER - and not you - to escape the values every time. You've made another great point, which layers on top of my point, which is: 1) Use each language Y as it was intended 2) Escape everything automatically by passing values by reference to an API layer in language X So to sum up: Use HTML for structure, CSS for appearance, and JS for all dynamic behaviors. Keep your files separate! Do not allow embedding arbitrary CSS and JS in your HTML and so on. For MySQL use a MySQL driver API and pass values to it For HTML use an HTML renderer API and pass values to it For Javascript-accessible data embedded in HTML use a JSON function (easy) and pass values to it. For JSONP (old school) use JSON wrapped with some callback. Better: load actual JSON using XHR and CORS. Best: use iframes and postMessage to execute arbitrary methods in the other domain via an authorized session. And so on.