Security Vulnerability Report
Server-Side Code Injection Leading to Remote Code Execution in Total.js CMS
Product: Total.js CMS
Affected version: v1.0.0, current master at the time of testing
Framework: total5 v0.0.18
Severity: Critical
Suggested CVSS: 9.2 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)
Testing status: Successfully reproduced in a local test environment
1. Summary
I identified a server-side code injection issue in Total.js CMS that can lead to arbitrary command execution on the server.
The issue is related to the CMS widget functionality. Widgets can contain a <script total> section, and the server processes this section using JavaScript's new Function().
The problem is that widget content can be supplied through the CMS interface and the resulting code is executed directly inside the Node.js process. As a result, a user who has permission to create or modify widgets can potentially execute arbitrary JavaScript with the privileges of the CMS process.
During testing, I was able to:
- Create a malicious widget.
- Execute JavaScript on the server.
- Access Node.js functionality from the injected code.
- Execute an operating system command using
child_process.
- Write a file to the server filesystem.
- Confirm the command output through the CMS interface.
- Confirm that the injected widget is stored and can be recompiled when the application starts.
This means the issue can result in remote code execution and potentially complete compromise of the CMS host, depending on the privileges of the Node.js process.
The vulnerable code path and affected components are documented in the sections below.
2. Vulnerability Details
Vulnerability Type
CWE-94: Improper Control of Generation of Code (Code Injection)
The vulnerable functionality is located primarily in:
definitions/func.js
plugins/widgets/schemas/widgets.js
The widget compiler processes the <script total> section and passes the resulting content to new Function().
The relevant behavior is:
(new Function('exports', meta.total))(item.ref);
meta.total contains the contents of the widget's <script total> section.
This causes the supplied JavaScript to be compiled and executed inside the server-side Node.js process.
3. Attack Flow
The issue can be reproduced through the following general flow:
User with widget permission
|
v
Create / modify widget
|
v
Submit malicious <script total>
|
v
Widgets/save
|
v
FUNC.recompile()
|
v
new Function('exports', meta.total)
|
v
JavaScript executes in Node.js
|
v
Access server-side functionality
|
v
OS command execution
The Widgets/save action accepts widget HTML and invokes FUNC.recompile() during the save operation.
The source indicates that the action is protected by the widgets,admin permission declaration, but the widget permission itself provides access to the vulnerable compilation functionality.
4. Why This Is Security Relevant
I understand that server-side widget scripting may be an intentional feature of Total.js CMS.
However, the security concern is the trust boundary around that feature.
A CMS with multiple users and permissions allows administrators to assign specific capabilities to users. A user who is only intended to manage widgets may not necessarily be expected to receive unrestricted operating system level code execution.
In the current implementation, widget scripting effectively provides that capability.
This means the security impact is significantly greater than normal widget customization.
The issue is particularly important in environments where:
- Multiple CMS users have different permission levels.
- Editors or content managers are allowed to manage widgets.
- The administration interface is accessible remotely.
- The CMS process has access to sensitive application files or environment variables.
- The CMS has access to internal services or databases.
The report's testing also identified that stored widgets are recompiled during application loading, which can make an injected payload persistent across application restarts.
5. Proof of Concept
I reproduced the issue against a fresh local installation of Total.js CMS.
The PoC creates a widget containing server-side JavaScript. The injected code uses Node.js functionality to execute whoami and write the result to a file.
The relevant proof of concept was:
<script total>
exports.id = "poc";
exports.name = "POC";
(function() {
try {
var req = process.mainModule.require;
var fs = req("fs");
var cp = req("child_process");
var out = cp.execSync("whoami").toString().trim();
fs.writeFileSync(
"poc-proof.txt",
"PWNED_BY_CODE_INJECTION\n" +
"pid=" + process.pid + "\n" +
"user=" + out + "\n" +
"cwd=" + process.cwd()
);
exports.name = "POC:" + out;
} catch (e) {
exports.name = "POC-ERR:" + (e.stack || e.message);
}
})();
</script>
<body>
<div>poc</div>
</body>
The important part is not the specific command used in this PoC. The important observation is that JavaScript supplied through the widget was executed by the server process.
The original testing confirmed that the widget name was modified using the output of the server-side whoami command and that a proof file was created on the server.
6. Reproduction Steps
Step 1: Obtain the source
git clone https://github.com/totaljs/cms.git
cd cms
npm install
Step 2: Start the application
The application becomes available at:
These were the commands used during the original reproduction.
Step 3: Authenticate
Open:
http://127.0.0.1:8010/admin/
Authenticate with an account that has permission to manage widgets.
Step 4: Create a widget
Navigate to:
Widgets -> Options -> Create
Create a widget containing the server-side payload shown in the PoC section.
Step 5: Submit the widget
Submit the widget.
During testing, the server processed the <script total> section immediately as part of the widget compilation process.
Step 6: Verify code execution
The injected code executes:
and writes the result to:
The widget name is also changed to include the command output.
This provides two independent indicators that the code executed on the server.
7. Observed Result
The reproduced result included:
login: 200 {"success":true}
save: 200 {"success":true,"value":"poc1786731269435"}
injected widget:
{"id":"poc1786731269435","name":"POC:desktop-iuu\msi", ...}
The resulting proof file contained information similar to:
PWNED_BY_CODE_INJECTION
pid=3556
user=desktop-iuu\msi
cwd=D:\cms-master
The username shown in the widget was produced by the server-side execution of whoami, confirming that the command was executed by the Node.js process rather than by the browser.
8. Manual Reproduction
The vulnerability can also be demonstrated without using an automated script.
- Open the CMS administration interface.
- Authenticate with an account authorized to manage widgets.
- Navigate to Widgets.
- Select Options.
- Select Create.
- Insert a widget containing a harmless server-side execution test.
- Submit the widget.
- Observe the resulting widget metadata.
- Verify the server-side artifact created by the test.
The original testing confirmed the behavior through the browser interface as well.
9. Impact
The vulnerability can have significant security impact because arbitrary JavaScript executes within the server process.
Depending on the privileges of the CMS process, an attacker may be able to:
Remote Code Execution
Execute operating system commands through Node.js modules such as child_process.
Sensitive Information Disclosure
Access information available to the Node.js process, including environment variables, application configuration, and files readable by the service account.
File System Modification
Create, modify, or delete files accessible to the CMS process.
Application Compromise
Modify application files or introduce persistent malicious functionality.
Persistence
A malicious widget is stored by the CMS and can be processed again when stored widgets are loaded or recompiled.
Denial of Service
Server-side code execution can potentially be abused to terminate or exhaust the Node.js process.
Privilege Boundary Bypass
If a non-administrative user is granted widget management privileges, that user may gain capabilities equivalent to arbitrary server-side code execution.
The observed impact and affected areas are consistent with the testing documented in the original report.
10. Affected Code Paths
The following components were identified during analysis:
| Component |
Location |
Relevant behavior |
| Widget compiler |
definitions/func.js |
Executes widget <script total> through new Function() |
| Widget creation/update |
plugins/widgets/schemas/widgets.js |
Accepts widget HTML and invokes the compiler |
| Layout import |
plugins/layouts/schemas/layouts.js |
Can provide widget content through imported layouts |
| Widget loading |
definitions/func.js |
Recompiles stored widgets during application startup |
| Administration login |
plugins/admin/login.html |
First-run credentials are rendered by the login page |
The specific source locations are documented in the original analysis.
11. Reproduction Environment
The issue was reproduced in the following environment:
| Component |
Version / Configuration |
| OS |
Windows 10/11 |
| Node.js |
v24.14.1 |
| Total.js framework |
total5 v0.0.18 |
| CMS |
v1.0.0 / current master |
| Port |
8010 |
| Access |
127.0.0.1 |
These values reflect the environment used for the reproduction and should not be interpreted as a statement that other environments are unaffected.
12. Security Assessment
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
An attacker needs an account capable of reaching the widget functionality. Depending on deployment configuration, the default first-run administrator credentials may also increase exposure.
User Interaction
None
Confidentiality Impact
High
Integrity Impact
High
Availability Impact
High
Suggested CVSS Score
9.2 Critical
CVSS v3.1:
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
The final severity should ultimately be determined by the Total.js maintainers based on the intended security model and deployment assumptions.
13. Additional Observation
During testing, I also observed that the first-run administration login page can expose the default administrator credentials.
The current implementation renders the login information directly on the login page. If an installation has not completed its initial credential change or hardening process, this may make administrative access easier to obtain.
I recommend treating this as a separate security issue from the code injection vulnerability, because the two problems have different root causes and remediation requirements.
14. Recommended Remediation
I recommend considering the following changes.
14.1 Restrict server-side code execution
If server-side widget scripting must remain available, restrict it to explicitly trusted administrators.
The normal widgets permission should not implicitly provide unrestricted server-side code execution.
14.2 Avoid new Function() for untrusted content
The strongest fix would be to avoid evaluating user-controlled widget content as JavaScript.
Widget metadata could instead be parsed using a restricted parser or represented as declarative configuration.
14.3 Implement proper sandboxing
If dynamic server-side scripting is an essential feature, execute it within a properly isolated environment.
The execution environment should not expose unrestricted access to:
process
require
child_process
fs
net
A controlled API should be provided instead.
14.4 Review widget import functionality
The layout import functionality should also be reviewed to ensure that imported widget data cannot bypass any security controls introduced for normal widget creation.
14.5 Review startup recompilation
Stored widgets should not automatically result in unrestricted server-side code execution during application startup.
Any compilation mechanism should operate within the same security restrictions as widget creation.
14.6 Remove plaintext first-run credentials
The initial administrator credentials should not be rendered on the login page.
A safer first-run flow would generate credentials securely and require the administrator to establish a new password before the administration interface becomes available.
14.7 Add security documentation
If server-side widget scripting is intentionally considered an administrator-only feature, this should be clearly documented as a privileged capability.
Deployment documentation should also recommend protecting the administration interface through appropriate network access controls when necessary.
The remediation recommendations above are based on the vulnerable code paths and behavior observed during testing.
15. Suggested Security Test After Fix
After implementing a fix, I recommend testing at least the following cases:
- A normal content user should not be able to execute arbitrary JavaScript on the server.
- A user with only the
widgets permission should not be able to access Node.js internals.
- Widget creation should not execute arbitrary statements supplied inside
<script total>.
- Widget imports should receive the same security restrictions as manually created widgets.
- Stored malicious widgets should not execute after an application restart.
- Access to
process, require, child_process, fs, and other sensitive Node.js functionality should be blocked where server-side scripting remains supported.
- First-run credentials should not be exposed through the public login page.
16. Disclosure
This report was prepared for responsible disclosure to the Total.js CMS maintainers.
The testing described here was performed against a local instance under the researcher's control.
The proof of concept uses a harmless command, whoami, and creates a local proof file to demonstrate server-side code execution. No destructive actions or third-party data access were required to establish the vulnerability.
17. Conclusion
The core issue is that Total.js CMS treats widget supplied JavaScript as executable server-side code.
Because the widget content reaches new Function() and executes inside the Node.js process, the feature can provide arbitrary server-side code execution to users who can reach the vulnerable widget functionality.
I recommend reviewing the intended trust model for server-side widgets and either restricting this functionality to explicitly trusted administrators or replacing the current execution model with a properly isolated and constrained mechanism.
I would be happy to provide additional reproduction details, testing evidence, or collaborate with the maintainers on validating a proposed fix.
Security Vulnerability Report
Server-Side Code Injection Leading to Remote Code Execution in Total.js CMS
Product: Total.js CMS
Affected version: v1.0.0, current master at the time of testing
Framework: total5 v0.0.18
Severity: Critical
Suggested CVSS: 9.2 (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)
Testing status: Successfully reproduced in a local test environment
1. Summary
I identified a server-side code injection issue in Total.js CMS that can lead to arbitrary command execution on the server.
The issue is related to the CMS widget functionality. Widgets can contain a
<script total>section, and the server processes this section using JavaScript'snew Function().The problem is that widget content can be supplied through the CMS interface and the resulting code is executed directly inside the Node.js process. As a result, a user who has permission to create or modify widgets can potentially execute arbitrary JavaScript with the privileges of the CMS process.
During testing, I was able to:
child_process.This means the issue can result in remote code execution and potentially complete compromise of the CMS host, depending on the privileges of the Node.js process.
The vulnerable code path and affected components are documented in the sections below.
2. Vulnerability Details
Vulnerability Type
CWE-94: Improper Control of Generation of Code (Code Injection)
The vulnerable functionality is located primarily in:
The widget compiler processes the
<script total>section and passes the resulting content tonew Function().The relevant behavior is:
meta.totalcontains the contents of the widget's<script total>section.This causes the supplied JavaScript to be compiled and executed inside the server-side Node.js process.
3. Attack Flow
The issue can be reproduced through the following general flow:
The
Widgets/saveaction accepts widget HTML and invokesFUNC.recompile()during the save operation.The source indicates that the action is protected by the
widgets,adminpermission declaration, but the widget permission itself provides access to the vulnerable compilation functionality.4. Why This Is Security Relevant
I understand that server-side widget scripting may be an intentional feature of Total.js CMS.
However, the security concern is the trust boundary around that feature.
A CMS with multiple users and permissions allows administrators to assign specific capabilities to users. A user who is only intended to manage widgets may not necessarily be expected to receive unrestricted operating system level code execution.
In the current implementation, widget scripting effectively provides that capability.
This means the security impact is significantly greater than normal widget customization.
The issue is particularly important in environments where:
The report's testing also identified that stored widgets are recompiled during application loading, which can make an injected payload persistent across application restarts.
5. Proof of Concept
I reproduced the issue against a fresh local installation of Total.js CMS.
The PoC creates a widget containing server-side JavaScript. The injected code uses Node.js functionality to execute
whoamiand write the result to a file.The relevant proof of concept was:
The important part is not the specific command used in this PoC. The important observation is that JavaScript supplied through the widget was executed by the server process.
The original testing confirmed that the widget name was modified using the output of the server-side
whoamicommand and that a proof file was created on the server.6. Reproduction Steps
Step 1: Obtain the source
git clone https://github.com/totaljs/cms.git cd cms npm installStep 2: Start the application
The application becomes available at:
These were the commands used during the original reproduction.
Step 3: Authenticate
Open:
Authenticate with an account that has permission to manage widgets.
Step 4: Create a widget
Navigate to:
Create a widget containing the server-side payload shown in the PoC section.
Step 5: Submit the widget
Submit the widget.
During testing, the server processed the
<script total>section immediately as part of the widget compilation process.Step 6: Verify code execution
The injected code executes:
and writes the result to:
The widget name is also changed to include the command output.
This provides two independent indicators that the code executed on the server.
7. Observed Result
The reproduced result included:
The resulting proof file contained information similar to:
The username shown in the widget was produced by the server-side execution of
whoami, confirming that the command was executed by the Node.js process rather than by the browser.8. Manual Reproduction
The vulnerability can also be demonstrated without using an automated script.
The original testing confirmed the behavior through the browser interface as well.
9. Impact
The vulnerability can have significant security impact because arbitrary JavaScript executes within the server process.
Depending on the privileges of the CMS process, an attacker may be able to:
Remote Code Execution
Execute operating system commands through Node.js modules such as
child_process.Sensitive Information Disclosure
Access information available to the Node.js process, including environment variables, application configuration, and files readable by the service account.
File System Modification
Create, modify, or delete files accessible to the CMS process.
Application Compromise
Modify application files or introduce persistent malicious functionality.
Persistence
A malicious widget is stored by the CMS and can be processed again when stored widgets are loaded or recompiled.
Denial of Service
Server-side code execution can potentially be abused to terminate or exhaust the Node.js process.
Privilege Boundary Bypass
If a non-administrative user is granted widget management privileges, that user may gain capabilities equivalent to arbitrary server-side code execution.
The observed impact and affected areas are consistent with the testing documented in the original report.
10. Affected Code Paths
The following components were identified during analysis:
definitions/func.js<script total>throughnew Function()plugins/widgets/schemas/widgets.jsplugins/layouts/schemas/layouts.jsdefinitions/func.jsplugins/admin/login.htmlThe specific source locations are documented in the original analysis.
11. Reproduction Environment
The issue was reproduced in the following environment:
These values reflect the environment used for the reproduction and should not be interpreted as a statement that other environments are unaffected.
12. Security Assessment
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
An attacker needs an account capable of reaching the widget functionality. Depending on deployment configuration, the default first-run administrator credentials may also increase exposure.
User Interaction
None
Confidentiality Impact
High
Integrity Impact
High
Availability Impact
High
Suggested CVSS Score
9.2 Critical
CVSS v3.1:
The final severity should ultimately be determined by the Total.js maintainers based on the intended security model and deployment assumptions.
13. Additional Observation
During testing, I also observed that the first-run administration login page can expose the default administrator credentials.
The current implementation renders the login information directly on the login page. If an installation has not completed its initial credential change or hardening process, this may make administrative access easier to obtain.
I recommend treating this as a separate security issue from the code injection vulnerability, because the two problems have different root causes and remediation requirements.
14. Recommended Remediation
I recommend considering the following changes.
14.1 Restrict server-side code execution
If server-side widget scripting must remain available, restrict it to explicitly trusted administrators.
The normal
widgetspermission should not implicitly provide unrestricted server-side code execution.14.2 Avoid
new Function()for untrusted contentThe strongest fix would be to avoid evaluating user-controlled widget content as JavaScript.
Widget metadata could instead be parsed using a restricted parser or represented as declarative configuration.
14.3 Implement proper sandboxing
If dynamic server-side scripting is an essential feature, execute it within a properly isolated environment.
The execution environment should not expose unrestricted access to:
A controlled API should be provided instead.
14.4 Review widget import functionality
The layout import functionality should also be reviewed to ensure that imported widget data cannot bypass any security controls introduced for normal widget creation.
14.5 Review startup recompilation
Stored widgets should not automatically result in unrestricted server-side code execution during application startup.
Any compilation mechanism should operate within the same security restrictions as widget creation.
14.6 Remove plaintext first-run credentials
The initial administrator credentials should not be rendered on the login page.
A safer first-run flow would generate credentials securely and require the administrator to establish a new password before the administration interface becomes available.
14.7 Add security documentation
If server-side widget scripting is intentionally considered an administrator-only feature, this should be clearly documented as a privileged capability.
Deployment documentation should also recommend protecting the administration interface through appropriate network access controls when necessary.
The remediation recommendations above are based on the vulnerable code paths and behavior observed during testing.
15. Suggested Security Test After Fix
After implementing a fix, I recommend testing at least the following cases:
widgetspermission should not be able to access Node.js internals.<script total>.process,require,child_process,fs, and other sensitive Node.js functionality should be blocked where server-side scripting remains supported.16. Disclosure
This report was prepared for responsible disclosure to the Total.js CMS maintainers.
The testing described here was performed against a local instance under the researcher's control.
The proof of concept uses a harmless command,
whoami, and creates a local proof file to demonstrate server-side code execution. No destructive actions or third-party data access were required to establish the vulnerability.17. Conclusion
The core issue is that Total.js CMS treats widget supplied JavaScript as executable server-side code.
Because the widget content reaches
new Function()and executes inside the Node.js process, the feature can provide arbitrary server-side code execution to users who can reach the vulnerable widget functionality.I recommend reviewing the intended trust model for server-side widgets and either restricting this functionality to explicitly trusted administrators or replacing the current execution model with a properly isolated and constrained mechanism.
I would be happy to provide additional reproduction details, testing evidence, or collaborate with the maintainers on validating a proposed fix.