From 89a20fad8b76144ed0849e9b4018492d1ae86452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=BC=ED=98=81?= Date: Mon, 24 Aug 2026 23:34:12 +0900 Subject: [PATCH] =?UTF-8?q?security(build):=20Security=20=ED=83=AD=20?= =?UTF-8?q?=EC=9E=94=EC=97=AC=20=EC=95=8C=EB=A6=BC=204=EA=B1=B4=20?= =?UTF-8?q?=ED=95=B4=EC=86=8C=20=E2=80=94=20okhttp=C2=B7logback=C2=B7httpc?= =?UTF-8?q?lient=20=ED=95=98=ED=95=9C=EA=B3=BC=20=EC=9B=8C=ED=81=AC?= =?UTF-8?q?=ED=94=8C=EB=A1=9C=20permissions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Security 탭 미해결 48건(코드 스캐닝 3 + Dependabot 45)을 전수 분류해, 다른 PR· 이슈가 다루지 않는 4건만 처리한다. 경로가 전부 settings.gradle.kts 로 뭉개져 보여 전 프로젝트 전 resolvable configuration 을 실측했다(develop ec30bafd9, 수집 1349행). - okio 2.8.0 (GHSA-w33c-445m-f8w7): Kakao SDK 경유 okhttp 4.9.2 의 전이 의존성 으로 :feature:onboarding:presentation·:feature:setting:presentation 의 compileClasspath 에만 남아 있었다. :app 최종 조합은 이미 okhttp 5.4.0 + okio-jvm 3.17.0 이라 APK 는 안전했고, 실체는 두 모듈이 okio 2.8.0 API 로 컴파일되고 런타임엔 3.17.0 이 오는 불일치다. okhttp 4.9.x 가 okio 2.x API 를 쓰므로 okio 를 직접 올리면 런타임이 깨진다 — okhttp 를 카탈로그 버전으로 정렬해 okio 를 함께 끌어올린다. - httpclient 4.5.6 (GHSA-7r82-7xv7-xcpj): androidLintTool 과 UTP result-listener configuration 경유. buildscript classpath 는 이미 4.5.14. - logback-core 1.3.16 (GHSA-jhq6-gfmj-v8fx·GHSA-p47f-322f-whfh· GHSA-qqpg-mvqg-649v): 전 모듈 ktlint configuration 경유. classic 은 core 와 버전이 같아야 동작해 함께 올린다. - mock-cleanup-check.yml: 워크플로 18종 중 유일하게 permissions 블록이 없어 기본 토큰 권한 전체를 받고 있었다(actions/missing-workflow-permissions). 범위 밖 44건 — netty 39건은 #1058/PR #1060 이 AGP UTP 경유분을 덮는 중이고 실측상 취약 버전 출처가 unified-test-platform 두 configuration 뿐이라 그 범위와 일치한다. KGP 1건은 #986(패치가 2.4.20-Beta1 베타뿐), 생체인증 CodeQL 2건은 Keystore CryptoObject 설계 변경이라 #1073 으로 뗀다. --- .github/workflows/mock-cleanup-check.yml | 3 ++ build.gradle.kts | 38 ++++++++++++++++++++---- gradle/libs.versions.toml | 2 ++ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/.github/workflows/mock-cleanup-check.yml b/.github/workflows/mock-cleanup-check.yml index e3ab394249..f172897a70 100644 --- a/.github/workflows/mock-cleanup-check.yml +++ b/.github/workflows/mock-cleanup-check.yml @@ -4,6 +4,9 @@ on: push: branches: [main] +permissions: + contents: read + jobs: mock-cleanup: name: Check MOCK_CLEANUP TODOs diff --git a/build.gradle.kts b/build.gradle.kts index bb76ed224c..b7a27a91fb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -47,13 +47,14 @@ plugins { alias(libs.plugins.firebase.crashlytics) apply false } -// 빌드·테스트 클래스패스의 보안 하한(#921·#975~#985). 상류가 취약 버전을 물고 있고 상류 최신판도 +// 클래스패스의 보안 하한(#921·#975~#985·#1072). 상류가 취약 버전을 물고 있고 상류 최신판도 // 아직 패치 버전 미만이라 constraint 로 올린다 — Robolectric 4.15.1(bcprov 1.80)·AGP 9.2.1(bcprov // 1.79·commons-lang3 3.16.0·jose4j 0.9.5·jdom2 2.0.6)·Firebase App Distribution 5.3.0(netty -// 4.1.110.Final). androidLintTool 처럼 AGP 가 뒤늦게 만드는 configuration 까지 잡도록 configureEach -// 로 걸고, require 시맨틱이라 상류가 하한 이상을 선언하게 되면 그쪽이 이긴다. 여기 목록은 전부 빌드 -// 도구 경유라 APK 산출물에는 없다(releaseRuntimeClasspath 0건 실측). build-logic 은 별도 빌드라 -// build-logic/build.gradle.kts 가 같은 하한을 선언한다. +// 4.1.110.Final)·AGP androidLintTool 과 UTP(httpclient 4.5.6)·ktlint CLI(logback 1.3.16)·Kakao +// SDK 2.23.2(okhttp 4.9.2→okio 2.8.0). androidLintTool 처럼 AGP 가 뒤늦게 만드는 configuration +// 까지 잡도록 configureEach 로 걸고, require 시맨틱이라 상류가 하한 이상을 선언하게 되면 그쪽이 +// 이긴다. okhttp 를 뺀 나머지는 빌드 도구 경유라 APK 산출물에는 없다(releaseRuntimeClasspath 실측). +// build-logic 은 별도 빌드라 build-logic/build.gradle.kts 가 같은 하한을 선언한다. data class SecurityFloor( val module: String, val version: String, @@ -84,7 +85,32 @@ val securityFloors = version = libs.versions.jdom2.get(), because = "GHSA-2363-cqg2-863c — 2.0.6.1 미만 취약 — #985", ), - ) + SecurityFloor( + module = "org.apache.httpcomponents:httpclient", + version = libs.versions.httpclient.get(), + because = "GHSA-7r82-7xv7-xcpj — 4.5.13 미만 취약 — #1072", + ), + ) + + // logback-core 만 취약하지만 classic 은 core 와 같은 버전이라야 동작해 함께 올린다. + listOf("logback-core", "logback-classic").map { artifact -> + SecurityFloor( + module = "ch.qos.logback:$artifact", + version = libs.versions.logback.get(), + because = "GHSA-jhq6-gfmj-v8fx 등 3건 — 1.5.34 미만 취약 — #1072", + ) + } + + // okio 2.8.0(GHSA-w33c-445m-f8w7)이 Kakao SDK 경유 okhttp 4.9.2 로 딸려 온다. okhttp 4.9.x 는 + // okio 2.x API 를 쓰므로 okio 만 3.x 로 올리면 런타임이 깨진다. 그래서 okio 가 아니라 okhttp 를 + // 카탈로그 버전으로 정렬해 okio 를 함께 끌어올린다 — :app 최종 조합이 이미 그 짝(okhttp 5.4.0 + + // okio-jvm 3.17.0)이라, 카탈로그 okhttp 를 직접 의존하지 않는 feature 모듈의 컴파일 클래스패스만 + // 뒤처져 있던 것을 맞추는 셈이다. logging-interceptor 는 okhttp 와 같은 버전이라야 한다. + listOf("okhttp", "logging-interceptor").map { artifact -> + SecurityFloor( + module = "com.squareup.okhttp3:$artifact", + version = libs.versions.okhttp.get(), + because = "GHSA-w33c-445m-f8w7 — okhttp 4.9.2 가 물고 오는 okio 2.8.0 취약 — #1072", + ) + } fun Project.securityFloorConstraintSet() = securityFloors.map { floor -> diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ed7c3cb3f0..29e1e87945 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -52,6 +52,8 @@ netty = "4.1.137.Final" commonsLang3 = "3.18.0" jose4j = "0.9.6" jdom2 = "2.0.6.1" +httpclient = "4.5.14" +logback = "1.5.34" [libraries] androidx-biometric = { module = "androidx.biometric:biometric", version.ref = "biometric" }