Please make your language analyzable/auditable for computer security people.
Security folks need to be able to find vulnerabilities in a program before it ships. Ideally, we're called in early and can comment on the codebase as it develops, but often not.
When a new version of the language or core libraries comes out, things that were previously safe may no longer be:
- libraries may become more powerful : e.g. URL library now supports
javascript:
- there may be new ways to convert strings or bytes into code : e.g.
eval
or deserialization libraries
- language reflection techniques may become more powerful : e.g. exposing local variables
Any of these changes can increase the amount of abusable authority a program has, but since the amount of authority the program uses (when dealing with non-malicious clients) hasn't changed, security folk are hard pressed to figure that out without an intensive re-audit.
So, please think about us when designing and versioning the language. Below are a few tips:
Define a few primitives that a program can be decomposed into.
HTML5 is particularly bad this way.
They have obviously put a lot of thought into security and have some very smart people, but instead of specifying new program elements like <video>
in terms of old ones, or creating a common abstraction that new <video>
and old <img>
both can be specified in terms of, <video>
is yet another one-off program element with its own security consequences.
Make your language amenable to static analysis (even if not statically typed).
Security folk often use static analysis to find patterns, and to try and rule out parts of a program so that they can focus on the really tricky bits.
It should be obvious which identifiers are local variables and which are not.
E.g., don't make the same mistake as old versions of JavaScript which made it impossible to tell whether x
is a local variable reference in the below (according to a literal reading of an old version of the spec):
if (Math.random() > 0.5) {
Object.prototype.x = 0;
}
function f() {
var x = 1;
(function () {
alert(x); // Might alert 0, might alert 1.
})();
}
Allow for decomposable security
A lot of secure systems are designed around a secure kernel that preserves the security properties, so that security folk can focus their efforts on analyzing a small amount of code and freeing most programmers from having to deal with {annoying,pedantic,paranoid} security folk.
It should be possible to write such a kernel in your language. If one of the security properties of your language, is that only a certain subset of URLs will ever be fetched, can the kernel writers do something to channel all URL fetching through their code? Or can static build checks (like looking at imports) serve the same function.
Some languages like Newspeak use an object capabilities model. That's awesome and a great way to get decomposable security.
But if you can't do that, making the module graph a statically analyzable artifact can get you quite a bit of benefit. If I can prove that a module can't reach the file I/O module (except by calling code in a module in the TCB), then I can rule out whole classes of problems from that module.
Limit the authority of embedded scripting languages
A lot of useful systems are organized as a static core that kicks off a lot of code written in dynamic (even functional) languages.
And embedding scripting languages can make a system much more extensible.
But a scripting language shouldn't have the full authority of the VM.
If you choose to allow embedded scripting languages, make it easy for the invoker to limit what they can do. An object-capabilities model (see comment on Newspeak above) is very appropriate here ; so when evaluating code in a scripting language, the caller should pass in the code to execute and all the global variables for that code.
Treat eval
as a language embedding itself as a scripting language
If your language can invoke its own compiler to turn a string into code, then allow it to be sandboxed the same as you would any embedded scripting language.
Use a simple concurrency model
We security folks don't like to have to worry about race conditions when trying to figure out if a security property is maintained.
Please consider alternatives to threading before settling on threads as an almost impossible-to-secure default option.
One simple one is event loop concurrency like that found in E, Verilog, and JavaScript.
Don't encourage quoting confusion
Some languages are glue languages, and they end up dealing with strings in a lot of different languages.
For example, JavaScript often composes strings of HTML, CSS, XML, JSON, and even JavaScript. It is very hard for programmers to remember to properly encode plain text strings when combining them to make strings in other languages, so JS programs, unsurprisingly, have all kinds of quoting confusion problems : XSS being the worst.
If you want to include string composition features try to reduce the programmer's security burden. DSLs, hygienic macros, and embedded templating languages can be a great way of doing this by moving the burden for properly escaping onto library or language developers and away from the end-developer.