Not a complete solution, but I thought perl's "taint" feature was a brilliant idea, and I wish more languages did similar. In short, data provided by the user is automatically marked as "tainted", and cannot be passed into a shell command, an SQL string, printed into the HTML, etc, without being explicitly converted into a safe form.
(I'd particularly like it if it were possible for the user to define their own types, so we could have "raw string", "validated HTML string", "validated SQL string", etc - and also "distance in meters", "distance in feet", etc -- and it wouldn't be possible to operate on different types without explicitly converting them into compatible forms)