Immutability and Security — From Java to Kotlin to Haskell

Axel Hodler
Level Up Coding
Published in
3 min readOct 31, 2020

--

Image by GLady from Pixabay

The state of an immutable object cannot be modified after its creation. If the object can be modified after its creation we call it a mutation of the object. In short the object is mutable.

Let’s use an example in Java.

We have list of allowedUsers , a method to getAllowedUsers and a method to check whether a username canUserAccessResource. We can think of it as a way to do some simple access control such as canUserAccessResource("Mallory") , which would, and should, return false. Mallory is not in the list of allowedUsers.

A more verbose example can be found in Programming Languages on Coursera

The code above has a mutation related issue. Where exactly? We think about it for a moment.

Our list allowedUsers can be modified to allow access to users which were not part of the list initially.

We create a test to make the issue visible and thus fixable.

Both tests are passing. Mallory, not in the allowedUsers at the beginning, can access the resource after the mutation of the list. That’s bad.

Instead of learning how we can alleviate the above why don’t we use more modern languages which might bring us immutability out of the box?

Like Kotlin?:

We have no need for the getter anymore. Plus, the docs on listOf state:

Returns a new read-only list of given elements.

Does this fix the security issue?

This time we use kotlinc REPL instead of a test

Attempts such as

authorizedUsers[2] = "Mallory"

or

authorizedUsers = listOf("Mallory")

will fail.

There is neither a set method to provide access to the list nor is there a way to reassign the authorizedUsers because we are using valinstead of var. Seems fine?

What we can do is cast it to MutableList and then modify it

The actual object authorizedUserscan be changed by another reference. Although the wording MutableList might suggest using List would be immutable it is not.

In defense of Kotlin: It’s stressed quite often how the wording read-only is used instead of immutability. Again, the docs of listOf state

Returns a new read-only list of given elements.

Read-only, not immutable. Let’s leave the JVM and continue with our immutability journey in Haskell. Haskell is a pure functional language.

Using the stack Haskell REPL.

Data is immutable in Haskell. We do not mutate the existing list but build a new list from applying the function. Haskell helps us to avoid the security issue by default.

Why does all the above matter? It’s about predictability. Would a senior programmer recognise the issue in the Java example? Quite likely. Would a junior or a senior with sleep deprivation on a deadline? Maybe. Would we want to keep in mind how every other part of the codebase is able to modify the allowed users? Let’s guess the answer is no.

True. We could have fixed the issue with Java by simply copying the list in the getter. Now it would not matter whether someone attempts to mutate the returned copy. The initial allowedUsers would not change.

Although creating the copy is something we would have to remember all the time. Mental overhead.

Would someone starting out with Kotlin realise the difference between read-only and immutability before stumbling upon it in the docs or when encountering a bug?

Seems like the simplest approach to getting the issues above out of the way is if our programming language is using immutability by default?

--

--

Building things. Usually by writing code. www.hodler.co. Software Engineering @porschedigital