Cross-site scripting (XSS).

Cross-site scripting occurs when a web application displays data from a user without escaping it first. Typically the attacker will try to use this flaw to run some JavaScript.

For example if a user enters a value into a form which fails validation. The application may display the invalid value back to the user so that the user can correct the error. A persistent XSS attack occurs when the data from the user passes validation and is stored in the database, to be displayed at a later date.

To defend against XSS, escape all data that has come from an untrusted source, such as a user. The special characters that you need to escape are different depending on where you are using the untrusted data. For example if you are using it as the body of an element, the JSTL <c:out /> tag will safely escape the text.

No results found for postcode: <c:out value="${postcode}" />

If you are using the untrusted data in the value of an attribute or as part of some JavaScript, different characters need to be escaped.

Whitelist validation helps, as well as checking the length of text a user has entered. The maximum length of a postcode is known, so check that the user has not entered a longer piece of text. You need to do this on the server-side as the attacker may not be using a browser, so maximum lengths specified in an <input> tag may be ignored.

The values of request parameters may be escaped in various ways to obscure an attack. You can guard against this by canonicalising (unescaping) all input data before using it.
Make sure you specify a language and a charset.

In addition, you can limit the damage by making sure that the database schema that the web application datasource logs into has the minimum privileges over the data. For example if the web app user cannot drop tables, delete data etc. and only has access to the minimum number of database tables, any drop table statement injected into the SQL will not run.