Need Object taint

Crystal doesn’t at present have a security model. This is most important for the web frameworks implemented in it, but I think it is general enough that it belongs in Crystal.

To solve the general issue of sanitizing input from the user before it is saved or rendered, Crystal needs Object and Struct taint, which of course should be copied from Ruby. This is a ton of work because it needs to be preserved across all String operations and all string parsing operations such as to_i . It should then be the case that objects are sanitized before being rendered or saved, unless the programmer insists.

For those unfamiliar with the Ruby implementation, input from the user got a taint bit set, which web frameworks like Rails used to prevent them from being rendered (and possibly saved) without being filtered, unless the programmer insisted. There was also a parallel feature called trust which was less used.

Discussion of the Ruby taint/trust feature

Do you realise the taint concept has been deprecated in Ruby 2.7 because nobody used it? https://blog.saeloun.com/2020/02/18/ruby-2-7-access-and-setting-of-safe-warned-will-become-global-variable.html

And honestly, I don’t think it makes sense. Input sanitization has many facets. IME you can’t reasonably express a need for sanitization just by a binary flag. Think about having sources and sinks with different trust levels.

1 Like

Agreed.
I do wish, though, that there was a common implementation of a HTML-safe string.
E.g. to extract https://github.com/straight-shoota/crinja/blob/master/src/runtime/safe_string.cr into a library like https://pypi.org/project/MarkupSafe/

Oops. I guess it’s been that long since I’ve been a Rails coder. Taint was implemented when I used it.

Having sources and sinks with multiple trust levels sounds good, but it’s just as much work to implement, and has a potential space penalty since every object would be carrying a byte around. We might have been able to squeeze a bit in without a penalty.

I’m partial to the idea of tainting user-input as a way of keeping Strings from reaching sensitive functions (ex: system). However, my Functional Programming colleagues on Twitter insist that representing both unstructured/unvalidated as well as structured/validated data as Strings is a code-smell. Perhaps a compromise would be to represent user-input from say web frameworks as String-like objects which can automatically handle the escaping/unescaping? This would be similar to Rail’s SafeBuffer.

That’s a good idea @oprypin. Should have a shard like MarkupSafe for re-usability.

And that python lib also proves the point. MarkupSafe is used to express a text object is “safe to use in HTML and XML”. It doesn’t have any meaning regarding SQL queries or shell commands for example.

Yeah, that’s probably true. It’s easy to shoot yourself in the foot when safe and unsafe content gets mixed up.

@postmodern Yeah, SafeBuffer actually served as inspiration for crinja’s SafeString.

1 Like

Btw. since we’re on the topic, I might add a shameless hint towards sanitize for sanitizing HTML/XML ;)

2 Likes