How to prevent tracking sensitive data in URLs?
Asked Answered
M

3

7

Some URLs in my single-page-app (SPA) contain sensitive information like an access token, user information, etc.

Examples:

/callback#access_token=HBVYTU2Rugv3gUbvgIUY
/[email protected]

I see that hotjar allows suppressing DOM elements and images from tracked data. Is it possible to hide params in URL or at least disable tracking for some pages?

Mcbroom answered 10/2, 2020 at 12:11 Comment(2)
Have you considered putting those data into request headers using AJAX?Fractocumulus
Did you try putting, accessing that data through cookies?Lawanda
G
2

Since you are saying that it is your SPA, you might solve the problem by switching from GET requests (which have the parameters inside the URL) to POST requests. I do not know hotjar, but if you tell the tracking service to analyze URLs only, that would be an option worth considering.

Another option frequently used is to obfuscate your parameters in the URL, see e.g. Best way to obfuscate an e-mail address on a website? However, that is never a really safe solution for sensitive data, since the de-ciphering step is too easy, in particular if your man-in-the-middle has all requests ever send to your SPA.

Edit. I just found in the Hotjar allows RegEx. Assuming you could enter a regular expression of URL-parts to exclude. The general syntax /foo/bar/ means that foo should be replaced by bar, in our case, we want to delete the given snippet, that why it is /foo//.

For the given case of the access token, the regular expression would be

/callback#access_token=[a-zA-Z0-9]{15}//

and respectively for the email part of the URL

/\?email=(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])//

This second RegEx partially taken from How to validate an email address using a regular expression?

Greek answered 13/2, 2020 at 13:54 Comment(3)
It's a callback URL from 3-rd party service. I cannot change it. Having this token from the URL, someone can log in to the application.Mcbroom
I see the issue now. Can you use other tracking services?Greek
@TarasHupalo I just had another idea how to tackle your issue.Greek
S
2

It seems to me that it's reasonable to assume that tracking scripts will try to access window.location.href or similar to get the current url which they will store.

So a possible solution would be create a dynamic scope which has a different value for window.location.href (with all sensitive info filtered out)

This is how it might work:

// get the tracker script as a string, so you can eval it in a dynamic scope

let trackerScript = 'console.log("Tracked url:", window.location.href)';

// now lets lock it up
function trackerJail(){
  let window = {
    location: {
      // put your filtered url here
      href: "not so fast mr.bond"
    }
  }
  
  eval(String(trackerScript))
}

trackerJail()

If the tracking snippet is wrapped in a function it might be possible to create a dynamic scope for it without running eval by overriding it's prototype instead. But I'm not sure you can count on tracker scripts being wrapped in a neat function you can modify.

Also, there are a couple more ways the script might try to access the URL, so make sure to cover all the exits

Sufism answered 19/2, 2020 at 20:23 Comment(1)
(Unaffiliated) Reminds me of figmas sandboxing system: figma.com/blog/how-we-built-the-figma-plugin-systemTerse
T
2

If you control the page and order of scripts, you could read the data from the url then delete it before anything else can get to it.

proofOfConcept.html

<script id="firstThingToLoad.js">
    console.log(window.location.href);
    const keyRegex = /key=[^&]*/;
    const key = window.location.href.match(keyRegex);
    console.log("I have key", key);

    const href = window.location.href.replace(keyRegex, "");
    history.replaceState({}, "", href);
</script>

<script id="someSnoopyCode.js">
    console.log("I'm snooping: ", window.location.href);
</script>

<body>
    <a href="/?key=secret">Link to private</a>
</body>

Of course the Link to private should not exist as is. Also, this does break refresh and most navigation in general, though there are ways to catch and save that.

Terse answered 19/2, 2020 at 23:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.