FWIW, Signal's native mobile apps are written in Java and Objective-C respectively, so there's not really much of a difference compared to Wire (which is a good choice as well). Still, even a hypothetical React Native app written in JavaScript wouldn't be much worse; after all, React Native isn't just a Web View made to look like a native app, but uses actual native components.
So, electron is the new flash. I'll be avoiding that, then.
The Signal devs thought $.html() does some kind of escaping: https://github.com/signalapp/Signal-Desktop/commit/9d41b8616... (this commit made something that was easy to exploit into something that was even easier to exploit).
To be honest, I'd lay more blame on the authors of the DOM spec making innerHTML a setter than on Electron, and jQuery exposing this misfeature even more with $.html(), teaching an army of web developers to do the wrong thing. We've all seen numerous (XSS) vulnerabilities in all kinds of websites, browser extensions, Electron apps, etc resulting from this API, tho in Electron apps it gets particularly devastating as often you'd get code execution not just in a sandboxed website but full code execution under the current user credentials in the system.
Still, when you ship an app with a relatively strict Content Security Policy as Signal did (including using script-src 'self'), you don't really expect a simple XSS vulnerability to lead to RCE, but it turns out that policy doesn't really do much in an Electron app.
Uhm... that's a really rookie mistake to make. Like, one of the very basics of jQuery usage. I'm not exactly sure what to think about it after seeing this commit you linked...
A mistake that seems like it could've been caught in a code review!
> The Signal devs thought $.html() does some kind of escaping
I mean, it does do a kind of escaping. If you assign javascript to innerHTML directly, it won't execute. jQuery specifically checks whether you're adding a script tag, and if so, it takes the extra step to execute it for you.
This is an absolutely egregious rookie error. I wouldn't touch the Signal desktop app with a 10 foot pole after seeing that commit.
> const expected: string = "Hello<br><script>alert('evil');</script>World!";
(Meaning they actually changed a line that had "<script>alert('evil')</script>" and didn't notice.)
I have seen this before though, with some folks removing path sanitisation code I added several years prior to fix a CVE. So it's not uncommon (it also got merged, so when I found out and fixed it I added a very large and scary comment to stop people from doing it again).
Yes, but most engineers would look at that last element and say "what on earth is going on here", where $.html() being dangerous is something that engineers who don't usually work on web might not know about. You're right about blaming the DOM spec, but there's no actual reason for signal desktop to interact with that poorly designed spec except that they chose electron as a framework.
Can you explain that last part? I can't think of how an XSS attack could get around that, and Electron's documentation specifically recommends it: https://github.com/electron/electron/blob/master/docs/tutori...
There are ways to lock down the CSP further to mitigate this, but no one really expects script-src 'self' to be unsafe, especially when it's what their documentation recommends.
[1]: https://ivan.barreraoro.com.ar/signal-desktop-html-tag-injec...
For example, my IntelliJ runs as my user account, but it doesn't need access to all my files.
I should be able to select which directories it has access to and it's within a container by default.
I mean I can set this stuff up manually, but in the future I'd like to see this as the default.
Similar to the way Android apps ask for permissions.
It will take a looong time for "standard" OSes to get there, if they ever do. The required changes in UX are very significant...
Or the sandbox models on Android, iOS and macOS.
Sure, you can write secure apps in Electron, just like you can do risky stuff in real-life and be fine most of the time. But why take the risk?
Had the app been written with a native language and SDK, they wouldn’t need to worry about escaping or anything. I have yet to hear about getting remote code execution for dumping text into an UILabel or similar, while XSS happens almost every day.
The app isn't using React but jQuery, which doesn't have those protections.
https://github.com/signalapp/Signal-Desktop/blob/f6eb745632c...
They do seem to be using react, and using dangerouslySetInnerHTML. Now that said, I haven't confirmed that this is the code that caused the issue, but it is in the Quotes component, which is referenced in the article.
They seem to have fixed this specific issue a few days ago (v.11.0):
https://github.com/signalapp/Signal-Desktop/blob/0d00fbfb7a2...
They do seem to be using jQuery elsewhere in the code base, but I'm not familiar enough to determine how it all fits together.
struct A {
int *p = nullptr;
A& operator=(int i) {
*p = i;
return *this;
}
};
int main(void)
{
A a;
a = 1; /* boom! */
return 0;
}The Android app was written by Moxie, and I think it's the one about which Matthew Green said:
After reading the code, I literally discovered a line of drool running down my face. It’s really nice.
You can say secure chat clients should not display HTML messages, but that's a pretty different thing.
With the prevalence of XSS and CSRF vulns on the regular sandboxed web, it's pretty brave to take that model into unsandboxed fat clients..?!
However, as you point out, the issue lies in the presentation layer unexpectedly executing code (or receiving inputs from unexpected and untrusted sources). This issue wouldn't be solved by switching to a different language. The core issue here isn't Javascript per se, but the dangerous runtime environments that are browsers and browser approximations (electron) that are designed to execute code from 3rd parties.
OpenBSD is a famously secure unix(alike) distro. That doesn't mean that every piece of software in OpenBSD is safe to use in any other context.