From 3d9c4391d16d618ba80d4f08d129a2c650f920c9 Mon Sep 17 00:00:00 2001 From: Ruslan Musaev <43766501+HocKu7@users.noreply.github.com> Date: Fri, 12 Jun 2026 11:05:23 +0200 Subject: [PATCH] dbeaver/pro#9119 fix code vulnerability (#4380) Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com> --- .../server/jetty/RequestHostFilter.java | 6 ++-- .../service/fs/model/WebFSServlet.java | 29 +++++++++++++++++-- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/server/bundles/io.cloudbeaver.server.ce/src/io/cloudbeaver/server/jetty/RequestHostFilter.java b/server/bundles/io.cloudbeaver.server.ce/src/io/cloudbeaver/server/jetty/RequestHostFilter.java index dca9cec893..6ccf8ac305 100644 --- a/server/bundles/io.cloudbeaver.server.ce/src/io/cloudbeaver/server/jetty/RequestHostFilter.java +++ b/server/bundles/io.cloudbeaver.server.ce/src/io/cloudbeaver/server/jetty/RequestHostFilter.java @@ -156,10 +156,10 @@ public class RequestHostFilter implements Filter { if (!availableHosts.contains(requestHost)) { for (String errorPath : errorPaths) { if (httpRequest.getServletPath().contains(errorPath)) { + log.warn("Request host '" + requestHost + "' is not allowed. Available hosts: " + availableHosts); response.setStatus(HttpServletResponse.SC_FORBIDDEN); - response.getWriter().write( - "Request host '" + requestHost + "' is not allowed. Available hosts: " + availableHosts - ); + response.setContentType("text/plain;charset=UTF-8"); + response.getWriter().write("Request host is not allowed. Available hosts: " + availableHosts); return false; } } diff --git a/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/model/WebFSServlet.java b/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/model/WebFSServlet.java index a6f30953fb..11f21b3a06 100644 --- a/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/model/WebFSServlet.java +++ b/server/bundles/io.cloudbeaver.service.fs/src/io/cloudbeaver/service/fs/model/WebFSServlet.java @@ -1,6 +1,6 @@ /* * DBeaver - Universal Database Manager - * Copyright (C) 2010-2025 DBeaver Corp and others + * Copyright (C) 2010-2026 DBeaver Corp and others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.Part; import org.eclipse.jetty.ee11.servlet.ServletContextRequest; +import org.jkiss.code.NotNull; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.model.data.json.JSONUtils; @@ -41,6 +42,7 @@ import org.jkiss.utils.IOUtils; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; +import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.util.Map; @@ -102,9 +104,10 @@ public class WebFSServlet extends WebServiceServletBase { if (CommonUtils.isEmpty(fileName)) { continue; } + Path safeTarget = resolveSafeChild(path, fileName); try (InputStream is = part.getInputStream()) { - Files.copy(is, path.resolve(fileName)); - node.addChildResource(path.resolve(fileName)); + Files.copy(is, safeTarget); + node.addChildResource(safeTarget); } } } catch (Exception e) { @@ -113,6 +116,26 @@ public class WebFSServlet extends WebServiceServletBase { } } + @NotNull + private Path resolveSafeChild(@NotNull Path parent, @NotNull String submittedFileName) throws DBException { + Path candidate; + try { + candidate = Path.of(submittedFileName); + } catch (InvalidPathException e) { + throw new DBException("Invalid file name"); + } + Path baseName = candidate.getFileName(); + if (baseName == null || baseName.toString().isBlank()) { + throw new DBException("Invalid file name"); + } + Path normalizedParent = parent.normalize(); + Path resolved = normalizedParent.resolve(baseName.toString()).normalize(); + if (!resolved.startsWith(normalizedParent) || resolved.equals(normalizedParent)) { + throw new DBException("Invalid file name"); + } + return resolved; + } + @Override protected Map getVariables(HttpServletRequest request) { Map variables = super.getVariables(request);