There are many language-specific security issues.
Many of them can be summarized as follows:
Turn on all relevant warnings and protection mechanisms available to you
where practical.
For compiled languages, this includes
both compile-time mechanisms and run-time mechanisms.
In general, security-relevant programs should compile cleanly with
all warnings turned on.
If you can use a ``safe mode'' (e.g., a mode that limits the activities
of the executable), do so.
Many interpreted languages include such a mode.
In general, don't depend on the safe mode to provide absolute protection;
most language's safe modes have not been sufficiently analyzed for their
security, and when they are, people usually discover many ways to exploit it.
However, by writing your code so that it's secure out of safe mode, and
then adding the safe mode, you end up with defense-in-depth (since in
many cases, an attacker has to break both
your application code and the safe mode).
Avoid dangerous and deprecated operations in the language.
By ``dangerous'', I mean operations which are difficult to use correctly.
For example, many languages include
some mechanisms or functions that are ``magical'', that
is, they try to infer the ``right'' thing to do using a heuristic -
generally you should avoid them, because an attacker may be able to
exploit the heuristic and do something dangerous instead of what was intended.
A common error is an ``off-by-one'' error, in which the bound is
off by one, and sometimes these result in exploitable errors.
In general, write code in a way that minimizes the likelihood of
off-by-one errors.
If there are standard conventions in the language (e.g., for writing loops),
use them.
Ensure that the languages'
infrastructure (e.g., run-time library) is available and secured.
Languages that automatically garbage-collect strings should be
especially careful to immediately erase secret data
(in particular secret keys and passwords).
Know precisely the semantics of the operations that you are using.
Look up each operation's semantics in its documentation.
Do not ignore return values unless you're sure they cannot be relevant.
Don't ignore the difference between ``signed'' and ``unsigned'' values.
This is particularly difficult in languages which don't support exceptions,
like C, but that's the way it goes.