Skip to content

security(build): Security 탭 잔여 알림 4건 해소 — okhttp·logback·httpclient 하한과 워크플로 permissions (closes 1072) [base: develop] - #1075

Merged
1hyok merged 2 commits into
developfrom
security/1072
Aug 25, 2026
Merged

1hyok merged 2 commits into
developfrom
security/1072

Conversation

@1hyok

@1hyok 1hyok commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Closes #1072

Security 탭 미해결 48건(코드 스캐닝 3 + Dependabot 45)을 전수 분류해, 다른 PR·이슈가 다루지 않는 4건만 처리한다.

경로 표시가 전부 settings.gradle.kts 로 뭉개져 있어 출처를 믿을 수 없으므로, 전 프로젝트·전 resolvable configuration 을 전수 리졸브해 실측했다(base ec30bafd9, 수집 1349행).

고친 것

1. com.squareup.okio:okio 2.8.0 — GHSA-w33c-445m-f8w7 (medium)

48건 중 유일하게 앱 코드 클래스패스에 있던 건. Kakao SDK 가 끌어오는 okhttp 4.9.2 의 전이 의존성이다.

com.squareup.okio:okio:2.8.0
\--- com.squareup.okhttp3:okhttp:4.9.2
     +--- com.kakao.sdk:v2-network:2.23.2
     ...

:feature:onboarding:presentation 과 :feature:setting:presentation 의 releaseCompileClasspath·debugCompileClasspath·각 테스트 컴파일 클래스패스가 오염돼 있었다.

최종 APK 는 원래 안전하다 — :app 의 releaseRuntimeClasspath 는 okhttp 5.4.0 과 함께 정렬돼 okio-jvm:3.17.0 이다. 실체는 그 두 모듈이 okio 2.8.0 API 로 컴파일되고 런타임엔 3.17.0 이 오는 컴파일/런타임 불일치다. 카탈로그가 이미 okhttp 5.4.0 을 선언하는데, 두 모듈만 카탈로그 okhttp 를 직접 의존하지 않아 Kakao SDK 의 4.9.2 를 그대로 받고 있었다.

okhttp 4.9.x 는 okio 2.x API 를 쓰므로 okio 만 3.x 로 올리면 런타임이 깨진다. 그래서 okio 가 아니라 okhttp 를 카탈로그 버전으로 정렬해 okio 를 함께 끌어올렸다 — :app 최종 조합이 이미 그 짝이라 뒤처진 컴파일 클래스패스를 맞추는 셈이다. logging-interceptor 도 okhttp 와 버전이 같아야 해 함께 건다.

2. org.apache.httpcomponents:httpclient 4.5.6 — GHSA-7r82-7xv7-xcpj (medium)

buildscript classpath 는 이미 4.5.14 인데, AGP 가 뒤늦게 만드는 androidLintTool 과 unified-test-platform-android-test-plugin-result-listener-gradle 이 4.5.6 을 물고 있었다. 전 모듈에 걸쳐 있다.

3. ch.qos.logback:logback-core 1.3.16 — GHSA-jhq6-gfmj-v8fx / GHSA-p47f-322f-whfh / GHSA-qqpg-mvqg-649v (low ×3)

전 모듈의 ktlint configuration 에서만 나온다. ktlint CLI 의 로깅 구현체다. logback-classic 은 core 와 버전이 같아야 동작하므로 함께 올렸다.

4. mock-cleanup-check.yml — actions/missing-workflow-permissions (medium)

