From ff4dc300667aba669ee2be40ac9a79ad8dcff626 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=BC=ED=98=81?= Date: Sun, 23 Aug 2026 19:49:56 +0900 Subject: [PATCH] =?UTF-8?q?chore(build):=20=EB=B9=8C=EB=93=9C=C2=B7?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=ED=81=B4=EB=9E=98=EC=8A=A4?= =?UTF-8?q?=ED=8C=A8=EC=8A=A4=20bouncycastle=20=ED=95=98=ED=95=9C=EC=9D=84?= =?UTF-8?q?=201.84=20=EB=A1=9C=20=EC=83=81=ED=96=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Robolectric 4.15.1(bcprov 1.80)·AGP 9.2.1(1.79) 전이 의존성이 GHSA-574f-3g2m-x479(critical) 영향권이라 constraint 로 1.84 를 보장한다. APK 산출물에는 bouncycastle 이 포함되지 않는다. #921 --- build-logic/build.gradle.kts | 9 ++++++ build.gradle.kts | 53 ++++++++++++++++++++++++++++++++++++ gradle/libs.versions.toml | 3 ++ 3 files changed, 65 insertions(+) diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index 31825d3c7a..17e60a7436 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -11,6 +11,15 @@ dependencies { compileOnly("org.jetbrains.kotlin:kotlin-serialization:${libs.versions.kotlin.get()}") testImplementation(libs.junit) testImplementation(gradleTestKit()) + + // 루트 build.gradle.kts 의 bouncycastle 하한은 별도 빌드인 여기까지 미치지 않는다 — 같은 근거(#921). + constraints { + listOf("bcprov-jdk18on", "bcpkix-jdk18on", "bcutil-jdk18on").forEach { artifact -> + implementation("org.bouncycastle:$artifact:${libs.versions.bouncycastle.get()}") { + because("GHSA-574f-3g2m-x479 등 1.84 미만 취약 — #921") + } + } + } } tasks.withType().configureEach { diff --git a/build.gradle.kts b/build.gradle.kts index c31689f803..6cd6dd616e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,22 @@ import kotlinx.kover.gradle.plugin.dsl.KoverProjectExtension import org.gradle.kotlin.dsl.configure +// AGP 9.2.1 이 buildscript classpath 로 끌어오는 bouncycastle 1.79 는 GHSA-574f-3g2m-x479(critical) +// 영향권이다(#921). 루트 classpath 는 plugins 블록 처리 시점에 리졸브가 끝나 아래 본문 훅으로는 늦고, +// buildscript 블록에서는 버전 카탈로그 accessor 를 쓸 수 없다 — libs.versions.toml 의 bouncycastle +// 과 같은 값을 리터럴로 유지할 것. +buildscript { + dependencies { + constraints { + listOf("bcprov-jdk18on", "bcpkix-jdk18on", "bcutil-jdk18on").forEach { artifact -> + add("classpath", "org.bouncycastle:$artifact:1.84") { + because("GHSA-574f-3g2m-x479 등 1.84 미만 취약 — #921") + } + } + } + } +} + // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { alias(libs.plugins.kover) @@ -16,6 +32,43 @@ plugins { alias(libs.plugins.firebase.crashlytics) apply false } +// 빌드·테스트 클래스패스의 bouncycastle 하한(#921). Robolectric 4.15.1(bcprov 1.80)·AGP 9.2.1(1.79) +// 전이 의존성이 GHSA-574f-3g2m-x479(critical) 영향권인데 상류 최신판도 1.84 미만이라 constraint 로 +// 올린다. androidLintTool 처럼 AGP 가 뒤늦게 만드는 configuration 까지 잡도록 configureEach 로 걸고, +// require 시맨틱이라 상류가 1.84 이상을 선언하게 되면 그쪽이 이긴다. APK 산출물에는 bouncycastle 이 +// 없다(releaseRuntimeClasspath 0건 실측). build-logic 은 별도 빌드라 build-logic/build.gradle.kts 가 +// 같은 하한을 선언한다. +val bouncycastleArtifacts = listOf("bcprov-jdk18on", "bcpkix-jdk18on", "bcutil-jdk18on") +val bouncycastleFloor = libs.versions.bouncycastle.get() + +fun Project.bouncycastleConstraintSet() = + bouncycastleArtifacts.map { artifact -> + dependencies.constraints.create("org.bouncycastle:$artifact:$bouncycastleFloor") { + because("GHSA-574f-3g2m-x479 등 1.84 미만 취약 — #921") + } + } + +allprojects { + // Gradle 9 는 declarable 이 아닌 configuration(compileClasspath 등)에 constraint 선언을 금지한다. + // 전용 declarable configuration 에 담아 모든 resolvable configuration 이 extend 하게 한다. + val floor = + configurations.create("bouncycastleConstraints") { + isCanBeResolved = false + isCanBeConsumed = false + bouncycastleConstraintSet().forEach { dependencyConstraints.add(it) } + } + configurations.configureEach { + if (name != floor.name && isCanBeResolved) extendsFrom(floor) + } +} +// buildscript 컨테이너에는 configuration 을 추가할 수 없어 declarable 인 classpath 에 constraint 를 +// 직접 단다. 루트 자신의 classpath 는 최상단 buildscript 블록이 담당한다(여기 시점엔 리졸브 완료라 불가). +subprojects { + buildscript.configurations.named("classpath") { + bouncycastleConstraintSet().forEach { dependencyConstraints.add(it) } + } +} + val coverageProjects = subprojects.filter { project -> project.buildFile.isFile && diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1011da0c2c..bfa04e7552 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -45,6 +45,9 @@ firebaseCrashlytics = "3.0.7" firebaseBom = "34.16.0" konsist = "0.17.3" kover = "0.9.9" +# 빌드·테스트 클래스패스 전용 보안 하한 — GHSA-574f-3g2m-x479(critical) 등 3건이 1.84 에서 패치(#921). +# 루트 build.gradle.kts 의 buildscript 블록은 카탈로그 accessor 를 못 써 같은 값을 리터럴로 둔다. +bouncycastle = "1.84" [libraries] androidx-biometric = { module = "androidx.biometric:biometric", version.ref = "biometric" }