From 42bdfb2cb4a82323498b5645c1946797546786fc Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Mon, 5 Oct 2026 18:18:24 +0200 Subject: [PATCH 1/2] checking MDI URL for trusted domains also from admin console UI --- .../META-INF/MANIFEST.MF | 1 + .../gwt/ui/client/SailingServiceWrite.java | 2 +- .../sailing/gwt/ui/client/StringMessages.java | 1 + .../gwt/ui/client/StringMessages.properties | 3 ++- .../ui/client/StringMessages_de.properties | 3 ++- .../MasterDataImportPanel.java | 26 ++++++++++++------- .../ui/server/SailingServiceWriteImpl.java | 8 +++++- 7 files changed, 31 insertions(+), 13 deletions(-) diff --git a/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF b/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF index 7838b88fb4c..c02d58e732d 100644 --- a/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF @@ -82,6 +82,7 @@ Import-Package: com.google.protobuf;version="4.28.3", com.sap.sailing.aiagent.interfaces, com.sap.sailing.domain.igtimiadapter.server.riot, com.sap.sse.aicore, + elemental2.dom, javax.servlet;version="3.1.0", javax.servlet.descriptor;version="3.1.0", javax.servlet.http;version="3.1.0", diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceWrite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceWrite.java index 4998c411708..fb6cc1e52f4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceWrite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceWrite.java @@ -280,7 +280,7 @@ public interface SailingServiceWrite extends FileStorageManagementGwtService, Sa UUID importMasterData(String host, UUID[] leaderboardGroupIds, boolean override, boolean compress, boolean exportWind, boolean exportDeviceConfigurations, String targetServerUsername, String targetServerPassword, - boolean exportTrackedRacesAndStartTracking) throws UnauthorizedException; + boolean exportTrackedRacesAndStartTracking) throws Exception; RegattaDTO createRegatta(String regattaName, String boatClassName, boolean canBoatsOfCompetitorsChangePerRace, CompetitorRegistrationType competitorRegistrationType, String registrationLinkSecret, Date startDate, diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index 2966b700c22..ef579865c9a 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -2614,4 +2614,5 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String noAutomatedTrackingTimes(String leaderboardName); String unknownError(String name); String pendingServerOperations(Integer numberOfPendingServerOperations); + String masterDataImportOnlyFromTrustedDomains(String trustedDomains, String host); } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index df4760d196d..111ab8a8dde 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -2649,4 +2649,5 @@ notRevokedTrackingTimesBecauseOfMissingStartOrFinishTime=Not revoked tracking ti noRegattaLeaderboard=Leaderboard {0} is not a regatta leaderboard. noAutomatedTrackingTimes=Leaderboard {0} has no automated tracking times. unknownError=Unknown error: {0} -pendingServerOperations=Data fetches pending: {0} \ No newline at end of file +pendingServerOperations=Data fetches pending: {0} +masterDataImportOnlyFromTrustedDomains=Master data import (MDI) allowed only from trusted domains ({0}). {1} is not trusted. \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index 26f6b6e6816..30c33d8c2fb 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -2643,4 +2643,5 @@ notRevokedTrackingTimesBecauseOfMissingStartOrFinishTime=Nicht widerrufene expli noRegattaLeaderboard=Rangliste {0} ist keine Regatta-Rangliste. noAutomatedTrackingTimes=Rangliste {0} nutzt keine automatisierten Tracking-Zeiten, auf die zurückgesetzt werden könnte. unknownError=Unbekannter Fehler: {0} -pendingServerOperations=Anhängige Ladeoperationen: {0} \ No newline at end of file +pendingServerOperations=Anhängige Ladeoperationen: {0} +masterDataImportOnlyFromTrustedDomains=Master data import (MDI) nur von vertrauenswürdigen Domains erlaubt ({0}). {1} ist nicht vertrauenswürdig. \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/masterdataimport/MasterDataImportPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/masterdataimport/MasterDataImportPanel.java index 14ef419956f..1551c9533df 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/masterdataimport/MasterDataImportPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/masterdataimport/MasterDataImportPanel.java @@ -32,6 +32,7 @@ import com.sap.sailing.domain.common.MasterDataImportObjectCreationCount; import com.sap.sailing.gwt.ui.adminconsole.places.AdminConsoleView.Presenter; import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sailing.landscape.common.SharedLandscapeConstants; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.filter.impl.KeywordMatcher; @@ -289,9 +290,15 @@ public class MasterDataImportPanel extends VerticalPanel { } protected void fireIdRequestsAndFillLists() { - String host = hostBox.getText(); - if (host != null && !host.isEmpty()) { - fireLgIdRequestAndFillList(host); + final String host = hostBox.getText(); + final elemental2.dom.URL url = new elemental2.dom.URL(host); + if (!SharedLandscapeConstants.isTrustedDomain(url.host)) { + Notification.notify(stringMessages.masterDataImportOnlyFromTrustedDomains( + SharedLandscapeConstants.TRUSTED_DOMAINS.toString(), url.host), NotificationType.ERROR); + } else { + if (host != null && !host.isEmpty()) { + fireLgIdRequestAndFillList(host); + } } } @@ -374,7 +381,6 @@ public class MasterDataImportPanel extends VerticalPanel { private void setFilterHandler(final TextBox filterBox) { filterBox.addKeyUpHandler(new KeyUpHandler() { - @Override public void onKeyUp(KeyUpEvent event) { filterLeaderboardGroupList(); @@ -398,11 +404,13 @@ public class MasterDataImportPanel extends VerticalPanel { return Collections.singleton(t); } }; - Map filteredMap = allLeaderboardGroupsNameAndIdsMap.entrySet().stream() - .filter(entry -> matcher.matches(filterTexts, entry.getValue())) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - fillLeaderboardGroupListBox(filteredMap); - changeButtonStateAccordingToApplicationState(); + if (allLeaderboardGroupsNameAndIdsMap != null) { + Map filteredMap = allLeaderboardGroupsNameAndIdsMap.entrySet().stream() + .filter(entry -> matcher.matches(filterTexts, entry.getValue())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + fillLeaderboardGroupListBox(filteredMap); + changeButtonStateAccordingToApplicationState(); + } } private void fillLeaderboardGroupListBox(Map leaderboardGroupsMap) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceWriteImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceWriteImpl.java index 212096e5920..b34ece3c0a2 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceWriteImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceWriteImpl.java @@ -300,6 +300,7 @@ import com.sap.sailing.gwt.ui.shared.courseCreation.CourseTemplateDTO; import com.sap.sailing.gwt.ui.shared.courseCreation.MarkPropertiesDTO; import com.sap.sailing.gwt.ui.shared.courseCreation.MarkRoleDTO; import com.sap.sailing.gwt.ui.shared.courseCreation.MarkTemplateDTO; +import com.sap.sailing.landscape.common.SharedLandscapeConstants; import com.sap.sailing.server.hierarchy.SailingHierarchyOwnershipUpdater; import com.sap.sailing.server.interfaces.RacingEventService; import com.sap.sailing.server.operationaltransformation.AbstractLeaderboardGroupOperation; @@ -405,6 +406,7 @@ import com.sap.sse.security.shared.impl.SecuredSecurityTypes.ServerActions; import com.sap.sse.security.shared.impl.UserGroup; import com.sap.sse.security.ui.server.SecurityDTOUtil; import com.sap.sse.security.ui.shared.SuccessInfo; +import com.sap.sse.security.util.RemoteServerUtil; import com.sap.sse.shared.media.ImageDescriptor; import com.sap.sse.shared.media.VideoDescriptor; import com.sap.sse.shared.util.impl.UUIDHelper; @@ -1792,7 +1794,7 @@ public class SailingServiceWriteImpl extends SailingServiceImpl implements Saili public UUID importMasterData(final String urlAsString, final UUID[] leaderboardGroupIds, final boolean override, final boolean compress, final boolean exportWind, final boolean exportDeviceConfigurations, String targetServerUsername, String targetServerPassword, - final boolean exportTrackedRacesAndStartTracking) { + final boolean exportTrackedRacesAndStartTracking) throws MalformedURLException { final UUID importOperationId = UUID.randomUUID(); getSecurityService().checkCurrentUserServerPermission(ServerActions.CAN_IMPORT_MASTERDATA); final String targetServerBearerToken; @@ -1801,6 +1803,10 @@ public class SailingServiceWriteImpl extends SailingServiceImpl implements Saili } else { targetServerBearerToken = null; } + final URL url = RemoteServerUtil.createBaseUrl(urlAsString); + if (!SharedLandscapeConstants.isTrustedDomain(url.getHost())) { + throw new IllegalArgumentException("not a trusted domain; valid domains are: "+SharedLandscapeConstants.TRUSTED_DOMAINS); + } // Create a progress indicator for as long as the server gets data from the other server. // As soon as the server starts the import operation, a progress object will be built on every server Runnable masterDataImportTask = new Runnable() { From 22e789d921fe3b925cb4baa884a1bf0f9bd69425 Mon Sep 17 00:00:00 2001 From: Axel Uhl Date: Mon, 5 Oct 2026 18:37:26 +0200 Subject: [PATCH 2/2] Bind httpprinter debug socket to loopback only Fixes CodeQL py/bind-socket-all-network-interfaces by binding the local debug HTTP printer to 127.0.0.1 instead of all interfaces (host = ''). The script is a small local debugging utility, so restricting it to loopback does not affect its intended use. Assisted-By: Claude Opus 4.8 --- configuration/httpprinter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration/httpprinter.py b/configuration/httpprinter.py index 858449fc8da..416245e7032 100644 --- a/configuration/httpprinter.py +++ b/configuration/httpprinter.py @@ -2,7 +2,7 @@ import socket -host = '' +host = '127.0.0.1' port = 50000 backlog = 5 size = 1024