From ad4eddb779371345535eeda8ded75703357c4dac Mon Sep 17 00:00:00 2001 From: Nikita Iarychenko Date: Thu, 10 Apr 2025 18:08:02 +0400 Subject: [PATCH] OPENIDE #161 Change approach from whitelists to blacklists --- .../com/intellij/util/io/HttpRequests.java | 4 +- .../src/ru/openide/io/BlackListUrls.kt | 79 ++++++ .../src/ru/openide/io/WhiteListUrls.kt | 231 ------------------ 3 files changed, 81 insertions(+), 233 deletions(-) create mode 100644 platform/ide-core/src/ru/openide/io/BlackListUrls.kt delete mode 100644 platform/ide-core/src/ru/openide/io/WhiteListUrls.kt diff --git a/platform/ide-core/src/com/intellij/util/io/HttpRequests.java b/platform/ide-core/src/com/intellij/util/io/HttpRequests.java index 2d6704ebefe8..e4f7d30a4648 100644 --- a/platform/ide-core/src/com/intellij/util/io/HttpRequests.java +++ b/platform/ide-core/src/com/intellij/util/io/HttpRequests.java @@ -25,7 +25,7 @@ import com.intellij.util.net.NetUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import ru.openide.io.StubUrlConnection; -import ru.openide.io.WhiteListUrls; +import ru.openide.io.BlackListUrls; import javax.net.ssl.*; import java.io.*; @@ -554,7 +554,7 @@ public final class HttpRequests { request.myUrl = "https:" + request.myUrl.substring(5); } - if (!WhiteListUrls.isAvailableUrl(request.myUrl)) { + if (!BlackListUrls.isAvailableUrl(request.myUrl)) { LOG.info("Not available url: " + request.myUrl); URL url = new URL(request.myUrl); return new StubUrlConnection(url); diff --git a/platform/ide-core/src/ru/openide/io/BlackListUrls.kt b/platform/ide-core/src/ru/openide/io/BlackListUrls.kt new file mode 100644 index 000000000000..450e2aa11562 --- /dev/null +++ b/platform/ide-core/src/ru/openide/io/BlackListUrls.kt @@ -0,0 +1,79 @@ +// OpenIDE Project +// Copyright (C) 2025 “Open Development Platform” Ltd. (https://openide.ru) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License version 3 or later as published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +package ru.openide.io + +import com.intellij.notification.Notification +import com.intellij.notification.NotificationAction +import com.intellij.notification.NotificationType +import java.net.URL +import java.net.URLConnection + +object BlackListUrls { + private val urls = listOf( + "resources.jetbrains.com", + "download.jetbrains.com", + "packages.jetbrains.team", + "cache-redirector.jetbrains.com", + "www.jetbrains.com", + "intellij-test-discovery.labs.intellij.net", + "forms-service.jetbrains.com", + "ea-report.jetbrains.com", + "plugins.jetbrains.com", + "resources.jetbrains.com", + "uploads.jetbrains.com", + "analytics.services.jetbrains.com" + ) + + private val WITHOUT_PROTOCOL_REGEX = Regex("https?://") + + @JvmStatic + fun isAvailableUrl(url: String): Boolean { + if (url.startsWith("file")) return true + val urlWithoutProtocol = url.replaceFirst(WITHOUT_PROTOCOL_REGEX, "") + if (urls.startsWith(urlWithoutProtocol)) { + if (OpenIdePersistentUrlStorage.getInstance().getUrls().startsWith(url)) { + return true + } + + val findPluginId = OpenIdePluginUtil.getInstance().findNonBundledPluginId(Throwable()) + if (findPluginId != null) { + return true + } + + showAccessRequestNotification(url) + return false + } + + return true + } + + private fun showAccessRequestNotification(url: String) { + val addUrlAction = NotificationAction.createSimpleExpiring(OpenIdeBundle.message("allow.access")) { + OpenIdePersistentUrlStorage.getInstance().getUrls().add(url) + } + + Notification("Find Problems", OpenIdeBundle.message("access.to.untrusted.source"), url, NotificationType.WARNING) + .addAction(addUrlAction) + .notify(null) + } + + private fun List.startsWith(url: String): Boolean { + return this.any { url.startsWith(it, true) } + } +} + +class StubUrlConnection(url: URL): URLConnection(url) { + override fun connect() { + } +} \ No newline at end of file diff --git a/platform/ide-core/src/ru/openide/io/WhiteListUrls.kt b/platform/ide-core/src/ru/openide/io/WhiteListUrls.kt deleted file mode 100644 index b3dd47e2f91f..000000000000 --- a/platform/ide-core/src/ru/openide/io/WhiteListUrls.kt +++ /dev/null @@ -1,231 +0,0 @@ -// OpenIDE Project -// Copyright (C) 2025 “Open Development Platform” Ltd. (https://openide.ru) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License version 3 or later as published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see http://www.gnu.org/licenses/. -package ru.openide.io - -import com.intellij.notification.Notification -import com.intellij.notification.NotificationAction -import com.intellij.notification.NotificationType -import java.net.URL -import java.net.URLConnection - -object WhiteListUrls { - private val urls = listOf( - "github.com", - "search.maven.org", - "repo.jfrog.org", - "oss.sonatype.org", - "repository.jboss.org", - "repo.maven.apache.org", - "repo1.maven.org", - "plugins.gradle.org/plugin/org.jetbrains.intellij", - "api.github.com/repos", - "pypi.python.org", - "localhost", - "services.gradle.org", - "plugins.openide.ru", - "downloads.marketplace.openide.ru", - "downloads.openide.ru", - "repo1.maven.org/maven2/net/sourceforge/plantuml/plantuml/1.2023.10/plantuml-1.2023.10.jar", - "amplicode.ru", - "download.openide.ru", - "download-ide.axiomjdk.ru", - "schemastore.org", - "storage.yandexcloud.net", - "openide.ru", - "d5dloaaon52j82oceane.apigw.yandexcloud.net", - "index.docker.io", - "grafana.com", - "mcr.microsoft.com", - "container-registry.oracle.com", - "registry-1.docker.io", - "checksid.jmix.io", - "store-admin.jmix.io", - "jmix", - "sso.jmix.io", - "account.jmix.io", - "global.repo.jmix.io", - "nexus.jmix.io", - "usage-stat.cuba-platform.com", - "api.hsforms.com/submissions/v3/integration/submit/", - "store.amplicode.ru", - "ls.store.amplicode.ru", - "resources.openide.ru", - "api.github.com", - "avatars.githubusercontent.com", - "plugin.openbpm.ru", - "gitflic.ru" - ) - - // Collect urls from KnownSchemaIdentifiers.json - private val jsonSchemaUrls = listOf( - "raw.githubusercontent.com", - "json.schemastore.org", - "schemastore.azurewebsites.net", - "json-schema.org", - "developer.1password.com/schema/ssh-agent-config.json", - "appsemble.app/api.json#/components/schemas/AppDefinition", - "gitlab.com/appsemble/appsemble/-/raw/HEAD/packages/cli/assets/appsemblerc.schema.json", - "www.asyncapi.com/schema-store/all.schema-store.json", - "atmos.tools/schemas/atmos/atmos-manifest/1.0/atmos-manifest.json", - "coderabbit.ai/integrations/schema.v2.json", - "github.com/cloudcannon/configuration-types/releases/latest/download/cloudcannon-config.schema.json", - "github.com/cmhughes/latexindent.pl/raw/main/documentation/latexindent-yaml-schema.json", - "chat-agents.lobehub.com/schema/lobeAgentSchema_v1.json", - "fasterci.com/config.schema.json", - "flagd.dev/schema/v0/flags.json", - "ide-integration.batect.dev/v1/configSchema.json", - "bitbucket.org/atlassianlabs/intellij-bitbucket-references-plugin/raw/master/src/main/resources/schemas/bitbucket-pipelines.schema.json", - "schemas.wp.org/trunk/block.json", - "blockprotocol.org/schemas/block-metadata.json", - "carafe.fm/schema/draft-02/bundle.schema.json", - "gitlab.com/chromaway/core-tools/chromia-cli/-/raw/dev/chromia-build-tools/src/main/resources/chromia-model-schema.json", - "appliedengdesign.github.io/cnccodes-json-schema/draft/2022-07/schema", - "deta.space/assets/spacefile.schema.json", - "codemagic.io/codemagic-schema.json", - "wixplosives.github.io/codux-config-schema/codux.config.schema.json", - "openapi.vercel.sh/vercel.json", - "unpkg.com/@changesets/config/schema.json", - "getcomposer.org/schema.json", - "on.cypress.io/cypress.schema.json", - "gitlab.com/sbenv/veroxis/docker-seq/-/raw/HEAD/docker-seq.schema.json", - "dprint.dev/schemas/v0.json", - "dstack-runner-downloads.s3.eu-west-1.amazonaws.com/latest/schemas/configuration.json", - "enterprisecontract.dev/enterprise-contract-controller/schema/policy_spec.json", - "cdn.jsdelivr.net/gh/tarampampam/error-pages@latest/schemas/config/1.0.schema.json", - "gitlab.com/sbenv/veroxis/ezd-rs/-/raw/HEAD/ezd.schema.json", - "gitlab.com/fdroid/fdroiddata/-/raw/master/schemas/metadata.json", - "ffizer.github.io/ffizer/ffizer.schema.json", - "gitlab.cern.ch/steam/fiqus/-/raw/master/docs/schema.json", - "gitlab.com/gitlab-org/gitlab/-/raw/master/app/assets/javascripts/editor/schema/ci.json", - "gitpod.io/schemas/gitpod-schema.json", - "golangci-lint.run/jsonschema", - "goreleaser.com/static", - "github.com/goss-org/goss/raw/master/docs/schema.yaml", - "unpkg.com/@graphql-mesh/types/esm/config-schema.json", - "unpkg.com/graphql-config/config-schema.json", - "www.graphql-code-generator.com/config.schema.json", - "hazelcast.com/schema/config/hazelcast-config-5.5.json", - "html-validate.org/schemas/config.json", - "hyperfoil.io/schema.json", - "ifstate.net/schema/1/ifstate.conf.schema.json", - "schema.infrahub.app/python-sdk/repository-config/latest.json", - "jenkins-x.io/schemas", - "github.com/abstracta/jmeter-java-dsl/releases/latest/download/jmdsl-config-schema.json", - "jsr.io/schema/config-file.v1.json", - "jsonapi.org/schema", - "www.krakend.io/schema/krakend.json", - "kubri.dev/schema.json", - "cdn.jsdelivr.net/npm/liblab@latest/liblab.config.schema.json", - "w3id.org/linkml/meta.schema.json", - "grnhse-vpc-assets.s3.amazonaws.com/jsonschemas/lotus.yaml.json", - "github.com/napari/npe2/releases/latest/download/schema.json", - "noxorg.dev/schemas/NoxConfiguration.json", - "spec.openapis.org/oas/3.1/schema/2022-10-07", - "meta.open-rpc.org/", - "github.com/usnistgov/OSCAL", - "schema.postman.com/collection/json/v2.1.0/draft-07/collection.json", - "www.qgoda.net/schemas/qgoda.json", - "docs.renovatebot.com/renovate-schema.json", - "cdn.jsdelivr.net/gh/roadrunner-server/roadrunner@latest/schemas/config/3.0.schema.json", - "cdn.sdf.com/schemas/sdf-schema-1.3.json", - "starship.rs/config-schema.json", - "schemas.wp.org/trunk/theme.json", - "turborepo.org/schema.json", - "static.trunk.io/pub/trunk-yaml-schema.json", - "developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", - "tstyche.org/schemas/config.json", - "cdn.jsdelivr.net/npm/tsup/schema.json", - "sap.github.io/ui5-tooling/schema", - "github.com/go-vela/types/releases/latest/download/schema.json", - "www.unpkg.com/wrangler/config-schema.json", - "json-stat.org/format/schema/2.0/", - "typedoc.org/schema.json", - "mise.jdx.dev/schema/mise.json", - "motif.land/api/motif.schema.json", - "github.com/helmwave/helmwave/releases/latest/download/schema.json", - "github.com/fbecart/zinoma/releases/latest/download/zinoma-schema.json", - "uniswap.org/tokenlist.schema.json", - "docs.gradle.com/enterprise/admin/schema/gradle-enterprise-config-schema-10.json", - "docs.gradle.com/build-cache-node/schema/build-cache-node-config-schema-5.json", - "yarnpkg.com/configuration/yarnrc.json", - "taskfile.dev/schema.json", - "render.com/schema/render.yaml.json", - "www.liquibase.org/json/schema/liquibase-flow-file-latest.json", - "github.com/mason-org/registry-schema/releases/latest/download/package.schema.json", - "s3.eu-central-1.amazonaws.com/files.netin.io/spider-schemas/template.schema.json", - "noodl.s3.us-west-1.amazonaws.com/noodl.schema.json", - "download.stackhawk.com/hawk/jsonschema/hawkconfig.json", - "www.updatecli.io/schema", - "geojson.org/schema/GeoJSON.json", - "public.dhe.ibm.com", - "datahubproject.io/schemas/datahub_ingestion_schema.json", - "upliftci.dev/static/schema.json", - "github.com/DannyBen/completely/blob/master/schemas/completely.json", - "docs.visivo.io/assets/visivo_schema.json", - "enduricastorage.blob.core.windows.net/public/endurica-cl-schema.json", - "rivet.gg/rivet.schema.json", - "cdn.subsquid.io/schemas/squid_manifest.json", - "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/raw/master/pkg/agentcfg/agentcfg_schemas/ConfigurationFile.json", - "www.cardgamesimulator.com/schema/CardGameDef.json", - "alec016.github.io/Custom-Machinery", - "bioimage-io.github.io/spec-bioimage-io/bioimageio_schema_latest.json", - "www.json-wf.org.uk/json-wf-schema-1.0.json", - "download.qt.io/official_releases/qtcreator/latest/installer_source/jsonschemas/project.json", - "api.app-prg1.zerops.io", - "repo1.maven.org/maven2/com/walmartlabs/concord/runtime/v2/concord-runtime-model-v2/2.14.0/concord-runtime-model-v2-2.14.0-schema.json", - "deployments.allegrogroup.com/tycho/schema", - "www.eidolonai.com/json_schema/v1/resources/overview.json", - "waku.ngjx.org/static/schema.json" - ) - - private val WITHOUT_PROTOCOL_REGEX = Regex("https?://") - - @JvmStatic - fun isAvailableUrl(url: String): Boolean { - if (urls.startWith(url) - || jsonSchemaUrls.startWith(url) - || OpenIdePersistentUrlStorage.getInstance().getUrls().startWith(url)) { - return true - } - - val findPluginId = OpenIdePluginUtil.getInstance().findNonBundledPluginId(Throwable()) - if (findPluginId != null) { - return true - } - - showAccessRequestNotification(url) - return false - } - - private fun showAccessRequestNotification(url: String) { - val addUrlAction = NotificationAction.createSimpleExpiring(OpenIdeBundle.message("allow.access")) { - OpenIdePersistentUrlStorage.getInstance().getUrls().add(url) - } - - Notification("Find Problems", OpenIdeBundle.message("access.to.untrusted.source"), url, NotificationType.WARNING) - .addAction(addUrlAction) - .notify(null) - } - - private fun List.startWith(url: String): Boolean { - if (url.startsWith("file")) return true - val urlWithoutProtocol = url.replaceFirst(WITHOUT_PROTOCOL_REGEX, "") - return this.any { urlWithoutProtocol.startsWith(it, true) } - } -} - -class StubUrlConnection(url: URL): URLConnection(url) { - override fun connect() { - } -} \ No newline at end of file