Would Hey-risk it? Part 18: The Unexpected

Picture of a jack-in-a-box jumping out of its box

This weapon, or weak spot if you prefer, is almost always an issue in some way. Let us check the rhyme and then go into the specifics:

”The unexpected and unwanted, make sure you address
Or one day they´ll make you some unhandled mess
Some general safety net should be in place
To handle the unhandled surprises with grace”

So, what does it mean?

Unexpected, and unwanted, input and/or behaviour needs to be handled gracefully.

I am not in any way saying the system should be bulletproof, or that you should have custom error messages for every single possible scenario.
But a user should not be able to cause the system to break into pieces by whatever shenanigans they come up with.

Depending on your application, your level of risk acceptance, your business and your users – you can do it in a multitude of different ways.

Of course, code should have proper error handling in place. Catching exceptions before they cause any big issues and letting the user know something went wrong.
If it’s something we can identify as a potential unwanted scenario we should also let the user know what they did wrong so they can fix it.
(But not too helpful, since this can be exploited by hackers!)

It’s a fine balance between generalising, throwing a bunch of similar things into the same bucket and produce a generic error message, and being explicit, making sure scenarios have uniquely identifiable error messages.
A good rule of thumbs for me has been that if a specific problem occurs in production, we make it explicit.

So, where to put it?
You have the aspect of user friendliness, where you want the error message to show up as soon as possible and as close to the culprit as possible.
Meaning as soon as a user leaves a field, it is validated and the user is immediately informed of the problem.
Or, you validate the fields when the user does some sort of confirmation action – Submit a form, save, move to next screen etc.
Or, you can validate in each service (or similar, depending on tech stack).
Or, you can validate in the database (if you have one).
Or, on any combination of those.
And the further ”down the stack” you get, that error needs to be sent back up towards the user in some way in order for them to know something went wrong.
Which to choose? Well. No one size fits all I’m afraid. But I can at least give some pointers.

You want to help the user do the right thing. So, you want validations, restrictions and other tools in the frontend, directly visible to the user. It saves them time, makes it easier to correct mistakes immediately, and it’s easy(er) to make it understandable to the user
But if you only validate things on the frontend, you risk someone bypassing the interface and getting dirty data into your database. Maybe you used JavaScript but forgot that the user can turn that off. Maybe you implemented a new way of communicating with the underlying service without an interface. Maybe an evil tester is using postman or the developer tools to test your services.

So, you want validations on your backend as well. Here you might want to both check that the data is ”clean” (as in, nothing that we don’t want here) and apply business rules. Maybe we want to check for duplicates, calculate some fields or check that this user is eligible for the thing they are trying to do.
But you probably don’t want to run all of those checks every time a user leaves a field, since that would be slow and cause unnecessary network traffic.

And you probably want validations on your database as well. Either by constraints on fields and formats or by different database rules. But these are even slower, and we will have to transport the error message a long way back to the user. These errors are also often the least understandable to a user.

Story time

Once upon a time we implemented a new digital form to replace a paper form. We spent a lot of time making it easy to use, understandable and tried to simplify what we could. We created guides, added pictures and put restraints in to make sure the users would always know what was expected of them.

We tested it thoroughly, especially the fields that had a minimum and maximum length, since I knew this was something that could be implemented in many ways, with different weaknesses. I entered manually, copy-pasted, copy-pasted and added, copy-pasted and added and deleted and added. Well, you get the picture. All was well!

In production we started getting really weird errors from some users. It looked ok and we just could not figure it out. First ones were just written of as ”something weird with that one”, but they kept coming! Not a lot, but more than a few.

It turned out if you copy-pasted from a certain text document-program, you got some extra, invisible, characters. Since we had the validation on the frontend – this slipped by into the backend where it went kablooie.

Quote of the day

“The best error message is the one that never shows up”

Thomas Fuchs

Reading suggestions

Application security – what is server side input validation – Ba Yin Min
Why form validation is important – Milecia McG
How to write good error messages – Saadia Minhas
Improper error handling – OWASP
Information Exposure Through an Error Message – MITRE
Discovery of Cyberattack Trends Targeting Connected Medical Device – Zingbox

Previous posts in the series

Title and linkCategory
Part 1: IntroductionNone
Part 2: Mischievous MisconceptionsTrap
Part 3: The RiftWeapon
Part 4: The FascadeTool
Part 5: The Temptress’ TrailsTrap
Part 6: AlliesWeapon
Part 7: Don’t turn backTool
Part 8: The GluttonTrap
Part 9: Beyond the borderWeapon
Part 10: Forever and neverTool
Part 11: The ShallowsTrap
Part 12: The TwinsWeapon
Part 13: The ObserverTool
Part 14: AlethephobiaTrap
Part 15: Opus interruptusWeapon
Part 16: The IllusionistTool
Part 17: Fools’ assumptionsTrap