Deploying a browser Javascript application locally does not automatically protect you from serverside malicious Javascript; you have to know a lot more about how the application is structured to know whether it's even helpful.
Deploying any application locally puts you entirely at mercy of whoever wrote it, and those that know how to abuse it. That holds true for any type of application.
However, in this context, deploying this particular self-contained application locally protects against the hypothetical attack where a genuine application is later modified to turn malicious. It is relatively easy to look for and identify any execution of server-side content.
To prove that an application is not intentionally malicious, you would have to inspect the source. To prove that an application cannot be malicious, directly or indirectly, intentionally a not, you will need full formal verification of the application. And that verification only holds if you have formal verification of what it runs on.
No, it does not. You've missed my point. Deploying a browser JS application locally would help you if you could be sure that the application never loaded any additional Javascript from the server during execution. But browser JS applications can in fact do that, and so local deployment does not help as much as you think it does.
You missed my point. In multiple ways. I already accounted for remotely fetched JS in my previous comment.
It is relatively easy to find JavaScript execution points (there are only so many ways to parse and execute text string from a server in JavaScript—eval, new Function, script element, on... DOM attributes, ...), and thus it is quite easy guarantee that an application does not intentionally execute remote code (intentional is what is inside the control of the source code—an image decoding bug in the browser causing code execution is outside the scope here).
A local deployment (with proper protection of the deployment) guarantees that an application remains static, and cannot be changed arbitrarily for malicious intent. Combined with a relatively easy inspection for intentional remote code execution, you can conclude that there is no direct way for the application to turn malicious.
If you do not inspect the source, a local deployment still reduces the chance of a malicious modification being possible from "100% guaranteed" to "maybe, if the application is written in a specific way, or if there is an unintentional code execution bug somewhere in the browser".
You will of course never be able to reduce the chance of any application turning malicious to 0 without full verification of the application and platform it runs on (including all other applications running with permissions to interfere).
Not to endorse the argument that a local app written in JS is inherently any more worrisome than one written for, say, .NET or GTK+ (because it's not), but this statement really sticks out:
> It is relatively easy to find JavaScript execution points
Have you ever been tasked with actually trying to guard against these things in security-critical situations? Because even with a deep understanding of the ECMA/W3C/WHATWG specs, years of experience with the arcane internals of a specific browser and JS engine, those engines' quirks wrt the way those specs are implemented, and the way they extend the specs, this was really tough even 5 years ago. The fact that JS is now an even faster moving target with yearly updates to the spec means that it's harder now. I don't think anyone who's worked on browsers would get behind the statement you made there.
Yes, I have. The list is not very long, and it is comprehensive.
At a previous place of employment, we implemented a full in-JS sandbox. The project was nasty, but as it hooked all JS execution, I do in fact have the fairly short list—what was not hooked would fail, so we were 100% sure that the list was comprehensive. Some of the entries do surprise slightly, mainly due to arcane APIs accepting both strings and function objects. New ECMAScript revisions didn't result in new execution points, although they did complicate the project in other ways.
The project also means that I could whine for ages about browser engine quirks, terrible APIs, awful specs and the likes, and will absolutely never look positively on browsers ever again.
I don't follow, since you said none of those things --- eval, script elements, DOM attributes --- in any previous post.
I also don't understand why you think it's straightforward for people ("relatively easy", in fact) to verify that a browser JS app is server-proof. As table stakes, you'd need a comprehensive understanding of every way in which the server gets to update the DOM of the client.
They were implied as "execution of server-side content" in the sentence: "It is relatively easy to look for and identify any execution of server-side content."
It is correct that it would be complicated to do for an arbitrary hosted app that may inject server-side rendered content with scripts in them, but this is not the case here.
There are very few places where "external" content is inserted into the DOM (decrypted mailbox content that may be HTML, account info), and those should all employ proper script stripping techniques. Finding DOM append or assignment (including attribute assignment) points is relatively easy.
With the DOM out of the way, you only have places where the application intentionally executes JavaScript through eval and new Function (potentially wrapped in whatever frameworks they use).
It really isn't very hard. And yes, I have done it before—and no, I couldn't have missed something when I did it, as only interaction I had found would succeed in my sandbox.
That will break the app if it wasn't written for it.
It doesn't change the argument, though. I'm arguing that it is relatively easy to deal with within the limits of what can be dealt with. If a strict content security policy can be applied, it just gets even easier.
I'd say that a csp is the only reasonable way to verify for a non-trivial app. A deep audit of every line of the app plus the whole dependency graph (that must be repeated on the diffs for every update) is not how I would define 'relatively easy'.
And yes, I know it will break if not written for it--I'm saying that coding to fit a strict csp is the only way to have a verifiably secure js app. Without it, you're in the jungle.
I don't mind the CSP approach, I was just stating that with it, the app either works, or everything breaks.
However, two things:
1. Nothing here requires a deep audit. Finding every execution point can be done with a bit of patience and "git grep". Some terrible frameworks, such as jQuery, can obscure things a bit, in which case knowledge of them speeds things up.
2. This may be a simple slip of words, but CSP does not in any way make your app verifiable secure. Coding towards a strict CSP is more about responsible coding and risk reduction/threat containment, by making foreign JavaScript execution non-trivial. There is nothing in a browser that lets you make something verifiably secure.
1 - Theoretically yes, but this is highly error prone and needs to be repeated on every update. Taking human factors into account, it's not a reliable strategy imho.
2 - My point isn't that a strict CSP makes the app magically secure, just that without it there's realistically no hope, and there's no point in wasting energy on trying to run a nontrivial app that doesn't have a strict CSP locally with the hope of getting around the security concerns of remotely hosted html/js.
If you load a local html file with a strict CSP into Chrome with no extensions installed, that's actually a pretty darn secure execution environment. It's much easier to verify than a native app, for example, and it can do a lot less damage. Based on a single line at the top of the file, you can be certain that the app doesn't load remote js or css, doesn't use eval, only communicates with specific domains, etc. It isn't magic, but it can get you a long way and it does offer numerous clear, concrete benefits vs. a remotely hosted app.