Problem Solving: Mask Nested Attributes in Javascript
In this post I will explain the problem solving for hiding or masking, that is, to “cover”, attribute values that are nested and appear one or multiple times in a Javascript object.
Understanding the problem
In some cases, companies such as fintechs or healthtechs deal with sensitive data on a daily basis. This can become a problem when developers add logs in the code, in order to be able to debug it. These logs, are printed and stored in places like S3 or Google Cloud Platform for weeks/months or even years, where all developers in that company have access to.
Meaning that in beta environments we don’t have any problem as data can be faked, but in production, where data corresponds to real people, this seems to be a delicate problem. Developers in the company will have the chance to look at sensitive data that is being exposed, e.g. health results or bank account information; when this data does not contribute to the debugging process of the developer and it can bring problems in the long run, as it goes against the GDPR.
Determining the solution requirements
Therefore, what we want is a helper that takes care of masking or even hiding the sensitive data that we indicate it. In the majority of the cases, the best action to do is to mask the attribute as we still want to be able to debug and track that the attribute is contained in the object.
But it can exist the scenario in which we don’t even need the attribute because it is not essential for checking if our method/service is working properly, so therefore, we want to be able to hide this attribute from the object, not in the original object, but in a clone of it for the logs.
Once we know our problem and the solution that we want, we have to think about how to tackle this problem. Given an array of attributes to mask and a Javascript object, we want to look for these attributes in the object and then do whatever action we desire on them. For this, we will have to traverse the entire object searching and checking each key.
On the other hand, if we analyze a Javascript object such as the following one:
We can see that a JS object is basically a tree where each node is a key/attribute and we have the relationship of parent-child keys as one attribute can be an object itself and have subattributes.
So, taking another look at the object above, we can say that it is equivalent to:
Once we have converted our object into a tree, we know that we need to traverse the entire tree to check every single key. In this case, we can approach this problem in two ways: Depth First Search Algorithm or Breadth First Search Algorithm. Either one of these two algorithms will make the job.
Existent Solutions
When considering if we should use a custom solution or use an already-existing library, it is always preferred the second one as it implies less time and resources, and at the end, you don’t need to reinvent the wheel, right?
In the search of a library for this problem, we found some of them pretty interesting:
- Deepdash: It is a library built over Lodash which helps you dealing with nested values and attributes in object. The problem is that you only have the option to hide the attribute (using the omitDeep method) but not to mask it.
- Maskdata: It is a Node.js module to mask various kinds of data. With the help of maskdata, you can mask email, phone number, card number, JSON fields, password etc. The problem is that it only allows to mask the attribute, not to hide it.
In most of the cases with either of these two libraries will be more than enough to solve the problem, but it is still frustrating to not only have a library that can combine mask and hide, and also be able to add custom options such as the char to use for replacing the attribute value, or the length of the string that will replace the original value. So… I developed a custom one!
Choosing a Solution: Recursivity will be our ally
As we saw before, an object is just a tree from that we want to traverse. From the two algorithms that were mentioned before, I decided to go for the Depth First Search one applying recursivity.
In this way with the help of Object.keys()
, we will traverse each key and its child, checking if the node (key) visiting has children (it is an object), or it doesn’t any.
So for example, we want to mask from the object in Figure 1.1, the attributes id
and views
, maintaining the original length of the value. The resulting output when using the library will be:
To know more about the library which is called nested-mask, check the documentation here.