All communication across a network is governed by what network people call protocols. A protocol defines how communication is supposed to take place; it assigns a meaning of the chunks of data being sent across the network.
If you compare a network application to a game, then the protocol is the set of rules that apply. Protocol definitions state things like: If, under certain conditions, participant A says boo!, then participant B must react by performing action X.
Note the word must in the previous sentence! The most common mistake people make when implementing network services is that they read will instead of must. They assume that other participants will always behave as the protocol says. But very much as with every game, there are cheats who refuse to play by the rules. And if you are not careful, you will not even notice you're being cheated before you've lost.
That is why, in a network application, you should never make assumptions about the data presented to you.
This will sound pretty much like motherhood and apple pie wisdom; and it probably is unless you know exactly what data an attacker can control, and how.
As an example, here's a very common mistake people make when writing CGI scripts in Perl.5.1 For instance, early versions of the Apache Web server came with a CGI script that displayed user information using the finger program. To be sure, there's a network protocol here, even if it's a very simple one: the client sends a request to the web server asking for /cgi-bin/finger.cgi?username, and the server returns some HTML gibberish containing either some information on the user indicated, or an error message. The code was fairly simple; it would obtain the argument passed by the client, and invoke /usr/bin/finger giving this string as an argument:
system "/usr/bin/finger $user";
Perl's builtin system function works pretty much the same way as the one in your standard C library does; it invokes the shell and gives it the string for evaluation. Now if a malicious client invoked this CGI script giving a login name of root;evil_command, the shell will recognize the semicolon, and dutifully execute finger root first, followed by evil_command.
If you've been following security mailing lists for a while, this type of bug will be painfully familiar to you. But it perfectly illustrates the sort of mental short circuit that sometimes afflicts even the best programmers, and leads to security bugs. Something in the brain of whoever wrote this script probably said: ``See, there's the login name passed by the client, and we all know that login names are alphanumerics only, so if we pass it to the shell no harm is done. QED.'' The author expected the client to conform to the protocol he had devised, and to pass a valid login name.