The C-style “oops I used an object after freeing it and now anyone can execute arbitrary code” style of vulnerabilities is confined to a fairly narrow set of programming languages, most notably C and C++, which unfortunately happen to be popular and to have some interoperability advantages. One of the key requirements of a security-amenable language is that it can never tempt its users into writing parts of their project in C, which happens if the language is too slow (eg Python) or can’t otherwise interoperate with important systems (most languages, unfortunately). Some programming language choices create performance and sysadmin problems that are treated by end-users as dealbreakers; in fact this was responsible for most of C’s historical success.
A lot of issues crop up at the interfaces between programming languages, which tend not to fall neatly into one of the languages’ scope. SQL injection is a classic example. A language can’t do a whole lot in practice to protect against that, but a library can: by designing the APIs so that doing things the safe way is easy, and doing things the dangerous way requires calling functions with “dangerous” in the name (like React’s dangrouslySetInnerHTML).
If I import third-party libraries from the internet, there is a lot of opportunity for mischief (both by those third parties, and by the people who might hack them). This is probably the nodejs ecosystem’s weakest link at the moment. This problem is largely social; the best defense is a trustworthy group of curators providing a core set of libraries that you rarely need to step outside, plus an expectation that libraries are large projects that avoid creating indirect dependencies and that you use a small number of. (As opposed to having a hundred different left-pad style tiny libraries from a hundred different authors.)
Reducing security vulnerability incidence to zero is possible in some domains, but a programming language alone can’t do it; I can write if(password=="backdoor") acceptLogin() in any language.
I think there’s a fair amount of room left for incremental improvement, but in practice I think it looks less like “move everyone to Haskell and Coq” and more like “design a good core-library crypto API for X” and “reform common practices around npm”.
it looks less like “move everyone to Haskell and Coq” and more like “design a good core-library crypto API for X” and “reform common practices around npm”.
+1, coq is my dayjob and I’m constantly telling people to be less messianic when they talk about formal verification.
by designing the APIs so that doing things the safe way is easy, and doing things the dangerous way requires calling functions with “dangerous” in the name
+1, want to extend it by paraphrasing the ancient folk wisdom that I think comes in flavors for both libraries and languages: “things are bad when good behavior is impossible, things are good when bad behavior is impossible, everything comes in a spectrum of easier or harder bad or good behavior”, which can be read in terms of rewards and punishments (easy code is rewarding, hard code is punishing).
The C-style “oops I used an object after freeing it and now anyone can execute arbitrary code” style of vulnerabilities is confined to a fairly narrow set of programming languages, most notably C and C++, which unfortunately happen to be popular and to have some interoperability advantages. One of the key requirements of a security-amenable language is that it can never tempt its users into writing parts of their project in C, which happens if the language is too slow (eg Python) or can’t otherwise interoperate with important systems (most languages, unfortunately). Some programming language choices create performance and sysadmin problems that are treated by end-users as dealbreakers; in fact this was responsible for most of C’s historical success.
A lot of issues crop up at the interfaces between programming languages, which tend not to fall neatly into one of the languages’ scope. SQL injection is a classic example. A language can’t do a whole lot in practice to protect against that, but a library can: by designing the APIs so that doing things the safe way is easy, and doing things the dangerous way requires calling functions with “dangerous” in the name (like React’s
dangrouslySetInnerHTML
).If I import third-party libraries from the internet, there is a lot of opportunity for mischief (both by those third parties, and by the people who might hack them). This is probably the nodejs ecosystem’s weakest link at the moment. This problem is largely social; the best defense is a trustworthy group of curators providing a core set of libraries that you rarely need to step outside, plus an expectation that libraries are large projects that avoid creating indirect dependencies and that you use a small number of. (As opposed to having a hundred different
left-pad
style tiny libraries from a hundred different authors.)Reducing security vulnerability incidence to zero is possible in some domains, but a programming language alone can’t do it; I can write
if(password=="backdoor") acceptLogin()
in any language.I think there’s a fair amount of room left for incremental improvement, but in practice I think it looks less like “move everyone to Haskell and Coq” and more like “design a good core-library crypto API for X” and “reform common practices around npm”.
+1, coq is my dayjob and I’m constantly telling people to be less messianic when they talk about formal verification.
+1, want to extend it by paraphrasing the ancient folk wisdom that I think comes in flavors for both libraries and languages: “things are bad when good behavior is impossible, things are good when bad behavior is impossible, everything comes in a spectrum of easier or harder bad or good behavior”, which can be read in terms of rewards and punishments (easy code is rewarding, hard code is punishing).