Protect Personally Identifiable Information (PII) in Your Apps Using RudderStack
Tags: security, android, ios, rudderstack
Published: 2020-04-06 14:52:07

<!-- wp:heading -->
<h2>Introduction</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong>Personally Identifiable Information (PII)</strong> is the information that may be used to identify and track an individual. GDPR mandates software companies to encrypt any PII and ensure that they protect the users’ identity from any misuse. As a result, In a post-<a href="https://gdpr-info.eu/">GDPR</a> world, all organizations need to detect and mask/obfuscate/delete PII data flowing through their information systems. Refer to this <a href="https://www.csoonline.com/article/3215864/how-to-protect-personally-identifiable-information-pii-under-gdpr.html">article</a> for more information on PII and how to protect it.&nbsp; </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>One typical reason for PII data leak is human error.  Developers add various user-centric attributes as part of the "traits" structure in a message. Due to this, one might inadvertently include a PII event that gets forwarded to the destination. This could be almost a disaster from the data privacy perspective.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>At <a href="https://rudderstack.com/">RudderStack</a>, we simplify the process of performing PII checks and incorporating corrective actions on the streaming data. Hence, we have provided template PII Detection and Masking code on <a href="https://github.com/rudderlabs/sample-user-transformers">GitHub</a>. Developers/administrators can introduce this code as a user transformation in their RudderStack installation via the Config Plane.  This transformation will protect human PII data leak oversights from resulting in serious non-compliances.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>You can mask/obfuscate PII within RudderStack, as a result, you eliminate:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>The need to encrypt such data for GDPR compliance</li><li>Risks associated with a potential data breach</li><li>The need to search through and delete data in the event of withdrawal of consent</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Implementation</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>First of all, copy the code from GitHub into the <code>Transformation</code> window under <code>Transformation Settings</code> for a user transformation:<br></p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://lh6.googleusercontent.com/lQt3ayErzDL1rNNVkVvk-N_SEsVXvGH9OztKkvW9vt-qUJwPR41f51LUZf6PjRDnvDAI2fanIombNXlpElX1uxMB6LUSvjL3pj3FDicZ3dCWTQQE4gBpzJOy503Za8dZWPvPvwgh" alt=""/><figcaption> User Transformation page in Rudder Configuration Plane </figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>The code in question leverages the <a href="https://github.com/farzher/fuzzysort">fuzzysort</a> implementation. The following code block demonstrates the implementation:</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>function transform(events) {
    
 //traverse the JSON structure and replace PII fields with obfuscations for fuzzy matched keys
 for( var i = 0; i &lt; events.length; i++) {
     
     event = events[i];
     walk(event,['SSN','Social Security Number', 'social security no.','social sec num', 'ssnum'],'XXX-XX-XXXX');

 }
    
 return events;
}

function walk(obj,targetKeyArray,newValue) {

 for (var key in obj) {
     
     value = obj[key]
     if (value &amp;&amp; (typeof value == 'object')){ //recurse till leaf is reached
         walk(value,targetKeyArray,newValue)
     }
     fs = fuzzysortNew()
     matches = fs.go(key,targetKeyArray,{allowTypo: true})
     if ((typeof matches != "undefined") &amp;&amp; Array.isArray(matches)) {
         if (matches.length > 0) {
             obj[key] = newValue;
         }
     }
 }</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>PII Substitution Logic</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The <code>transform</code> method is the entry-point for any user transformation. It takes an array of <code>event</code> objects as an argument and returns an array of transformed <code>event</code> objects.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>So, in the sample above, we iterate through each event in the array and invoke the <code>walk</code> method. The <code>walk</code> method takes three arguments:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>The object itself which has to be traversed</li><li>List of keywords (i.e., field names) for which fuzzy matching is to be performed</li><li>The substitution value</li></ul>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>You can include all variations of all target field names in a single list and pass that as an argument. Furthermore, the values of all fields such as SSN/Social Security Number/Credit Card Number/First Name/Last Name would get replaced with a single masked value, XXX-XX-XXXX. In contrast, the requirement might be to have different substitution values for different fields. In that case, you can call <code>walk</code> multiple times with different lists to match. The <code>walk</code> method recurses through the object hierarchy. So, as part of the recursion, the actual substitution takes place only at the <code>leaf</code><strong> </strong>nodes. A leaf is a primitive data type node.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>You can choose to use different variations of methods available in the library and described in fuzzysort. The sample implementation uses the <code>go</code> method and specifies <code>allowTypo</code> as <code>true</code>. So, the code would consider that a word with a single transposed letter as a valid match. As a result, whenever the code finds a match, it replaces the value of the matched key with the substitution specified.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Sample PII Detection and Masking Transformation in Action</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The following screenshots show the transformation in action. The first screenshot shows an exact match with one of the keywords specified. Furthermore, the second screenshot shows a fuzzy match where the field name does not exactly match any of the keywords supplied.<br></p>
<!-- /wp:paragraph -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://lh5.googleusercontent.com/aM2k8ghqIx17Gl3Opk_sIUmvi72fsA3l2jrBbfdqz1x64uWOhY2a_esZUhrd7oJ8ggPqI12RQ6mldbEZd_ZHjZR_0K9Yb06nIY08I-8XnGPoguRiXfHwZ2woYpzmIOSEKM31GFPb" alt=""/><figcaption>Replacement with direct match<br></figcaption></figure>
<!-- /wp:image -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://lh6.googleusercontent.com/55n9TNY3AdJTH6sp9c-e98YUcCIJAIMfcWkcNhlZxOCs_cu9IQ47TvMqGijSQL7qhsQds75WUFaEGyR6X3Ax1uo-uCEzW0aVp0NZlDiFj_I2qpjCblU9Iv4Xe4yS-W-oYdoKV0SQ" alt=""/><figcaption> Replacement with fuzzy match </figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Conclusion</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Template PII Detection and Masking code is a handy tool to integrate PII detection and masking into your RudderStack installation. Because of this, we have made it available as a part of our open-source sample transformations collection. You can choose to vary the degree of complexity/flexibility you want in your detection and masking code and modify the walk event accordingly.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>To explore RudderStack and offerings for your business with RudderStack, <a href="https://rudderstack.com/request-a-demo/">request a demo</a>.<br></p>
<!-- /wp:paragraph -->