Should You Report the Message Text of Exceptions

Should you report the message text of exceptions?

If you are presenting an error condition to the user, it should probably be a user-friendly message. Exceptions contain technical details that the user should not/does not need to know.

In some situations it could be a security concern to present stacktrace information, so the user should never be shown stack traces.

If you are displaying error messages to the user, there is some point where you consciously make the decision to show a popup, or add a message to a log window. At that point you can translate any exception into a more user friendly message. Note that you might need more information than the default Exception types provide, so you can/should probably create you own Exception types that contain all the information you need to present all the data you need to the user.

possible to expose sensitive information via Java Exceptions?

The most common way of exposing sensitive information is to give the user (client) of the program a stack trace.

A stack trace is useful for programmers debugging a problem, and not to anyone else. So logging code should not output stack traces as a matter of course. It should output them only when an exception indicates a bug in the program. And it should output them where they can be made available to a programmer, but to as few others as possible.

If a program has a log file invisible to normal users of the program but visible to administrators (as is the case with servers), that is an appropriate place to log stack traces.

Similarly arguments apply about other sensitive information.

Although your question is entirely about security concerns, this can be considered too as a user experience (user interface) issue: the messages you give to the various users of the program should be appropriate for those users, and should provide them with information that is useful to them, without extraneous information that could confuse them. In particular, the message text of an exception should not be reported to users (but should be include as part of any stack trace).

For a client-server program, the clients have no interest in the details of why the server failed to process a request sent by the client. They need to know that the request did fail. If the request failed because of a problem with the server, rather than a faulty request by the client, they need to know that is the case, so they can contact the administrators to fix the server. If the request failed because the client sent a faulty request, the client should be told that, with a description of what was faulty about the request, so the client can send a corrected request.

Also, beware that not all exceptions indicate a problem that some user must be told about. If the program automatically handles the condition signalled by an exception, in many cases there is no need to tell the user at all about the condition signalled by the exception.

Custom Exception Messages: Best practices

I strongly recommend the advice on Krzysztof's blog and would note that in your case you seem to be trying to deal with what he calls Usage Errors.

In this case what is required is not a new type to indicate it but a better error message about what caused it. As such a helper function to either:

  1. generate the textual string to place into the exception
  2. generate the whole exception and message

Is what is required.

Approach 1 is clearer, but may lead to a little more verbose usage, 2 is the opposite, trading a terser syntax for less clarity.

Note that the functions must be extremely safe (they should never, ever cause an unrelated exception themselves) and not force the provision of data that is optional in certain reasonable uses.

By using either of these approaches you make it easier to internationalise the error message later if required.

A stack trace at a minimum gives you the function, and possibly the line number, thus you should focus on supplying information that is not easy to work out from that.

Java: what information in error stack trace do we typically not wish to show users?

You shouldn't show any of that gobbledygook to your users. It's meaningless to most of them and doesn't help you. As you suspect, it also exposes internals of your implementation that may suggest vulnerabilities that a malicious user might be able to use.

Instead, you should catch exceptions, log them, and show a more comprehensible error message to your users. You can use getMessage() to extract the message part of an exception. If the exception has no message, then show something like "no details available".

UPDATE:

I have some comments based on the question update. First, I would totally insulate the user from any of the internals of your system, both to be kind to the user and for security. (For instance, even knowing that you are using the java.sql package may suggest vulnerabilities to a clever hacker.) So do not use the exception message, the first line of the stack trace, or anything like that when displaying anything to the user.

Second, you should be mapping all errors from the exception level (at which they are experienced in your code) to messages that are at the right level of abstraction for the user. The proper way to do that would depend on the internals of your system and what the user might have been trying to do when the exception was raised. This might mean structuring your system into layers such that each layer that catches an exception translates it into an exception at a higher layer of abstraction. A Java exception can wrap another exceptions (the cause). For instance:

public boolean copyFile(File source, File destination) throws CopyException {
try {
// lots of code
return true;
} catch (IOException e) {
throw new CopyException("File copy failed", e);
}
}

Then this could be used at a higher level in a User class:

public boolean shareFile(File source, User otherUser) throws ShareException {
if (otherUser.hasBlocked(this) {
throw new ShareException("You cannot share with that user.");
}
try {
return copyFile(source, otherUser.getSharedFileDestination(source));
} catch (CopyException e) {
throw new ShareException("Sharing failed due to an internal error", e);
}
}

(I hope it's clear that the above code is meant to illustrate the idea of converting exceptions to higher levels of abstraction, not as a suggestion for code that you should use in your system.)

The reason that you want to handle things like this (instead of somehow massaging the message and/or stack trace) is that an exception (for instance an IOException with message "permission denied") may mean totally different things to the user (and to your system) in different contexts.

Java Logging exceptions, use getMessage or toString : log.warn(ex.getMessage()) or log.warn(ex) working with open source

How about

log.warn("some descriptive message, maybe with context {}", 
someId, ex);

The exception details will already be printed as part of the stacktrace, so you don't need to include them in the message usually.

In case you want to suppress the stacktrace and only print the exception message, usually, ex.toString() works better than ex.getMessage(), because it also includes the exception class name, which the message does not. In fact, often the message is empty (for example with NullPointerExceptions).

Intercept Exceptions to Translate it to another language

You can catch an exception, and then throw a new one of the same type (or a different type if you prefer). Then translate the message from the original exception and pass it into the new exception. Something like the following (not tested):

try {
// do something
}
catch (Exception e) {
throw new Exception(translate(e.getMessage()))
}

public String translate(String message) { /* translation code */ }

Update in response to comment:

If you can modify the application (and particularly if the application uses custom exceptions derived from a few base classes) then you might be able to modify these to retrieve translated messages (but if you could do that, you could build in the translated messages, or full internationalisation, from the start!).

Intercepting and replacing all Exceptions globally is probably not possible, although it looks like you can at least detect them globally using debug hooks - see this answer. It's conceivable that you could modify the Exception message on-the-fly using reflection, but this sounds pretty nasty.

One final possibility is to use Aspect-Oriented Programming (AOP) to compile-in extra behaviour around code that throws an exception (see this question, for example). You'd need to recompile the whole application using AOP tools though, and would probably still need to modify the application code a bit.

Where to format exception message and how to report it to client

I can't decide where to format exception message and how to correctly report it to client.

My Opinion:

Giving the end-user an exception message shouldn't happen ever. An exception in a web context means that code is incorrect. This should be logged for an administrator/developer to handle. I would suggest reading Eric Lippert's blog on Vexing exceptions on the types of exceptions and how to handle them.

This doesn't mean that the client should be not aware that something went wrong however. In most cases, it's enough to tell the end user that something went wrong, the company is aware of it and working to correct it. In exceptional cases, you may want to include an incident number (tracked back to the exception logged identifier) on the page if your company needs to contact the client.

When I need to do a ton of ajax, I wrap every single call through a single global function. You can take a look at it in the question: Return partial view if action is ajax or child action universally . Doing this also means that if the authentication ticket expires, you can STILL return nice ajax that can tell your client side to do whatever you want (popup a login modal, redirect to login page, whatever).



Related Topics



Leave a reply



Submit