3 ms·
Perl 5 has a taint mode built into the language. If enabled, it forces the developer to untaint every bit of user-controllable data (by running it through a pat
by Tepix 6y ago
Perl 5 has a taint mode built into the language. If enabled, it forces the developer to untaint every bit of user-controllable data (by running it through a pattern match) before doing anything dangerous with it. I can't believe that this isn't a standard feature in all languages.
- masklinn 6y agoThat’s because it’s both more annoying than warranted and completely insufficient, even ignoring that “running through pattern match” is not great (see: parse, don’t validate). * “untainting” is highly context-specific, that something was cleaned up for HTML does nothing for SQL * which also means that the boundary is incorrect, just because you’re getting something out of storage does not mean it’s safe for anything (not even storing it back)
- Tepix 6y agoYou are right, the programmer still has to think. But with builtin taint it's harder to overlook something because it forces you to consider everything. I have a friend who is a long time C++ developer. Every time we discuss C++ he tells me that memory errors can be easily avoided in C++ if you have a certain level of competency. Someone still developed Rust because of this issue and it is popular.
- staticassertion 6y agoYou can do this with any language with a type system by wrapping reads with a 'Tainted' type. ie: fn safe_read(path: str) -> Tainted<IO> { Tainted(unsafe_read(path)) } And then you can apply functions to Tainted<IO> or whatever type that convert it into something structured / validated. So long as your functions only take in those validated types (ie: you do not write functions that take str) you can ensure that new reads will fail to typcheck without first parsing. To be honest this is how most programs I see work anyways, at least in typed languages. Few work directly on strings. But they do it naturally, without enforcement - so like, a function might take a 'str', but the 'str' passed in was parsed into a wrapping structure already.
- marcosdumay 6y agoYou can do some actually useful stuff with a real type system, instead of replicating Perl's stupidity. For example, you can convert the input into a safe representation, suitable for the exact place you'll be using the string, instead of "validating" it.
- masklinn 6y agoExactly. What you need is not a “tainted” type and assume everything that’s not it is safe. That’s not the case. Html-escaping a string does not make it safe for SQL or whatever. What you need is a safe type for each use case, and ways to convert values to that (or mark them as that depending on your TS).
- staticassertion 6y agoThis is what I was referring to at the end of my post: > Few work directly on strings. But they do it naturally, without enforcement - so like, a function might take a 'str', but the 'str' passed in was parsed into a wrapping structure already. ie: Most programs in typed languages already do what you're saying - they parse the data directly into a structure, and therefor they validate some aspects of it naturally, so even when you do see a 'str' in typed code it's very often already gone through some sort of parsing phase.
- marcosdumay 6y agoHum... Your sibling has a nice explanation of what I was trying to say. You don't sanitize user input when parsing, you do it on usage. "Robert'; drop table users--" is a perfectly fine name and you shouldn't mangle it on you data fields.
- staticassertion 6y agoWe're saying the same thing.
- xeeeeeeeeeeenu 6y agoTaint mode is a terrible misfeature and modern code should not use it. It's one of those things that makes people think "it's annoying and makes me do additional work so surely it improves the security". No, it doesn't. For those who are unware what taint mode exactly is: when it's enabled, a string may have a hidden "tainted" flag. Passing a tainted string to many (but not all) built-in functions will result in an exception. Many built-ins return tainted strings, additionally all strings in @ARGV (cli parameters) and %ENV (env variables) are tainted. You can get an untainted string by accessing a tainted string through a regex capture group ($1, $2 etc.). Taint mode is global, so it affects everything, including third party modules. You may ask "how do I even validate my environmental variables? What's the difference between valid and invalid PATH?". Well, you can't. That's why programs using taint mode are often littered with code like: my($untainted) = $foo =~ /^(.*)$/ The worst thing is that you never know whether a function from a third party (CPAN?) module will return a tainted string or not. It may differ between platforms! For example, File::Spec is sometimes returning tainted strings on unixes, but not on Windows (or the other way around, I'm not sure!). In practice that means you will have to run your program, check if it throws an exception, and if it does, you have to use the above no-op "validation" regex. Well, that assumes that the said third party code works in taint mode. If it wasn't tested with it, it's possible that it won't work at all and there's nothing you can do about it.