워크플로 18종 중 permissions: 블록이 없는 유일한 파일이라 토큰이 기본 권한 전체를 받고 있었다. contents: read 를 단다. (#847 후속인 #1039 가 같은 파일의 actions/checkout SHA 고정을 하지만 permissions: 는 건드리지 않아 이 지적은 남아 있었다.)

범위 밖으로 둔 44건

건 사유
netty 39건 #1058 / #1060 이 처리 중. 실측상 취약 버전(4.1.93·4.1.110) 출처가 unified-test-platform-core 와 unified-test-platform-android-test-plugin-host-emulator-control 뿐이라 #1060 범위와 정확히 일치한다. 이 PR 리졸브에서도 의도대로 그대로 남아 있다.
kotlin-gradle-plugin 1건 #986. 패치가 2.4.20-Beta1 베타뿐이라 지금 올릴 수 없다.
CodeQL insecure-local-authentication 2건 Keystore CryptoObject 도입 + 키 무효화 처리 + 모듈 분담이 얽힌 설계 변경이라 #1073 으로 뗐다.

검증

전부 로컬 실측(worktree 격리, base ec30bafd9).

리졸브 재실측 — 수정 전후 동일 조건 전수 리졸브 비교:

대상 전 후
okio 2.8.0 + 3.17.0 혼재 3.17.0 단일
okhttp / logging-interceptor 4.9.2 잔존 4.x 0건
logback-core / -classic 1.3.16 1.5.34
httpclient 4.5.6 + 4.5.14 혼재 4.5.14 단일
netty 4.1.93 / 4.1.110 잔존 그대로 (#1060 몫)

빌드

  • ktlintCheck + compileDebugUnitTestKotlin + compileDebugAndroidTestKotlin + compileReleaseKotlin → BUILD SUCCESSFUL (exit 0). logback 을 1.3→1.5 로 올리므로 ktlint 실동작 확인이 이번 변경의 핵심 리스크였다.
  • CI 게이트와 동일한 :koverXmlReportCi :konsist:test :build-logic:test → BUILD SUCCESSFUL, 실패 0건.
  • build-logic 은 별도 빌드라 자체 constraint 를 두지만, 그 클래스패스엔 이 4종이 0건이라 추가 선언이 필요 없음을 실측 확인했다.

시각 검증 — 시각 변경 없음(빌드 스크립트·버전 카탈로그·워크플로만). screenshotTest baseline 사이클 skip.

리뷰어에게

  • okhttp 정렬이 코드에 미치는 영향은 없다. okhttp3/okio 를 직접 import 하는 모듈은 core:data·core:network·feature/{afternote,receiver,timeletter}:data 뿐이고 전부 이미 카탈로그 5.4.0 을 쓰던 곳이다. 이번에 컴파일 클래스패스가 바뀐 onboarding·setting presentation 은 okhttp API 를 직접 쓰지 않는다.
  • build.gradle.kts 상단 주석의 "여기 목록은 전부 빌드 도구 경유라 APK 산출물에는 없다" 는 okhttp 가 들어오며 더는 참이 아니라 함께 고쳤다.
  • fix(build): netty 보안 하한을 AGP UTP 설정까지 확장 — 릴리스 PR dependency-review high 8건 해소 (closes 1058) [base: develop] #1060 과 같은 securityFloors 목록을 건드린다. 텍스트 충돌은 없지만 병합 순서에 따라 리베이스가 필요할 수 있다.

…한과 워크플로 permissions

Security 탭 미해결 48건(코드 스캐닝 3 + Dependabot 45)을 전수 분류해, 다른 PR·
이슈가 다루지 않는 4건만 처리한다. 경로가 전부 settings.gradle.kts 로 뭉개져
보여 전 프로젝트 전 resolvable configuration 을 실측했다(develop ec30baf,
수집 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 으로 뗀다.
@1hyok

1hyok commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator Author

#1060 과 충돌 예고 — 병합 순서 안내

#1060 과 이 PR 은 build.gradle.kts 를 함께 건드려 나중에 머지되는 쪽이 리베이스해야 한다. 지금은 둘 다 mergeable=MERGEABLE / CLEAN 이라 머지 카드에는 아무 표시가 없다 — GitHub 은 base 와의 충돌만 계산하고 열린 PR 끼리의 충돌은 보지 않기 때문이다. 미리 적어 둔다.

실측

develop → #1060(fix/1058) → 이 PR 순서로 순차 머지해 확인했다.

1단계: develop + #1060 머지 OK
2단계: CONFLICT (content): Merge conflict in build.gradle.kts

충돌 hunk 는 1개, 그것도 securityFloors 위 설명 주석 블록 하나뿐이다. constraint 코드는 자동 머지된다 — #1060 은 netty 블록을 bouncycastle 뒤에, 이 PR 은 httpclient/logback/okhttp 를 jdom2 뒤에 넣어 삽입 위치가 겹치지 않는다.

주석이 부딪히는 이유는 두 PR 이 같은 문장의 서로 다른 부분을 각자 고쳤기 때문이다.

양쪽 정보를 합치면 되고 버릴 내용은 없다.

해소안

충돌 블록을 통째로 아래로 교체하면 된다.

// 클래스패스의 보안 하한(#921·#975~#985·#1058·#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)·AGP UTP 설정(netty — unified-test-platform-core
// 가 4.1.93, -host-emulator-control 이 4.1.110)·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·UTP 처럼 AGP 가
// 뒤늦게 만드는 configuration 까지 잡도록 configureEach 로 걸고, require 시맨틱이라 상류가 하한 이상을
// 선언하게 되면 그쪽이 이긴다. okhttp 를 뺀 나머지는 빌드 도구 경유라 APK 산출물에는 없다
// (releaseRuntimeClasspath 실측). build-logic 은 별도 빌드라 build-logic/build.gradle.kts 가 같은
// 하한을 선언한다.

합친 상태 검증

위 해소안을 적용한 상태로 실측했다.

  • 전수 리졸브 — 두 PR 대상 취약 버전이 전부 0건: netty 4.1.137.Final 단일 · okio 3.17.0 · okhttp 5.4.0 · logback 1.5.34 · httpclient 4.5.14. 둘이 합쳐지면 Dependabot 45건 중 KGP 1건(fix(build): Kotlin Gradle Plugin 보안 권고 대응 필요 #986, 패치가 베타뿐)만 남는다.
  • ktlintCheck + compileDebugUnitTestKotlin + compileDebugAndroidTestKotlin → BUILD SUCCESSFUL
  • 합본 securityFloors 목록에 중복 항목 없음

참고

충돌이 실제로 발생하면 #1046 이 열어 둔 conflict-label 워크플로가 develop push 직후 conflict 라벨과 안내 코멘트를 자동으로 붙인다. 다만 그때는 이미 pull_request CI 가 트리거되지 않는 상태(#1028)이므로, 위 해소안으로 바로 풀면 검증이 다시 돈다.

@1hyok
1hyok requested review from Sadturtleman and koongmai August 24, 2026 15:52
@github-actions github-actions Bot added the conflict base 와 충돌 — CI 가 트리거되지 않는다. base 를 병합하면 자동으로 떨어진다 label Aug 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

이 PR 은 develop 와 충돌 상태이고, 그래서 CI 가 돌지 않는다.

pull_request 워크플로는 base 와 head 를 합친 가상 머지 커밋(refs/pull/<N>/merge)에서
실행되는데, 충돌이면 GitHub 이 그 ref 를 만들지 못해 워크플로가 트리거조차 되지 않는다.
체크가 실패하는 것이 아니라 아예 생성되지 않으므로, 새 커밋을 올려도 no checks reported
인 채 최신 커밋이 한 번도 검증되지 않은 상태로 남는다 (#1028).

develop 를 병합해 충돌을 풀면 검증이 다시 돈다. 해소되면 이 라벨은 자동으로 떨어진다.

@1hyok
1hyok merged commit 9897666 into develop Aug 25, 2026
13 checks passed
@1hyok
1hyok deleted the security/1072 branch August 25, 2026 04:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

conflict base 와 충돌 — CI 가 트리거되지 않는다. base 를 병합하면 자동으로 떨어진다

Projects

None yet

2 participants