CVE-2026-39842
OpenRemote is Vulnerable to Expression Injection
OpenRemote is an open-source IoT platform. Versions 1.21.0 and below contain two interrelated expression injection vulnerabilities in the rules engine that allow arbitrary code execution on the server. The JavaScript rules engine executes user-supplied scripts via Nashorn's ScriptEngine.eval() without sandboxing, class filtering, or access restrictions, and the authorization check in RulesResourceImpl only restricts Groovy rules to superusers while leaving JavaScript rules unrestricted for any user with the write:rules role. Additionally, the Groovy rules engine has a GroovyDenyAllFilter security filter that is defined but never registered, as the registration code is commented out, rendering the SandboxTransformer ineffective for superuser-created Groovy rules. A non-superuser attacker with the write:rules role can create JavaScript rulesets that execute with full JVM access, enabling remote code execution as root, arbitrary file read, environment variable theft including database credentials, and complete multi-tenant isolation bypass to access data across all realms. This issue has been fixed in version 1.22.0.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
10.0
OpenRemote is Vulnerable to Expression Injection
OpenRemote is an open-source IoT platform. Versions 1.21.0 and below contain two interrelated expression injection vulnerabilities in the rules engine that allow arbitrary code execution on the server. The JavaScript rules engine executes user-supplied scripts via Nashorn's ScriptEngine.eval() without sandboxing, class filtering, or access restrictions, and the authorization check in RulesResourceImpl only restricts Groovy rules to superusers while leaving JavaScript rules unrestricted for any user with the write:rules role. Additionally, the Groovy rules engine has a GroovyDenyAllFilter security filter that is defined but never registered, as the registration code is commented out, rendering the SandboxTransformer ineffective for superuser-created Groovy rules. A non-superuser attacker with the write:rules role can create JavaScript rulesets that execute with full JVM access, enabling remote code execution as root, arbitrary file read, environment variable theft including database credentials, and complete multi-tenant isolation bypass to access data across all realms. This issue has been fixed in version 1.22.0.
- Record
CVE-2026-39842- CVSS 3.1
- 10.0 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-94, CWE-917
- Updated
- 2026-11-02
EUVDEUVD-2026-22806
10.0
OpenRemote is an open-source IoT platform. Versions 1.21.0 and below contain two interrelated expression injection vulnerabilities in the rules engine that allow arbitrary code execution on the server. The JavaScript rules engine executes user-supplied scripts via Nashorn's ScriptEngine.eval() without sandboxing, class filtering, or access restrictions, and the authorization check in RulesResourceImpl only restricts Groovy rules to superusers while leaving JavaScript rules unrestricted for any user with the write:rules role. Additionally, the Groovy rules engine has a GroovyDenyAllFilter security filter that is defined but never registered, as the registration code is commented out, rendering the SandboxTransformer ineffective for superuser-created Groovy rules. A non-superuser attacker with the write:rules role can create JavaScript rulesets that execute with full JVM access, enabling remote code execution as root, arbitrary file read, environment variable theft including database credentials, and complete multi-tenant isolation bypass to access data across all realms. This issue has been fixed in version 1.22.0.
- Record
EUVD-2026-22806- CVSS 3.1
- 10.0 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-7mqr-33rv-p3mp
9.9
Expression Injection in OpenRemote
Summary
The OpenRemote IoT platform's rules engine contains two interrelated critical expression injection vulnerabilities that allow an attacker to execute arbitrary code on the server, ultimately achieving full server compromise.
- Unsandboxed Nashorn JavaScript Engine: JavaScript rules are executed via Nashorn's ScriptEngine.eval() with user-supplied script content and no sandboxing, class filtering, or access restrictions. Critically, any non-superuser with the write:rules role can create JavaScript rulesets.
- Inactive Groovy Sandbox: The Groovy rules engine has a GroovyDenyAllFilter security filter that is defined but never registered (the registration code is commented out), rendering the SandboxTransformer ineffective. While Groovy rules are restricted to superusers, the absence of sandboxing violates the principle of defense in depth.
Details
Attacker-Controllable Source-to-Sink Paths
There are two non-superuser and two superuser exploitable attack paths from the REST API entry point to final code execution. (JavaScript × Realm/Asset + Groovy × Realm/Asset) The most critical path is detailed below.
Path 1: Unsandboxed JavaScript Expression Injection via Realm Ruleset (Non-Superuser Exploitable)
RulesetDeployment.java L368:
Object result = scriptEngine.eval(script, engineScope);
The Nashorn JavaScript engine is initialized without a ClassFilter, allowing Java.type() to access any JVM class — including java.lang.Runtime (for RCE), java.io.FileReader (for file read), and java.lang.System (for env theft).
RulesResourceImpl.java L309 (and L331, L359, L412, L437):
// VULNERABLE: only restricts Groovy, JavaScript completely unrestricted
if (ruleset.getLang() == Ruleset.Lang.GROOVY && !isSuperUser()) {
throw new WebApplicationException(Response.Status.FORBIDDEN);
}
Non-superuser attackers with only the write:rules role can submit arbitrary JavaScript rules that execute with full JVM access.
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│ SOURCE → SINK Complete Data Flow │
├─────────────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ① HTTP REQUEST (Source / Entry Point) │
│ POST /api/{realm}/rules/realm │
│ Content-Type: application/json │
│ Body: { "type":"realm", "lang":"JAVASCRIPT", │
│ "rules":"<MALICIOUS_SCRIPT>", ... } ← Attacker-controlled malicious script │
│ │
│ ↓ JAX-RS Deserialization │
│ │
│ ② RulesResource.createRealmRuleset() │
│ model/.../rules/RulesResource.java:153-158 │
│ @POST @Path("realm") @RolesAllowed("write:rules") │
│ Interface: long createRealmRuleset(RequestParams, @Valid RealmRuleset ruleset) │
│ JSON body → RealmRuleset object (Jackson deserialization) …
- Record
GHSA-7mqr-33rv-p3mp- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-94, CWE-917
- Updated
- 2026-11-02
NVD
9.9
OpenRemote is an open-source IoT platform. Versions 1.21.0 and below contain two interrelated expression injection vulnerabilities in the rules engine that allow arbitrary code execution on the server. The JavaScript rules engine executes user-supplied scripts via Nashorn's ScriptEngine.eval() without sandboxing, class filtering, or access restrictions, and the authorization check in RulesResourceImpl only restricts Groovy rules to superusers while leaving JavaScript rules unrestricted for any user with the write:rules role. Additionally, the Groovy rules engine has a GroovyDenyAllFilter security filter that is defined but never registered, as the registration code is commented out, rendering the SandboxTransformer ineffective for superuser-created Groovy rules. A non-superuser attacker with the write:rules role can create JavaScript rulesets that execute with full JVM access, enabling remote code execution as root, arbitrary file read, environment variable theft including database credentials, and complete multi-tenant isolation bypass to access data across all realms. This issue has been fixed in version 1.22.0.
- Record
CVE-2026-39842- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-94, CWE-917
- Updated
- 2026-11-02
OSV
9.9
OpenRemote is Vulnerable to Expression Injection
OpenRemote is an open-source IoT platform. Versions 1.21.0 and below contain two interrelated expression injection vulnerabilities in the rules engine that allow arbitrary code execution on the server. The JavaScript rules engine executes user-supplied scripts via Nashorn's ScriptEngine.eval() without sandboxing, class filtering, or access restrictions, and the authorization check in RulesResourceImpl only restricts Groovy rules to superusers while leaving JavaScript rules unrestricted for any user with the write:rules role. Additionally, the Groovy rules engine has a GroovyDenyAllFilter security filter that is defined but never registered, as the registration code is commented out, rendering the SandboxTransformer ineffective for superuser-created Groovy rules. A non-superuser attacker with the write:rules role can create JavaScript rulesets that execute with full JVM access, enabling remote code execution as root, arbitrary file read, environment variable theft including database credentials, and complete multi-tenant isolation bypass to access data across all realms. This issue has been fixed in version 1.22.0.
- Record
CVE-2026-39842- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-917, CWE-94
- Updated
- 2026-11-02
OSVGHSA-7mqr-33rv-p3mp
9.9
Expression Injection in OpenRemote
Summary
The OpenRemote IoT platform's rules engine contains two interrelated critical expression injection vulnerabilities that allow an attacker to execute arbitrary code on the server, ultimately achieving full server compromise.
- Unsandboxed Nashorn JavaScript Engine: JavaScript rules are executed via Nashorn's ScriptEngine.eval() with user-supplied script content and no sandboxing, class filtering, or access restrictions. Critically, any non-superuser with the write:rules role can create JavaScript rulesets.
- Inactive Groovy Sandbox: The Groovy rules engine has a GroovyDenyAllFilter security filter that is defined but never registered (the registration code is commented out), rendering the SandboxTransformer ineffective. While Groovy rules are restricted to superusers, the absence of sandboxing violates the principle of defense in depth.
Details
Attacker-Controllable Source-to-Sink Paths
There are two non-superuser and two superuser exploitable attack paths from the REST API entry point to final code execution. (JavaScript × Realm/Asset + Groovy × Realm/Asset) The most critical path is detailed below.
Path 1: Unsandboxed JavaScript Expression Injection via Realm Ruleset (Non-Superuser Exploitable)
RulesetDeployment.java L368:
Object result = scriptEngine.eval(script, engineScope);
The Nashorn JavaScript engine is initialized without a ClassFilter, allowing Java.type() to access any JVM class — including java.lang.Runtime (for RCE), java.io.FileReader (for file read), and java.lang.System (for env theft).
RulesResourceImpl.java L309 (and L331, L359, L412, L437):
// VULNERABLE: only restricts Groovy, JavaScript completely unrestricted
if (ruleset.getLang() == Ruleset.Lang.GROOVY && !isSuperUser()) {
throw new WebApplicationException(Response.Status.FORBIDDEN);
}
Non-superuser attackers with only the write:rules role can submit arbitrary JavaScript rules that execute with full JVM access.
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│ SOURCE → SINK Complete Data Flow │
├─────────────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ① HTTP REQUEST (Source / Entry Point) │
│ POST /api/{realm}/rules/realm │
│ Content-Type: application/json │
│ Body: { "type":"realm", "lang":"JAVASCRIPT", │
│ "rules":"<MALICIOUS_SCRIPT>", ... } ← Attacker-controlled malicious script │
│ │
│ ↓ JAX-RS Deserialization │
│ │
│ ② RulesResource.createRealmRuleset() │
│ model/.../rules/RulesResource.java:153-158 │
│ @POST @Path("realm") @RolesAllowed("write:rules") │
│ Interface: long createRealmRuleset(RequestParams, @Valid RealmRuleset ruleset) │
│ JSON body → RealmRuleset object (Jackson deserialization) …
- Record
GHSA-7mqr-33rv-p3mp- CVSS 3.1
- 9.9 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-917, CWE-94
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
io.openremote:openremote-managerMaven |
through 1.21.0 | 1.22.0 |
io.openremote:openremote-managerMaven |
before 1.22.0, plus listed versions 1.10.01.11.01.11.11.11.21.11.3 Show 42 moreShow less1.12.01.12.11.12.31.13.01.13.11.14.01.15.01.15.11.15.21.16.11.17.01.17.11.17.21.17.31.18.01.19.01.2.01.2.11.2.21.2.31.2.41.20.01.20.11.20.21.21.01.3.01.3.11.3.21.3.31.3.41.3.51.4.01.5.01.6.01.6.21.6.31.6.41.6.51.7.01.8.01.8.11.9.0 |
1.22.0 |
Public exploits
Links only. Every CVE stores no exploit code.
| Source | Link | Date |
|---|---|---|
| PoC in GitHub | keraattin/CVE-2026-39842 | 2026-04-17 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV, PoC in GitHub |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-39842 is a critical vulnerability (CVSS 10.0) in Openremote, published April 14, 2026. Public exploit code exists. EPSS puts the chance of exploitation in the next 30 days at 0.92%, the 60th percentile. Fixed in io.openremote:openremote-manager 1.22.0.
References
github.com/openremote/openremote/security/advisories/GHSA-7mqr-33rv-p3mp
github.com/openremote/openremote/releases/tag/1.22.0
nvd.nist.gov/vuln/detail/CVE-2026-39842
github.com/advisories/GHSA-7mqr-33rv-p3mp
github.com/CVEProject/cvelistV5/tree/main/cves/2026/39xxx/CVE-2026-39842.json
github.com/openremote/openremote
Left out here: the rest of 2 source descriptions. The JSON record has them.