Elephant in the room

Hi team! Hi everyone! First off, I wanna wish everyone a Happy Lunar New Year! :firecracker: :firecracker: :firecracker:
My project is in its last leg of development and I would like to release it sometime this yr, hopefully =).
Having said that, I want to address the elephant in the room. How can I secure my code client-side?

The current adage is that since the client has access to what the server sends, all code client-side is therefore visible to the user. Either limit what the server sends, obfuscate client-side code or hide it somewhere. This works to a degree for a non-tech savvy user. For techies, ‘hacking’ client-side code is a breeze even if obfuscated/hidden since it resides in the client’s drive. The problem distills into a matter of time. However, I do not think that this problem has been tackled completely. Ideally, I would like to throw this question to an AI. Unfortunately, said AI does not yet exist…sigh…

So, what tech/science exists right now that can
a) prevent a user from reading/comprehending client-side code,
b) while not impeding browser functionalities,
c) and not creating a security risk (malicious code) ?

Can I encrypt client-side files and have the browser execute a code that decrypts and runs client-side files, say, in low lvl binary form after a chksum verification? If so, has it been done or is there a demo anywhere?

1 Like

There exist the API for this - SubtleCrypto - Web APIs | MDN
Crypto-js library - GitHub - brix/crypto-js: JavaScript library of crypto standards.

Pixel streaming

1 Like

I’m not familiar with your project and your needs, I’ve only done some low-effort protection.

  1. pre-fix for properties, methods, and classes (both static and non-static) needed renaming.
  2. Minifications

End result is pretty good for my use when most methods, classes and many properties are renamed. Making it hard to understand.

This method makes it also easier to debug if someone reports an error when I got the keys from the renaming.

Just minimize your code and mangle a list of words and be done with it. If you’re using webpack, you can add this to your production build (remember to update regex):

optimization: {
        minimize: true,
        minimizer: [
            new TerserPlugin({
                terserOptions: {
                    mangle: {
                        properties: {
                            regex: /add|words|here|you|want|mangled/,
                        },
                    },
                    compress: true,
                },
            }),
        ],
    },

You could make half the code work on apple and half the code work on desktop, so the user has to hold their phone in front of their left eye and look at their pc with right eye to get the full experience. But , babylon is equal opportunity for pirates, and as you know, many pirates have eye patches.

4 Likes

what it the intellectual property you are trying to protect?

if it is models then you can look at what some 3d model sharing sites do - it looks like they have their own custom format and loader. they have copyright notices as they know it’s not full proof. at least you can’t grab the common format directly from the network stream.

if it is javascript code then I don’t think anything above will prevent a determined person to work out what your code is doing. if you are decrypting it client side that is not a lot different than transport security - the decryption key is in the browser. I have worked a lot with obfuscated code and it can be deobfuscated to the point of being able to understand. i can also step through the prettified code in the browser and often work it out. you can certainly do a lot of things to make it not worth the effort for the casual curious person, but the only way to protect your code is to run it server-side. even wasm has decompilers!

2 Likes

btw there is “ai” called virtual photogrammetry that can recreate models from your screen.

so, your models arent safe and your engine isnt as good as unreal.

My heurstic is kind of: for protecting reads, use the legal system. For protecting writes, dont make your technique public.(imo p2p hash verification is probably the best/easiest)

Here is an idea: Replace EVERY .toString method with Object.toString() using Object.defineProperty to also make it read-only (that way no one can get results in the console).

The real way to protect it - like I’ve done with my game - is to use a Terms or Service that pretty much says: "If you access the project in anyway, via loading a webpage, or viewing the code, you agree to these terms … by agreeing to these terms, you agree to not duplicate, distribute, etc… any portions of this project’s code. Should you break these terms we reserve the right to… "

For example: my game’s ToS

2 Likes

Thanks for all the responses. I guess my question was a little too fudgy, let’s make it dirt simple. Ignore my project/assets/my coding…just treat it as:

<script type="text/javascript" src="helloWorld.js"></script>

In this timeline and reality, the browser reads the above, requests said file from server, loads it in memory, executes code, yada yada yada. The curious user can find > read > reverse-engineer > comprehend contents of file, minified/obfuscated/eyepatch or not. This flow is transparent.

As a dev, I want to protect helloWorld.js from prying eyes. I cannot prevent the user from finding/reading files. But I should be able to prevent the user from reverse-engineering and comprehending helloWorld.js easily.

So the analogy would be similar to the retro games that you buy and install from diskettes onto your hdd. There would be compiled files (.dat/.bin) which require the user to obtain hex editors to write into specific locations in order to cheat. I am happy enuff if the browser executes helloWorld.dat/bin/js and the user can access and read said files and see nothing but machine code.

“…require the user to write into specific locations in order to cheat”. that is a write and verification problem, not a read problem. is your purpose tamper detection or obfuscation? tamper detection is an interesting topic imo, obfuscation not so much.

If you are trying to prevent the user from accessing code, you could implement private class fields and restrict user interaction to functions. For example:

const game = new (class {
    #engine = new BABYLON.Engine();
    #scene = new BABYLON.Scene(this.#engine);
    #internal(){
        /*do something*/
    }
    constructor(){ /*do something*/ }
    logData(){
        console.log(this.#scene)
    }
})()
game.#scene //syntaxError
game.#internal() //syntaxError
game.logData() //logs game.#scene!

No need for any legal stuff or obfuscation or minification.
As for preventing the user from reading the file: In order for a file to be run, it first must be read first - you can bake a cake without the ingredients. I can’t think of any way you could prevent a file from being read while being executed.

1 Like

There is also https://obfuscator.io/ which has an accompanying npm module as well. I have used this with no issues before on web apps/sites

I kind of assumed phaselock meant that most online web games will end up like https://krunker.io/ with 99% of the population as bots because its hard to do anti-cheat with freely readable js in the browser (that being the elephant). My guess is he has security experience, because of his wise conclusion that security doesn’t exist, it only “distills into a matter of time”.

1 Like