jcpunk has asked for the wisdom of the Perl Monks concerning the following question:

This is a fairly simple question, i hope, the code below was suggested by ferrency to whom i am grateful, except that i am too ignorent to make it work.
my only restrictions are $username needs to have 3-16 letters/numbers and nothing else.
#!/usr/local/bin/perl -wT use strict; use CGI; ... $username =~ s/\W//g; if ($username =~ /(\w{2,16})/) { $username =~ $1; $username =~ tr/[A-Z]/[a-z]/; } else { #since username isnt able to be safe, it is empty $username =""; } `/bin/echo $username`;
Insecure dependency in `` while running with -T switch is my error... it seems as though the statement should be safe and untainting right? so what have i done wrong?
  • Comment on a terribly basic question showing my inept skills with regular expressions
  • Download Code

Replies are listed 'Best First'.
Re: a terribly basic question showing my inept skills with regular expressions
by bart (Canon) on May 17, 2003 at 21:31 UTC
    Replace this:
    $username =~ $1;
    with this:
    $username = $1;
    It'll both untaint the string, and do what is wanted.

    There's still lots of superfluous/horrible stuff in there, but at least, it should work now.

Re: a terribly basic question showing my inept skills with regular expressions
by Enlil (Parson) on May 17, 2003 at 22:25 UTC
    a couple things of note is that /(\w{2,16})/ will not check to see if the $username is between 3 and 16 letters and numbers. The fact that the lower limit is 2 will allow anything that is at least 2 characters. Also the fact that you have 16 in there doesn't do much more than tell the regex not to match more than 16 \w chars in a row. To put it another way it will match the most left hand match that is at least 2 characters long (in the character class [A-Za-z0-9_]) and will then try to match up to 16 characters (and this will be stashed into $1) Which might not be what you want as then anything over 16 characters will be truncated off when you replace the value in $username with $1. And as I already mentioned \w will match letters number and underscore (which does not fit your criteria) You might be looking for something more along these lines.
    ... if ( $username =~ /\A([A-Z0-9]{3,16})\z/i ) { $username = lc($1); } else { ... }
    Lastly if you are not going to capture what is output by the command you should use system instead of backticks (though you should probably capture what is returned by system anyhow) . Note: that $username will have to be chomped (have the newline removed) or \z won't match, in which case changing \z for $ will do just as well.

    One last thing is that you should really go through perlre and perlretut as they contain invaluable information.

    -enlil

Re: a terribly basic question showing my inept skills with regular expressions
by CountZero (Bishop) on May 18, 2003 at 07:45 UTC

    TIMTOWTDI

    1. chomp the password string
    2. Get the length of the copy of the password string and compare it to the minimum and maximum allowed length: if it is out-of-bounds, reject the password; otherwise
    3. Make a copy of the password string
    4. Delete all illegal characters in the copy of the password string:  tr/a-zA-Z0-9//d
    5. Compare the original and the copy of the password string: if they are different: reject the password string; otherwise
    6. untaint the password string

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: a terribly basic question showing my inept skills with regular expressions
by dws (Chancellor) on May 18, 2003 at 05:22 UTC
    My only restrictions are $username needs to have 3-16 letters/numbers and nothing else.

    Your code fragment also appears to want to downshift upper-case to lower-case. Is this also a requirement?

    If you're trying to verify that a tainted input is of a correct form, you might want to consider providing the user with an appropriate error message for malformed input. See this recent reply to a very similar question, which focuses on providing the user with a reasonable description of what they did wrong.