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)
This commit is contained in:
Nikita Iarychenko
2026-03-10 17:42:05 +04:00
parent 64cde49d94
commit 364de1bcba
14 changed files with 125 additions and 54 deletions
@@ -2,7 +2,7 @@
<idea-plugin>
<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"/>
</extensions>
</idea-plugin>
@@ -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));
@@ -961,7 +961,7 @@
<modcompletion.completionItemProvider language="JAVA" implementationClass="com.intellij.java.completion.modcommand.ReferenceItemProvider"/>
<modcompletion.completionItemProvider language="JAVA" implementationClass="com.intellij.java.completion.modcommand.NonImportedClassProvider"/>
<modcompletion.completionItemProvider language="JAVA" implementationClass="com.intellij.java.completion.modcommand.InnerScopeVariableItemProvider"/>
<completion.skip implementation="com.intellij.codeInsight.completion.AbstractExpectedTypeSkipper" id="skipAbstract"/>
<completion.skip implementation="com.intellij.codeInsight.completion.DeprecatedSkipper" id="skipDeprecated"/>
<statistician key="completion" implementationClass="com.intellij.codeInsight.completion.JavaCompletionStatistician"/>
@@ -1062,8 +1062,8 @@
nameKey="settings.inlay.java.external.annotations"
descriptionKey="inlay.annotation.hints.external.annotations" />
</codeInsight.declarativeInlayProvider>
<codeInsight.declarativeInlayProviderCustomSettingsProvider
language="JAVA" providerId="java.annotation.hints"
<codeInsight.declarativeInlayProviderCustomSettingsProvider
language="JAVA" providerId="java.annotation.hints"
implementationClass="com.intellij.codeInsight.hints.AnnotationInlaySettingsProvider"/>
<codeInsight.declarativeInlayProvider language="JAVA"
@@ -113,17 +113,17 @@ fun submitFeedback(feedbackData: FeedbackRequestDataHolder,
onDone: () -> Unit,
onError: () -> Unit,
feedbackRequestType: FeedbackRequestType = FeedbackRequestType.TEST_REQUEST) {
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)
}
//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() {
}
}
@@ -526,7 +526,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 "";
}
/*
@@ -939,7 +939,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"/>
@@ -207,7 +207,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;
}
@@ -328,7 +328,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"