Make the addition of JitPack repository configurable (#48595)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/48595

Historically React Native used to include the JitPack repository be default in the default repositories.

This sadly exposes React Native projects to supply chain attacks as explained here:
https://blog.oversecured.com/Introducing-MavenGate-a-supply-chain-attack-method-for-Java-and-Android-applications/

Moreover, artifacts on Jitpack are not GPG signed it's complicated to verify the identity of artifact authors.
I'm introducing a Gradle property to control if Jitpack should be included by default or not.

User can control this behavior by changing their `gradle.properties` file as such:

```
includeJitpackRepository=false
```

The default value of this property is currently true, but we're looking into changing it to false in the future.

Changelog:
[Android] [Added] - Make the addition of JitPack repository configurable

Reviewed By: cipolleschi

Differential Revision: D68016028

fbshipit-source-id: 392513fef389a4835b4e00a8184459e00d51fdd0
This commit is contained in:
Nicola Corti
2025-01-10 07:38:08 -08:00
committed by Facebook GitHub Bot
parent c85be01cba
commit a98528e609
3 changed files with 102 additions and 6 deletions
@@ -8,10 +8,13 @@
package com.facebook.react.utils
import com.facebook.react.utils.PropertyUtils.DEFAULT_INTERNAL_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.INCLUDE_JITPACK_REPOSITORY
import com.facebook.react.utils.PropertyUtils.INCLUDE_JITPACK_REPOSITORY_DEFAULT
import com.facebook.react.utils.PropertyUtils.INTERNAL_PUBLISHING_GROUP
import com.facebook.react.utils.PropertyUtils.INTERNAL_REACT_NATIVE_MAVEN_LOCAL_REPO
import com.facebook.react.utils.PropertyUtils.INTERNAL_USE_HERMES_NIGHTLY
import com.facebook.react.utils.PropertyUtils.INTERNAL_VERSION_NAME
import com.facebook.react.utils.PropertyUtils.SCOPED_INCLUDE_JITPACK_REPOSITORY
import java.io.File
import java.net.URI
import java.util.*
@@ -55,12 +58,14 @@ internal object DependencyUtils {
it.excludeGroup("com.facebook.react")
}
}
mavenRepoFromUrl("https://www.jitpack.io") { repo ->
repo.content {
// We don't want to fetch JSC or React from JitPack
it.excludeGroup("org.webkit")
it.excludeGroup("io.github.react-native-community")
it.excludeGroup("com.facebook.react")
if (shouldAddJitPack()) {
mavenRepoFromUrl("https://www.jitpack.io") { repo ->
repo.content { content ->
// We don't want to fetch JSC or React from JitPack
content.excludeGroup("org.webkit")
content.excludeGroup("io.github.react-native-community")
content.excludeGroup("com.facebook.react")
}
}
}
}
@@ -167,4 +172,13 @@ internal object DependencyUtils {
it.url = uri
action(it)
}
internal fun Project.shouldAddJitPack() =
when {
hasProperty(SCOPED_INCLUDE_JITPACK_REPOSITORY) ->
property(SCOPED_INCLUDE_JITPACK_REPOSITORY).toString().toBoolean()
hasProperty(INCLUDE_JITPACK_REPOSITORY) ->
property(INCLUDE_JITPACK_REPOSITORY).toString().toBoolean()
else -> INCLUDE_JITPACK_REPOSITORY_DEFAULT
}
}
@@ -22,6 +22,13 @@ object PropertyUtils {
const val REACT_NATIVE_ARCHITECTURES = "reactNativeArchitectures"
const val SCOPED_REACT_NATIVE_ARCHITECTURES = "react.nativeArchitectures"
/** Public property that allows to control whether the JitPack repository is included or not */
const val INCLUDE_JITPACK_REPOSITORY = "includeJitpackRepository"
const val SCOPED_INCLUDE_JITPACK_REPOSITORY = "react.includeJitpackRepository"
/** By default we include JitPack till React Native 0.80 where this is going to become false */
internal const val INCLUDE_JITPACK_REPOSITORY_DEFAULT = true
/**
* Internal Property that acts as a killswitch to configure the JDK version and align it for app
* and all the libraries.
@@ -14,6 +14,7 @@ import com.facebook.react.utils.DependencyUtils.getDependencySubstitutions
import com.facebook.react.utils.DependencyUtils.mavenRepoFromURI
import com.facebook.react.utils.DependencyUtils.mavenRepoFromUrl
import com.facebook.react.utils.DependencyUtils.readVersionAndGroupStrings
import com.facebook.react.utils.DependencyUtils.shouldAddJitPack
import java.net.URI
import org.assertj.core.api.Assertions.assertThat
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
@@ -98,6 +99,60 @@ class DependencyUtilsTest {
.isNotNull()
}
@Test
fun configureRepositories_withIncludeJitpackRepositoryFalse_doesNotContainJitPack() {
val repositoryURI = URI.create("https://www.jitpack.io")
var project = createProject()
project.extensions.extraProperties.set("includeJitpackRepository", "false")
configureRepositories(project, tempFolder.root)
assertThat(
project.repositories.firstOrNull {
it is MavenArtifactRepository && it.url == repositoryURI
})
.isNull()
// We test both with scoped and unscoped property
project = createProject()
project.extensions.extraProperties.set("react.includeJitpackRepository", "false")
configureRepositories(project, tempFolder.root)
assertThat(
project.repositories.firstOrNull {
it is MavenArtifactRepository && it.url == repositoryURI
})
.isNull()
}
@Test
fun configureRepositories_withincludeJitpackRepositoryTrue_containJitPack() {
val repositoryURI = URI.create("https://www.jitpack.io")
var project = createProject()
project.extensions.extraProperties.set("includeJitpackRepository", "true")
configureRepositories(project, tempFolder.root)
assertThat(
project.repositories.firstOrNull {
it is MavenArtifactRepository && it.url == repositoryURI
})
.isNotNull()
// We test both with scoped and unscoped property
project = createProject()
project.extensions.extraProperties.set("react.includeJitpackRepository", "true")
configureRepositories(project, tempFolder.root)
assertThat(
project.repositories.firstOrNull {
it is MavenArtifactRepository && it.url == repositoryURI
})
.isNotNull()
}
@Test
fun configureRepositories_withProjectPropertySet_hasHigherPriorityThanMavenCentral() {
val localMaven = tempFolder.newFolder("m2")
@@ -404,4 +459,24 @@ class DependencyUtilsTest {
assertThat(mavenRepo.url).isEqualTo(repoFolder.toURI())
}
@Test
fun shouldAddJitPack_withScopedProperty() {
val project = createProject(tempFolder.root)
project.extensions.extraProperties.set("react.includeJitpackRepository", "false")
assertThat(project.shouldAddJitPack()).isFalse()
}
@Test
fun shouldAddJitPack_withUnscopedProperty() {
val project = createProject(tempFolder.root)
project.extensions.extraProperties.set("react.includeJitpackRepository", "false")
assertThat(project.shouldAddJitPack()).isFalse()
}
@Test
fun shouldAddJitPack_defaultIsTrue() {
val project = createProject(tempFolder.root)
assertThat(project.shouldAddJitPack()).isTrue()
}
}