Unlike C/C++ applications where source code is compiled into native machine code (.exe, .dll, etc.) and is not exposed to end-users, Javascript Apps (React, Vite, js) that run on the client-side have their source code exposed and that is exactly how it is supposed to work: the bundled code is what makes the app run on our browsers.
Of course, it is:
- obfuscated (variables & functions renamed to random combinations of letters)
- minimized (unnecessary tabs/whitespaces removed)
But still, it can be pretty easy to guess the logic and discover the variables if you have decent debugging knowledge. This brings us to the topic, fueled by my curiosity:
Is it possible to manipulate Javascript source code in the browser?
const [isLoggedIn, setIsLoggedIn] = useState(false);
Manipulating the source code to change isLoggedIn
's default state to true
would be interesting, right? (I know this is starting to sound like the "hacking a website using inspect element" agenda)
Now, a quick google search would of course lead us to the answer that it is not possible. But there are still some unanswered questions related to this topic that we should go through:
1) What if we manipulate the source code under the browser's devtools assets?
2) Can we manipulate the variables/states in the browser's console?
Let's find out! We'll spin up a quick and simple Vite + React app in a production (build) environment:
pnpm create vite pnpm run build pnpm run preview
Browser used: Chrome (v138.0)
1) Direct access via assets in Browser DevTools:
The transformed code can be accessed under the assets/
directory in Sources tab in the devtools:
We can see that the names of variables and functions are all obfuscated:
If we directly try to override the code here, the browser prompts us to save the changed source files locally in order to view the desired changes:
This measure ensures that the changes only take place in the local enviornment. Hence, the source code on the actual domain origin, let's say "abc.com", remains unhanged. The local changes are harmless and equivalent to using Inspect Element in the browser, considering the backend server has adequate CORS policy set up.
Hence, no chance of code manipulation here.
More about this feature: developer.chrome
2) Access via browser DevTools' console:
We earlier came across the transformed code. It had some variables in the root of the javascript file:
const X1 = "/assets/react-CHdo91hT.svg" , Q1 = "/vite.svg";
Let's check to see if the X1
variable can be accessed via the console. If it can be accessed, it can be modified:
Turns out the javascript code is inaccessible in the global window
environment i.e. the environment that the browser's end-users operate in.
The reason behind this behavior is the type of the script used for javascript app code: Module. The scope of the code inside a type="module"
script is limited to that module only and inaccessible at the global level.
Since the index.js
file is of type module
, all the code is pretty much encapsulated and inaccessible. Hence, no chance of code manipulation here either.
End notes:
- This is a battle-tested area that we poked around with and there might be other ways to test the vulnerabilities of this topic, but we tried manipulating the code through the most commonly recognized areas: i.e. DevTools
- The code, though immutable, is still completely visible. So, it's always recommended to store any sensitive information (API keys or secrets) on the server.
- Even when using modules, the usage of global
window
object to declare any variable/function can expose it globally:
<script type="module"> const secret = "hidden"; window.exposed = "visible"; </script>
Top comments (0)