The link on cross-site scripting was very enlightening. The general lesson I guess is that these evil outsiders are cleverer than I am.
This is making me think that I should write a module to lighten the load.
CGI::Paranoia
By default would create and inherit from a CGI::Safe object.
By default would create and stash a CGI::Untaint object.
Would respect the CGI interface but would ensure that all functions in the CGI interface returned untainted values. Examples: param(), self_url(), start_form()
The constructor would accept an optional CGI-like object to inherit from and an optional CGI::Untaint object to stash.
The constructor would also accept an optional hash map (param() => CGI::Untaint handler) and an optional parameter specifying the INCLUDE_PATH paramater of the CGI::Untaint object.
The constructor would require a default untaint handler that would be used in all other cases.