OPENIDE #24 Restrict IDE access to untrusted sources

(cherry picked from commit 5bc56a6a642bb0baba1a0434c50f6b45cae64cb9)

(cherry picked from commit fdfad7b125)

(cherry picked from commit b869d83490)
(cherry picked from commit 3c336d8050)
(cherry picked from commit 364de1bcba)
This commit is contained in:
Nikita Iarychenko
2026-09-16 13:45:57 +04:00
parent 1c7e601c04
commit e3e0f1f6fe
15 changed files with 2507 additions and 73 deletions
+2384 -20
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -34,7 +34,7 @@
<component name="ProjectResources">
<default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" project-jdk-name="jbr-25" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_25">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="SuppressKotlinCodeStyleNotification">
@@ -7,7 +7,7 @@
<!-- endregion -->
<extensions defaultExtensionNs="com.intellij">
<applicationService serviceInterface="com.intellij.platform.ide.customization.ExternalProductResourceUrls"
serviceImplementation="com.intellij.idea.customization.base.IntelliJIdeaExternalResourceUrls"
serviceImplementation="com.intellij.idea.customization.base.OpenIdeExternalResourceUrls"
overrides="true"/>
<applicationService serviceInterface="com.intellij.openapi.ui.DialogBackgroundImageProvider"
@@ -0,0 +1,31 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.idea.customization.base
import com.intellij.openapi.util.BuildNumber
import com.intellij.platform.ide.customization.ExternalProductResourceUrls
import com.intellij.util.Url
import com.intellij.util.Urls
// TODO [OpenIDE]: replaces urls
class OpenIdeExternalResourceUrls : ExternalProductResourceUrls {
override val helpPageUrl: ((topicId: String) -> Url)? = null
override val gettingStartedPageUrl = null
override val youTubeChannelUrl = null
override val updateMetadataUrl = Urls.newFromEncoded("https://www.openide.com")
override fun computePatchUrl(from: BuildNumber, to: BuildNumber): Url = Urls.newFromEncoded("https://www.openide.com")
override val bugReportUrl: ((String) -> Url)? = null
override val technicalSupportUrl: ((description: String) -> Url) ? = null
override val feedbackReporter = null
override val downloadPageUrl = null
override val whatIsNewPageUrl = null
}
@@ -39,7 +39,7 @@ import java.util.stream.Collectors;
@InternalIgnoreDependencyViolation
public final class IntellijTestDiscoveryProducer implements TestDiscoveryProducer {
private static final String INTELLIJ_TEST_DISCOVERY_HOST = "https://intellij-test-discovery.labs.intellij.net";
private static final String INTELLIJ_TEST_DISCOVERY_HOST = "";
private static final NotNullLazyValue<ObjectReader> JSON_READER = NotNullLazyValue.createValue(() -> new ObjectMapper().readerFor(TestsSearchResult.class));
@@ -116,18 +116,17 @@ fun submitFeedback(feedbackData: FeedbackRequestDataHolder,
onDone: () -> Unit,
onError: () -> Unit,
feedbackRequestType: FeedbackRequestType = FeedbackRequestType.TEST_REQUEST) {
ApplicationManager.getApplication().executeOnPooledThread {
val urlOverride = System.getProperty(FEEDBACK_URL_OVERRIDE_PROPERTY)
val feedbackUrl = when (feedbackRequestType) {
FeedbackRequestType.NO_REQUEST -> return@executeOnPooledThread
FeedbackRequestType.TEST_REQUEST -> urlOverride ?: TEST_FEEDBACK_URL
FeedbackRequestType.PRODUCTION_REQUEST -> urlOverride ?: PRODUCTION_FEEDBACK_URL
}
val regionalFeedbackUrl = RegionUrlMapper.tryMapUrlBlocking(feedbackUrl)
LOG.info("Feedback sent to $regionalFeedbackUrl")
sendFeedback(regionalFeedbackUrl, feedbackData, onDone, onError)
}
//ApplicationManager.getApplication().executeOnPooledThread {
// val feedbackUrl = when (feedbackRequestType) {
// FeedbackRequestType.NO_REQUEST -> return@executeOnPooledThread
// FeedbackRequestType.TEST_REQUEST -> TEST_FEEDBACK_URL
// FeedbackRequestType.PRODUCTION_REQUEST -> PRODUCTION_FEEDBACK_URL
// }
//
// val regionalFeedbackUrl = RegionUrlMapper.tryMapUrlBlocking(feedbackUrl)
// LOG.info("Feedback sent to $regionalFeedbackUrl")
// sendFeedback(regionalFeedbackUrl, feedbackData, onDone, onError)
//}
}
private fun sendFeedback(feedbackUrl: String,
@@ -3,8 +3,8 @@ package com.intellij.facet.frameworks;
public final class LibrariesDownloadConnectionService extends SettingsConnectionService {
private static final String SETTINGS_URL = "https://www.jetbrains.com/idea/download-assistant.xml";
private static final String SERVICE_URL = "https://frameworks.jetbrains.com";
private static final String SETTINGS_URL = null;
private static final String SERVICE_URL = null;
private static final LibrariesDownloadConnectionService ourInstance = new LibrariesDownloadConnectionService();
@@ -0,0 +1,34 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.util.io
import java.net.URL
import java.net.URLConnection
object WhiteListUrls {
private val urls = listOf(
"https://github.com",
"https://search.maven.org",
"https://repo.jfrog.org",
"https://oss.sonatype.org",
"https://repository.jboss.org",
"https://repo.maven.apache.org",
"https://plugins.gradle.org/plugin/org.jetbrains.intellij",
"https://api.github.com/repos",
"https://pypi.python.org",
"http://localhost",
"https://services.gradle.org",
"https://plugins.jetbrains.com", // TODO [OpenIDE]: replace url
"https://downloads.marketplace.jetbrains.com/files", // TODO [OpenIDE]: replace url
"https://repo1.maven.org/maven2/net/sourceforge/plantuml/plantuml/1.2023.10/plantuml-1.2023.10.jar",
)
@JvmStatic
fun isAvailableUrl(url: String): Boolean {
return urls.any { url.startsWith(it, true) }
}
}
class StubUrlConnection(url: URL): URLConnection(url) {
override fun connect() {
}
}
@@ -531,7 +531,7 @@ class JdkListDownloader : JdkListDownloaderBase() {
return registry
}
}
return "https://download.jetbrains.com/jdk/feed/v1/jdks.json.xz"
return "" // TODO [OpenIDE]: replace url
}
}
@@ -40,7 +40,8 @@ private class RuntimeChooserJbrListDownloader : JdkListDownloaderBase() {
val majorVersion = runCatching { Registry.get("runtime.chooser.pretend.major").asInteger() }.getOrNull()
?: ApplicationInfo.getInstance().build.components.firstOrNull()
return "https://download.jetbrains.com/jdk/feed/v1/jbr-choose-runtime-${majorVersion}.json.xz"
return ""; // TODO [OpenIDE]: replace url
//return "https://download.jetbrains.com/jdk/feed/v1/jbr-choose-runtime-${majorVersion}.json.xz"
}
}
@@ -11,9 +11,13 @@ import com.intellij.util.SmartList;
import com.intellij.util.SystemProperties;
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread;
import com.intellij.util.concurrency.annotations.RequiresReadLockAbsence;
import com.intellij.util.io.HttpRequests;
import com.intellij.util.net.PlatformHttpClient;
import kotlinx.coroutines.Dispatchers;
import kotlinx.coroutines.ExecutorsKt;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.io.JsonReaderEx;
import org.jetbrains.io.JsonUtil;
@@ -159,8 +163,7 @@ public final class RegionUrlMapper {
}
private static @NotNull String getConfigUrl(@NotNull Region reg) {
String overridden = OVERRIDE_CONFIG_URL_TABLE.get(reg);
return overridden != null ? overridden : CONFIG_URL_TABLE.getOrDefault(reg, CONFIG_URL_DEFAULT);
return "";
}
/*
@@ -955,7 +955,8 @@
restartRequired="true"
description="Amount of time in minutes to check new Git version after IDE inactivity.\n
-1 to disable check."/>
<settingsEntryPointActionProvider os="windows" implementation="git4idea.config.GitVersionUpdateSettingsEntryProvider"/>
<!--<postStartupActivity os="windows" implementation="git4idea.config.GitNewVersionChecker$Starter"/>-->
<!--<settingsEntryPointActionProvider os="windows" implementation="git4idea.config.GitVersionUpdateSettingsEntryProvider"/>-->
<history.activityPresentationProvider implementation="git4idea.GitActivityPresentationProvider"/>
@@ -214,7 +214,7 @@
description="Enable the phased Gradle sync execution"/>
<registryKey key="gradle.phased.sync.bridge.disabled" defaultValue="false"
description="Disable bridges for the phased Gradle sync execution"/>
<registryKey defaultValue="https://download.jetbrains.com/resources/intellij/plugins/gradle/v1/compatibility.json"
<registryKey defaultValue=""
description="URL to get updates for gradle/jvm compatibility matrix" key="gradle.compatibility.config.url"/>
<registryKey defaultValue="86400"
description="Time to check in seconds for gradle compatibility update. Set to 0 to disable updates"
@@ -113,35 +113,36 @@ public final class SceneBuilderEditor extends UserDataHolderBase implements File
e instanceof NoClassDefFoundError &&
!SceneBuilderUtil.getSceneBuilder11Path().toFile().isFile()) {
myErrorNotification.setText(JavaFXBundle.message("javafx.scene.builder.editor.failed.to.open.file.error"));
myErrorNotification.createActionLabel(
JavaFXBundle.message("javafx.scene.builder.editor.download.scene.builder.kit"),
() -> {
DownloadableFileService service = DownloadableFileService.getInstance();
var description = service.createFileDescription("https://cache-redirector.jetbrains.com/" +
"intellij-dependencies/org/jetbrains/intellij/deps/scenebuilderkit/" +
SceneBuilderUtil.SCENE_BUILDER_VERSION + "/" + SceneBuilderUtil.SCENE_BUILDER_KIT_FULL_NAME, SceneBuilderUtil.SCENE_BUILDER_KIT_FULL_NAME);
FileDownloader downloader = service.createDownloader(Collections.singletonList(description), "Scene Builder Kit");
try {
Path tempDir = Files.createTempDirectory("");
final var list = downloader.downloadWithProgress(tempDir.toString(), myProject, myErrorPanel);
if (list == null || list.isEmpty()) {
myErrorNotification.clear();
myErrorNotification.setText(JavaFXBundle.message("javafx.scene.builder.editor.failed.to.download.kit.error"));
return;
}
FileUtil.copy(VfsUtilCore.virtualToIoFile(list.get(0).first), SceneBuilderUtil.getSceneBuilder11Path().toFile());
FileUtil.delete(tempDir.toFile());
SceneBuilderUtil.updateLoader();
updateState();
}
catch (IOException e2) {
LOG.warn("Can't download SceneBuilderKit", e2);
}
}
);
// TODO [OpenIDE]: https://git.haulmont.com/platform/open-ide/idea/-/issues/29
//myErrorNotification.createActionLabel(
// JavaFXBundle.message("javafx.scene.builder.editor.download.scene.builder.kit"),
// () -> {
// DownloadableFileService service = DownloadableFileService.getInstance();
// var description = service.createFileDescription("https://cache-redirector.jetbrains.com/" +
// "intellij-dependencies/org/jetbrains/intellij/deps/scenebuilderkit/" +
// SceneBuilderUtil.SCENE_BUILDER_VERSION + "/" + SceneBuilderUtil.SCENE_BUILDER_KIT_FULL_NAME, SceneBuilderUtil.SCENE_BUILDER_KIT_FULL_NAME);
// FileDownloader downloader = service.createDownloader(Collections.singletonList(description), "Scene Builder Kit");
// try {
// Path tempDir = Files.createTempDirectory("");
//
// final var list = downloader.downloadWithProgress(tempDir.toString(), myProject, myErrorPanel);
// if (list == null || list.isEmpty()) {
// myErrorNotification.clear();
// myErrorNotification.setText(JavaFXBundle.message("javafx.scene.builder.editor.failed.to.download.kit.error"));
// return;
// }
//
// FileUtil.copy(VfsUtilCore.virtualToIoFile(list.get(0).first), SceneBuilderUtil.getSceneBuilder11Path().toFile());
// FileUtil.delete(tempDir.toFile());
//
// SceneBuilderUtil.updateLoader();
// updateState();
// }
// catch (IOException e2) {
// LOG.warn("Can't download SceneBuilderKit", e2);
// }
// }
//);
myLayout.show(myPanel, ERROR_CARD);
return;
}
@@ -377,7 +377,7 @@
defaultValue="600000"
description="Interval in milliseconds defining how often Markdown plugin caches (e.g. PlantUML diagrams) should be cleared"/>
<registryKey key="markdown.plantuml.download.link"
defaultValue="https://download.jetbrains.com/grazie/markdown/extensions/plantuml/plantuml-1.2023.10-15.jar"
defaultValue="https://repo1.maven.org/maven2/net/sourceforge/plantuml/plantuml/1.2023.10/plantuml-1.2023.10.jar"
description="Link which Markdown plugin will use to download PlantUML JAR"/>
<registryKey key="markdown.open.link.in.external.browser"
defaultValue="true"