DEV Community

loading...
Cover image for Protecting your Web Components (but you did not hear this from me)

Protecting your Web Components (but you did not hear this from me)

Danny Engelman
Online since 1990, Yes! I started with Gopher. I do modern Web Component Development with technologies supported by **all** WHATWG partners (Apple, Google, Microsoft & Mozilla)
ใƒป2 min read




Protecting your IP (Intellectual Property) can be done by filing loads of Legal documents. Doing it with script is fairly impossible. Everything can be reversed engineered.

The most you can do is use tools like JSObfuscator and JSFuck to make your code as unreadable as possible. But ofcourse experienced hackers have tools also...

Then it dawned me; it is all about adding extra hurdles, and there is one more hurdle we can call to action.



In JavaScript

customElements.define("my-element", class extends HTMLElement{ ... })
Enter fullscreen mode Exit fullscreen mode

can be written as:

let D = "define";
customElements[D]("my-element", class extends HTMLElement)
Enter fullscreen mode Exit fullscreen mode

and since customElements and HTMLElement are on window

we can write:

let D = ["0unused","customElements","define","HTMLElement"];
window[D[1]][D[2]]("my-element", class extends window[D[3]]{ ... });
Enter fullscreen mode Exit fullscreen mode

Nothing special thus far; this is how Obfuscators & Dictionaries work.




The epiphany only came after 25 years in the Web world...

If you load a script with:

<script src="element.js"></script>
Enter fullscreen mode Exit fullscreen mode

the script can reference its source:

console.log(document.currentScript.src);
Enter fullscreen mode Exit fullscreen mode

Thus, I can put the Dictionary IN the URI

<script src="element.js?-customElements-define-HTMLElement-"></script>
Enter fullscreen mode Exit fullscreen mode
let D = document.currentScript.src.split`-`;

// D = ["element.js?","customElements","define","HTMLElement"];

window[D[1]][D[2]]("my-element",class extends window[D[3]]{ ... });
Enter fullscreen mode Exit fullscreen mode

Notes:

  • put your files deep down in a nested Subdirectory, and split on slashes
  • Use a Sub-domain
  • check if your script is running from the correct location

And you have added so many hurdles the average code hacker will give up.

  • Check where strings are used. If your replace .connected be carefull not to replace .connectedCallback
  • A domain name can be 253 characters and may contain - hyphens inbetween
  • The Browser doesn't do a DNS Lookup for every document!
  • stuff as many JavaScript methods in the domain name
  • if you can't register customElements-define-ACME- ... - innerHTML-querySelectorAll.com; just swap a word
  • Use DNS prefetch: https://developer.mozilla.org/en-US/docs/Web/Performance/dns-prefetch
  • oh... and domain calls are done in lowercase.. so you need to be creative (I am not going to spill all the beans)

Your code is still not save, add more hurdles:

  • Whack some atob() conversions in.
  • Know your Array Methods : https://array-methods.github.io
  • Make your Dictionary Array dynamic (push,pop,unshift,shift)
  • Add a time check.. if its a second later (someone has opened the F12 debugger).. do something unexpected

  • Write a gulp script to post-process your files (you are not getting mine)

And most important of all; don't tell anyone!




Discussion (0)