At the very least, make sure data is filtered on input.Match constructs that are known to be valid and harmless. In addition, be sure to be skeptical about any data coming from a potentially insecure channel.
In a client-server architecture, for example, even if you wrote the client, the server should never assume it is talking to a trusted client. We have often seen situations in which people had a custom client-server application and the application developer assumed that, because the client was written in house by trusted, strong coders, there was nothing to worry about in terms of malicious data being injected.
Those kinds of assumptions lead people to do things that turn out badly, such as embedding in a client SQL queries or shell commands that get sent to a server and executed.
In some environments, you might need to be able to handle arbitrary data, in which case you will need to treat all input in a way that ensures everything is benign.
Avoid the latter situation if possible, because it is a lot harder to get right.
Let's look at basic rules for proper data validation.
As we said earlier, you should never trust external input that comes from outside the trusted base.
That is, routines that read from a socket usually do not understand anything about the state the application is in.
Without such knowledge, input routines can do only rudimentary filtering.
Cryptography can sometimes help, but even then, we have seen situations in which the attacker did not need to send data that decrypted properly to cause a problem--for example, as a buffer overflow in the portion of an application that does the decryption.
You can regard input validation as a kind of access control mechanism.
In addition, you should be very skeptical about which components of the system are trusted, even after you have authenticated the user on the other end!