Introduction
In modern frontend development, tools like Vite, Webpack, Rollup, Parcel, and esbuild are commonly used to build and bundle frontend applications. These tools convert the written code into browser-executable JavaScript files (.js) and can also generate source map files. These files help developers debug and track issues more effectively.
Source maps are compiled to provide convenience during the development process, allowing developers to map original code
to compiled code
. These files usually end with .map
(e.g., example.min.js.map
or styles.css.map
).
Through these source maps, developers can easily track and fix errors during debugging, ensuring the code works as expected before entering the production environment.
Before deploying applications to production, the code is typically further processed to enhance performance and security. These processes include minifying the code, removing comments, and applying obfuscation techniques. These steps not only reduce file size and improve load speed but also make the original code harder to reverse-engineer.
For example, a variable like let isLogin = false
might be obfuscated to let a = 0
to protect the logic of the code.
In production environments, source maps are usually removed to prevent malicious individuals from reconstructing the original code. However, sometimes source maps may accidentally be compiled and uploaded with the code, which can pose potential security risks.
This article will explain how to use these source maps present on a website to reconstruct the original code. Understanding this process helps developers better protect their code and take appropriate measures to prevent potential security risks.
Analyzing Website Source Maps
First, press F12 to open the browser’s Developer Tools (DevTools) on the target webpage. Then, go to the “Sources” tab to find the original code loaded by the webpage.
If the webpage has source maps, the browser will automatically parse and restore the original code. The left image shows the obfuscated code without source maps, while the right image shows the restored original code after parsing the source maps.
In the compiled code, if source maps were chosen to be compiled, the source map information will be embedded at the bottom of the .js file. The developer tools will automatically reconstruct the original code based on this map file, as seen in the highlighted section of the right image.
|
|
Analysis of Source Maps
We can directly download main.XXXX.js.map
, which is in JSON format.
Here is an example of a standard source map file:
|
|
A standard source map contains the following key fields:
No. | Field Name | Description |
---|---|---|
1 | version | Indicates the version of the source map. The version number here is usually 3, which is the most common version supported by modern browsers. |
2 | file | Indicates the output file name corresponding to this source map file. In this example, it points to static/js/main.XXXX.js , a minified or compiled JS file. |
3 | mappings | A complex string used to describe the mapping relationship between the minified code and the original code. This field tells the browser where each line and column of the minified code corresponds to in the original code. The string uses VLQ (Variable-Length Quantity) encoding to efficiently compress and represent this mapping information. |
4 | sources | An array listing the filenames of the original code. Here, index.tsx and utils/useLazyFetch.js are two files from the original code, indicating that these files were compiled into the final main.XXXX.js . |
5 | sourcesContent | An array containing the original content of each file in the original code . If present, it will directly show the original code content. Even if the original files are inaccessible, the developer tools can retrieve the code from the source map. |
6 | names | An array listing all the identifier names used in the original code (e.g., variables, function names). These names are referenced in the mappings to help the browser restore the obfuscated names back to their original names. |
7 | sourceRoot | The root directory of the original code, used to help construct the complete source file path. Usually, this is an empty string, indicating no specific root directory. |
How to Restore Source Maps?
There are several tools available that can restore the original files using main.XXXX.js
and main.XXXX.js.map
as inputs. For example, the restore-source-tree tool. However, this tool may be outdated, as it didn’t work during my tests and could only recover one .map file at a time.
In comparison, I recommend the sourcemap tool, a powerful tool implemented in Go. You only need to provide the target website’s URL to restore the website’s frontend source code.
The process is very simple: Install Go → Clone the source project → Compile the project → Run it → Obtain the original source code.
Installing Go
Traditional Installation Method: Go to the official Go website to download and install.
Windows Installation using WinGet:
|
|
Linux:
|
|
The installation process is usually straightforward. After installation, you can verify the success by checking the Go version with the following command:
|
|
Example output:
|
|
Cloning the Sourcemap Project
Enter the following commands in your personal directory to clone and compile the project. Before proceeding, make sure you have Git installed:
|
|
Converting Website Source Maps to Source Code
In the same directory, run the following command to convert the website’s map into source code.
|
|
Example output:
|
|
You can then find the original source code under ./sourcemap/sources/xxxx.com
. This source code contains the folder structure, comments, package info, etc.
Conclusion
This article detailed how to use .js
files and source maps
to restore the frontend source code of a website. If source map files are exposed in a production environment, it means that users can reconstruct the original source code.
This could allow malicious individuals to discover potential vulnerabilities, APIs, test URLs, or even the author’s Gmail information (if it exists in the comments). Therefore, ensuring that source maps are not accidentally uploaded to production environments, or promptly removing these files when discovered, is crucial for protecting your source code.
Moreover, while removing source maps can effectively prevent the code from being easily restored, attention must still be paid to the security of the code logic itself. Ensuring the robustness and security of the code is key to preventing potential vulnerabilities.