VYPR
Moderate severityNVD Advisory· Published Aug 4, 2023· Updated Oct 17, 2024

CVE-2022-41401

CVE-2022-41401

Description

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.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

OpenRefine up to version 3.5.2 is vulnerable to Server-Side Request Forgery (SSRF), enabling unauthorized access to internal resources and sensitive file disclosure.

Vulnerability

Overview

CVE-2022-41401 is a Server-Side Request Forgery (SSRF) vulnerability in OpenRefine, an open-source data cleaning tool. Versions 3.5.2 and earlier are affected. The root cause lies in the ImportingUtilities.java class, which handles project creation from URLs. Prior to the fix, the code did not validate or restrict the URL protocol when importing data via a URL, allowing the use of protocols such as file:// [2][3]. This oversight permits an attacker to craft a request that makes the server send requests to internal resources or local files, bypassing intended access controls.

Attack

Vector and Exploitation

The vulnerability can be exploited by an unauthenticated attacker who can access the OpenRefine web interface. During project creation, the application accepts a URL to import data from. By supplying a URL with the file:// protocol (e.g., file:///etc/passwd), an attacker can force the server to read local files [3]. No authentication is required, as the import functionality is available to any user who can reach the OpenRefine instance [1]. The attack surface is the import feature, which by default listens on 127.0.0.1:3333, but if exposed to a network, an attacker can trigger SSRF remotely.

Impact

Successful exploitation allows an attacker to perform SSRF, leading to unauthorized access to internal systems and sensitive file disclosure. The attacker could read arbitrary files from the server (e.g., configuration files, credentials) or probe internal network services that are otherwise inaccessible from outside [1]. This can compromise the confidentiality of the host system and potentially lateral movement within the internal network.

Mitigation

The vulnerability was patched in commit 8cb2fec by adding an allowlist of permitted protocols (http, https, ftp, sftp) and throwing an IOException for unsupported protocols [3]. Users should upgrade to OpenRefine version 3.5.3 or later to remediate the issue [1]. As of the publication date, no workaround is documented, but restricting network access to the OpenRefine interface can reduce risk.

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.openrefine:mainMaven
< 3.6.03.6.0

Affected products

2

Patches

1
8cb2fec45dd9

Restrict protocols available at project creation. Closes #4918. (#4919)

https://github.com/OpenRefine/OpenRefineAntonin DelpeuchJun 6, 2022via ghsa
2 files changed · +56 0
  • main/src/com/google/refine/importing/ImportingUtilities.java+7 0 modified
    @@ -48,6 +48,7 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     import java.nio.file.Path;
     import java.text.NumberFormat;
     import java.util.ArrayList;
    +import java.util.Arrays;
     import java.util.Collections;
     import java.util.Comparator;
     import java.util.HashMap;
    @@ -96,6 +97,8 @@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     public class ImportingUtilities {
         final static protected Logger logger = LoggerFactory.getLogger("importing-utilities");
         
    +    final public static List<String> allowedProtocols = Arrays.asList("http", "https", "ftp", "sftp");
    +    
         static public interface Progress {
             public void setProgress(String message, int percent);
             public boolean isCanceled();
    @@ -262,6 +265,10 @@ public void update(long bytesRead, long contentLength, int itemCount) {
                         String urlString = Streams.asString(stream);
                         URL url = new URL(urlString);
                         
    +                    if (!allowedProtocols.contains(url.getProtocol().toLowerCase())) {
    +                        throw new IOException("Unsupported protocol: " + url.getProtocol());
    +                    }
    +                    
                         ObjectNode fileRecord = ParsingUtilities.mapper.createObjectNode();
                         JSONUtilities.safePut(fileRecord, "origin", "download");
                         JSONUtilities.safePut(fileRecord, "url", urlString);
    
  • main/tests/server/src/com/google/refine/importing/ImportingUtilitiesTests.java+49 0 modified
    @@ -170,6 +170,55 @@ public boolean isCanceled() {
             }
         }
     
    +    @Test
    +    public void urlImportingInvalidProtocol() throws IOException {
    +
    +        String url = "file:///etc/passwd";
    +        String message = "Unsupported protocol: file";
    +
    +        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    +        StringBody stringBody = new StringBody(url.toString(), ContentType.MULTIPART_FORM_DATA);
    +        builder = builder.addPart("download", stringBody);
    +        HttpEntity entity = builder.build();
    +
    +        ByteArrayOutputStream os = new ByteArrayOutputStream();
    +        entity.writeTo(os);
    +        ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
    +
    +        HttpServletRequest req = mock(HttpServletRequest.class);
    +        when(req.getContentType()).thenReturn(entity.getContentType());
    +        when(req.getParameter("download")).thenReturn(url.toString());
    +        when(req.getMethod()).thenReturn("POST");
    +        when(req.getContentLength()).thenReturn((int) entity.getContentLength());
    +        when(req.getInputStream()).thenReturn(new MockServletInputStream(is));
    +
    +        ImportingJob job = ImportingManager.createJob();
    +        Properties parameters = ParsingUtilities.parseUrlParameters(req);
    +        ObjectNode retrievalRecord = ParsingUtilities.mapper.createObjectNode();
    +        ObjectNode progress = ParsingUtilities.mapper.createObjectNode();
    +        try {
    +            ImportingUtilities.retrieveContentFromPostRequest(req, parameters, job.getRawDataDir(), retrievalRecord,
    +                    new ImportingUtilities.Progress() {
    +
    +                        @Override
    +                        public void setProgress(String message, int percent) {
    +                            if (message != null) {
    +                                JSONUtilities.safePut(progress, "message", message);
    +                            }
    +                            JSONUtilities.safePut(progress, "percent", percent);
    +                        }
    +
    +                        @Override
    +                        public boolean isCanceled() {
    +                            return job.canceled;
    +                        }
    +                    });
    +            fail("No Exception was thrown");
    +        } catch (Exception exception) {
    +            assertEquals(exception.getMessage(), message);
    +        }
    +    }
    +
         public static class MockServletInputStream extends ServletInputStream {
     
             private final InputStream delegate;
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.