Java security architecture protects users and systems from intruders and incorrect code in many cases. Still, it cannot ensure protection against vulnerabilities created by development code. Development errors can unintentionally produce such software downfalls as access to files, printers, web cameras, and microphones. Intruders can use those errors to steal data from a PC, watch people through connected devices, shutdown hardware, facilitate further cyber-attacks, and perform other malicious activities.

Java developers should know safety development guidelines to cut down on vulnerabilities. You can learn several methods to develop safe Java-based software from this article.

Input Data Validation

Validation allows the system to receive only well-formed data. It is recommended to prevent attacks at the earliest stage while processing the user (attacker) request. Input check can detect unauthorized login before the app processes it.

All the data from potentially unreliable sources must be validated. It should be performed for outside API users as well as for internal services, as each of them can be discredited and send invalid data.

Input data validation should be applied to the syntactic and semantic levels. Syntactic validation must provide correct syntax of structured fields (e.g., SSN, date, currency symbol), while semantic validation should ensure meaning correctness in a specific business context (e.g., price location in a foreseeable range).

Important Data Delete from Exception Messages

Internal exceptions should be “caught” and cleaned of important information. Exception objects can pass through private data. For example, the with a file path is shown when the method calls a constructor to read the master configuration file and the file is missing.

If one resends that exception back to the caller, a file system mockup appears. Many attack methods demand to know or to guess the file paths.

From time to time, one should also sanitize exceptions that comprise data obtained from caller input data. It implies file access exceptions which can reveal the file existence and its location. An attacker can collect useful data by providing different file names as the input data and analyzing the resulting exceptions.

One should be careful with the exceptions that are thrown by third-party libraries. It might be that the previous library version did not include a potentially confidential part of data as an exception. The developer may approve that exception distribution. However, a later library version may add debugging information to the exception post, which comprises confidential data. The app provides that additional information, even if the application code hasn’t changed. Therefore, it is a good practice to process exceptions that can potentially pass confidential information.

Exceptions may also include confidential information regarding configuration and internal system components. One should not pass the information about exceptions through to the end-users without assurance about its content. For example, don’t include exception stack traces inside HTML comments.

Prevention of Confidential Data from Appearing in Log Files

Data such as SSN (social security number) and passwords is confidential. The system must delete these data right after the user ends operations with them. That information should not be sent in log files, too. Some temporary data can be stored in variable data structures, such as symbol arrays, and be deleted after the usage. Forcible memory clearing lowers the Java-powered apps performance, but improves the security level for developers.

It is better to be careful when using an external library. If a library in use has a log file, it is better to make sure no confidential data is sent to it. For example, a low-level syntax analysis library can log a text in work. SSN will also be among the data to analyze. In this case, admins with access to log files can also have access to SSNs.

Dynamic SQL Requests Usage Instructions

Dynamic SQL is error-prone if there are no additional libraries or request builders. Errors can be syntactical or, worse, SQL injections vulnerabilities.

One should use java.sql.PreparedStatement or java.sql.CallableStatement instead of java.sql.Statement for parameterized SQL queries with Java Database Connectivity (JDBC). It is better to use a well-written library of a higher level to isolate the app code from SQL. There is no necessity to restrict such symbols as quote (‘) when using this type of library. There is no need to prohibit characters such as “less” (<) in SQL inputs if a text destined for XML/HTML is processed correctly during the output.

Correct PreparedStatement usage:

String sql = “SELECT * FROM User WHERE userId = ?”;

PreparedStatement preparedStatement = con.prepareStatement(sql);

preparedStatement.setString(1, userId);

ResultSet queryResult = preparedStatement.executeQuery();

How a Superclass Can Affect the Behavior of a Subclass

Subclasses don’t have full control over their behavior. A super class can affect subclass behavior by changing the implementation of the inherited method, which is not overridden. If a subclass overrides all inherited methods, the super class in this case can still affect subclass behavior by introducing new methods. Such super class changes can inadvertently violate subclass assumptions and lead to security vulnerabilities.

Class and Methods Expandability Restrictions

One should note that classes open for inheritance or methods available for overriding can be used by intruders. Therefore, it must be taken into consideration at the designing stage. It is better to make a class final or forbid the overriding of particular methods if there is a possibility to get confidential information from it. An unmodified class is easier to implement and ensure its security. It is better to give preference to compositions over the inheritance.

// Unsubclassable class with composed behavior.
public final class SensitiveClass {

// Unsubclassable class with composed behavior.
public final class SensitiveClass {
private final Behavior behavior;
// Hide constructor.
private SensitiveClass(Behavior behavior) {
this.behavior = behavior;
// Guarded construction.
public static SensitiveClass newSensitiveClass(
Behavior behavior
) {
// ... validate any arguments ...
// ... perform security checks ...
return new SensitiveClass(behavior);

Definition of Wrappers over Native Methods

Java-based code is subject to runtime checks. Runtime errors comprise: NullPointerException, IndexOutOfBoundsException, FileNotFoundException, etc. The native code is not validated. Opposed to the pure Java code, native methods are not protected against traditional buffer overflows. Not calling the native method directly, and wrapping it in a Java method instead, can help to avoid problems described above. Try declaring the native method as private and exposing functionality with a Java-based public wrapper method. The wrapper can safely perform any necessary validation prior to calling their own method.

Preference for Immutable Value Types

The calling code can change the internal state instance if the method returns a reference to an internal, mutable object. If there is no need to change the field, returning a copy of the desired field is considered good practice. One should call the copy constructor for the specified field, or the .clone() method for this.

In Conclusion

Only some recommendations/practices for secure software development were mentioned in this article:

  • Input Data Validation
  • Important Data Delete from Exception Messages
  • Prevention of Confidential Data from Appearing in Log Files
  • Dynamic SQL Requests Usage Instructions
  • How a Superclass Can Affect the Behavior of a Subclass
  • Class and Methods Expandability Restrictions
  • Definition of Wrappers over Native Methods
  • Preference for Immutable Value Types

These practices let developers build robust systems. The issue of software security to develop must be noted as it helps save time, protect the company from financial losses, and ensure reputation.