Skip to content

fix(build): Kotlin Gradle Plugin 보안 권고 대응 필요 #986

Closed

Description

@github-actions

📜 Overview (Required)

OSV가 현재 해석된 org.jetbrains.kotlin:kotlin-gradle-plugin 2.4.0에서 보안 권고를 반환했습니다.

영향 범위와 수정 버전을 확인하고 안전한 버전으로 올려야 합니다.

📌 Child Issue(Optional)

No response

📍 Note (Optional)

No response

Activity

  1. OnlyReadOneBook commented on Aug 24, 2026

    @OnlyReadOneBook
    Collaborator

    대응 보류 — 정식 패치판 부재 + 공격면 닫힘

    #1003 에서 나머지 감사 이슈를 처리하면서 이 건은 의도적으로 채택하지 않았다. 근거는 아래 셋이다.

    1. 정식 패치판이 없다. GHSA-r937-wjx7-w2jp 의 fixed 는 2.4.20-Beta1 이고, Maven Central 의 kotlin-gradle-plugin 은 현재 정식이 2.4.10 까지다(그 위는 2.4.20-Beta1·Beta2·RC). 즉 이 권고를 해소하려면 프로덕션 빌드 툴체인을 Beta/RC 로 올려야 한다.

    2. 이 레포에는 공격면이 닫혀 있다. 취약점은 Unsafe Deserialization in Kotlin Build Cache인데, gradle.properties:33 이 org.gradle.caching=false 다.

    3. 난이도·전제가 높다. CVSS AV:L/AC:H/PR:H/UI:N — 로컬 접근·높은 공격 난이도·높은 권한이 모두 필요하다.

    Beta 툴체인 채택의 회귀 위험이 위 조건에서의 실질 위험보다 크다고 판단했다. Kotlin 2.4.20 정식 출시 시 이 이슈로 대응한다 (그때는 카탈로그 kotlin 버전 상향 한 건이다).

    관련: 같은 감사 회차의 #973·#974·#975~#982·#985 는 #1003, #983·#984(bouncycastle)는 #922 가 처리한다.

  2. OnlyReadOneBook commented on Aug 25, 2026

    @OnlyReadOneBook
    Collaborator

    재확인 2026-08-26 — 보류 유지, 다만 앞선 근거 하나를 정정한다

    1. 정식 패치판은 아직 없다 (변화 없음)

    kotlin-gradle-plugin 의 maven-metadata.xml 실측:

    <release>2.4.20-RC</release>
    <lastUpdated>20260812082909</lastUpdated>
    

    버전 목록 끝은 2.4.20-Beta1 · 2.4.20-Beta2 · 2.4.20-RC 이고 정식 2.4.20 은 없다. 정식 최신은 여전히 2.4.10, 카탈로그는 2.4.0 인데 GHSA-r937-wjx7-w2jp 의 affected 는 introduced: 0 → fixed: 2.4.20-Beta1 이라 정식판 안에서는 올릴 곳이 없다. 8/23 판단의 이 축은 그대로다.

    2. 정정 — "공격면이 닫혀 있다" 는 CI 에서 틀렸다

    위 코멘트 근거 2번에서 gradle.properties:33 의 org.gradle.caching=false 를 들어 build cache 가 꺼져 있다고 썼다. 그건 로컬 기본값 얘기일 뿐이다. CI 는 #996 에서 --build-cache 를 켰다.

    자리 명령
    .github/workflows/lint.yml:48 ./gradlew ktlintCheck --continue --parallel --build-cache
    .github/workflows/lint.yml:80 ./gradlew lintDebug --continue --parallel --build-cache
    .github/workflows/unit-test.yml:61 ./gradlew :koverXmlReportCi … --build-cache
    .github/workflows/screenshot.yml:65 … --parallel --build-cache
    .github/workflows/build-cache-warm.yml:72 --build-cache

    즉 러너에서 Kotlin Build Cache 는 활성이고, 그 전제 위에서 다시 판단해야 한다.

    3. 재평가 — 그럼에도 보류가 맞다 (근거를 실측으로 갈아끼운다)

    엔트리를 심으려면 이미 저장소 쓰기 권한이 필요하다. PR 검증 워크플로는 전부 cache-read-only: true 라 아무도 캐시를 채우지 못한다 — lint.yml:35·lint.yml:73, unit-test.yml:54, screenshot.yml:48, codeql.yml:61, android-managed-device.yml:36, dependency-submission.yml:79. 채우는 자리는 cache-read-only: false 인 셋뿐이고(build-cache-warm.yml:46, firebase-wif-canary.yml:93, release-distribution.yml:69) 전부 develop push 또는 승인된 배포 경로다. fork PR 은 애초에 캐시 쓰기가 불가능하다. CVSS 의 PR:H 가 가리키는 전제와 정확히 겹친다.

    테스터에게 나가는 산출물은 이 경로 밖이다. release-distribution.yml 은 --build-cache 를 쓰지 않는다 — 릴리스 APK 를 만드는 빌드는 build cache 엔트리를 읽지 않는다.

    난이도 전제는 그대로다. AV:L/AC:H/PR:H/UI:N — 로컬 접근·높은 공격 난이도·높은 권한이 모두 필요하다.

    프로덕션 빌드 툴체인 전체를 RC 로 올리는 회귀 위험이 위 조건에서의 실질 위험보다 여전히 크다.

    결론

    보류 유지. 정식 2.4.20 출시 시 이 이슈로 대응한다 — 그때는 카탈로그 kotlin 버전 한 줄이다. 이번 재확인으로 바뀐 것은 판단이 아니라 그 판단을 떠받치는 근거다.

  3. added
    dependency-audit의존성 감사가 발행·추적하는 이슈 — 닫으면 «이번 회차 대응 보류» 판정으로 존중된다
    on Aug 25, 2026
  4. OnlyReadOneBook commented on Aug 25, 2026

    @OnlyReadOneBook
    Collaborator

    보류가 판정인 이상 열어 둘 이유가 없어 닫는다

    바로 위 재확인으로 «정식 2.4.20 이 나올 때까지 대응하지 않는다» 가 확정 판정이 됐다. 그런데도 이 이슈가 열려 있으면 열린 목록이 «지금 해야 할 일» 을 뜻하지 못하고, 볼 때마다 착수 대상으로 다시 판단하게 된다.

    그동안 닫지 못한 건 감사 자동화 때문이었다 — publish-dependency-audit-issues.mjs 가 state=open 만 조회해서, 닫으면 다음 회차(매주 월요일 06:17 KST)에 같은 권고가 새 번호로 부활하고 위 판정 근거도 따라오지 않는다.

    그 구멍을 #1191 / #1192 에서 메웠다. 이제 닫힌 감사 이슈는 «이번 회차 대응 보류» 판정으로 존중되고, 상황이 바뀌었을 때만 자동으로 다시 열린다. 이 이슈에 dependency-audit 라벨을 단 것이 그 추적 열쇠다.

    다시 열리는 조건

    감사는 fingerprint({key, 해석된 버전, 취약점 목록} 해시)로 판단한다.

    • 자동으로 다시 열린다 — 카탈로그 kotlin 이 다른 버전으로 바뀌었는데 여전히 권고 범위 안이거나, 이 좌표에 새 취약점이 추가된 경우.
    • 자동으로 열리지 않는다 — 정식 2.4.20 출시 그 자체. 카탈로그가 2.4.0 인 채로 있으면 해석 버전도 취약점 목록도 그대로라 fingerprint 가 바뀌지 않는다. 정식판이 나왔는지는 여전히 사람이 확인해야 한다.

    두 번째 항목이 남은 구멍이라는 걸 알고 닫는다. 정식 2.4.20 확인 뒤에는 이 이슈를 다시 열고 카탈로그 한 줄로 끝내면 된다.

  5. github-actions commented on Aug 30, 2026

    @github-actions
    ContributorAuthor

    주간 의존성 재검사

    OSV가 현재 해석된 org.jetbrains.kotlin:kotlin-gradle-plugin 2.4.10에서 보안 권고를 반환했습니다.

    영향 범위와 수정 버전을 확인하고 안전한 버전으로 올려야 합니다.

  6. added
    pr-open이 이슈를 구현하는 PR 이 열려 있다 — base 가 기본 브랜치가 아니어도 드러낸다
    on Aug 31, 2026
  7. OnlyReadOneBook commented on Aug 31, 2026

    @OnlyReadOneBook
    Collaborator

    재확인 2026-08-31 — 보류 유지. 다만 이번엔 «다음에 깨우는 일» 을 사람 손에서 뗀다

    0. 이 이슈가 다시 열린 이유는 상황 변화가 아니다

    8/30 감사 회차가 이 이슈를 자동으로 다시 열었다. 근거는 fingerprint 변화인데, 바뀐 것은 해석 버전뿐이다 — 2.4.0 → 2.4.10. 8/25 에 적어 둔 「자동으로 다시 열린다 — 카탈로그 kotlin 이 다른 버전으로 바뀌었는데 여전히 권고 범위 안」 조건에 정확히 걸린 것이고, 권고 자체는 그대로 미해소다.

    1. 정식 패치판은 여전히 없다

    kotlin-gradle-plugin maven-metadata.xml 실측:

    <release>2.4.20-RC2</release>
    <lastUpdated>20260826075222</lastUpdated>
    

    fixed: 2.4.20-Beta1 이상인 버전은 2.4.20-Beta1 · 2.4.20-Beta2 · 2.4.20-RC · 2.4.20-RC2 넷뿐이고 전부 프리릴리스다. 정식 최신은 2.4.10 으로, 이미 카탈로그가 쓰는 값이다. 8/25 대비 늘어난 것은 RC2 하나뿐 — 정식판은 나오지 않았다.

    2. 공격면 판단도 그대로다 (8/25 정정본 유지)

    PR 검증 job 은 전부 cache-read-only: true 이고 캐시를 채우는 자리는 develop push·승인된 배포 경로뿐이다. 이 단일 writer 구조는 build-cache-policy.test.mjs 가 고정하고 있다(exactly one workflow may write the shared Gradle User Home cache). 릴리스 APK 빌드는 --build-cache 를 쓰지 않는다. CVSS AV:L/AC:H/PR:H/UI:N 의 전제와 겹친다.

    결론: 보류 유지. 프로덕션 툴체인을 RC 로 올리는 회귀 위험이 위 조건에서의 실질 위험보다 여전히 크다.

    3. 이번에 실제로 고친 것 — 8/25 에 남겨 둔 구멍

    닫으면서 이렇게 적어 뒀다.

    자동으로 열리지 않는다 — 정식 2.4.20 출시 그 자체. (…) 정식판이 나왔는지는 여전히 사람이 확인해야 한다.
    두 번째 항목이 남은 구멍이라는 걸 알고 닫는다.

    원인은 두 겹이었다.

    1. queryOsv 가 쓰는 OSV querybatch 응답에는 fixed 가 없다 — 취약점 id 와 modified 뿐이라 감사는 패치 버전을 애초에 알지 못했다.
    2. security fingerprint 는 {key, 해석 버전, 취약점 목록} 만 본다. 정식판 출시는 이 셋 중 아무것도 바꾸지 않는다.

    #1663 이 둘 다 메운다. 권고 상세(/v1/vulns/{id})의 fixed 이벤트를 읽고 그 좌표가 실제로 배포한 버전 목록과 대조해 «fixed 이상인 stable 중 가장 낮은 것» 을 찾는다. 그 값을 fingerprint 에 싣되, 없을 때는 필드를 아예 빼서 직렬화 결과를 종전과 같게 유지한다 — 이 변경만으로 해시가 흔들리면 보류해 둔 이슈가 아무 상황 변화 없이 깨어나 #1191 이 세운 「닫힌 감사 이슈 = 보류 판정」이 무너지기 때문이다. 회귀 테스트가 그 바이트 동일성을 못 박고 있다.

    실 API 에 물려 본 결과:

    firstPatched    : 2.4.20-Beta1
    latestStable    : 2.4.10
    stableFixVersion: null
    => 판정          : 정식 패치판 없음 — 보류가 맞다
    

    4. 다시 열리는 조건 — 이제 셋 다 자동이다

    5. 닫는 시점

    #1663 이 머지된 뒤에 닫는다. 보류가 판정인 이상 열어 둘 이유가 없다는 8/25 판단은 그대로지만, 지금 닫으면 정식판 출시를 깨워 줄 장치가 아직 develop 에 없다. 머지가 그 순서를 결정한다 — 그래서 #1663 은 Closes 가 아니라 Refs 로 걸어 뒀다.

  8. removed
    pr-open이 이슈를 구현하는 PR 이 열려 있다 — base 가 기본 브랜치가 아니어도 드러낸다
    on Aug 31, 2026
  9. OnlyReadOneBook commented on Aug 31, 2026

    @OnlyReadOneBook
    Collaborator

    보류로 닫는다 — 다음에 깨우는 장치가 develop 에 들어갔다

    앞선 코멘트에서 「#1663 이 머지된 뒤에 닫는다」로 순서를 잡아 뒀고, 그 PR 이 방금 머지됐다(a96dfe1).

    이제 감사가 권고 상세(/v1/vulns/{id})의 fixed 를 실제 릴리스 목록과 대조해 정식 패치판 유무를 판정하고 그 값을 fingerprint 에 싣는다. 정식판이 없는 동안에는 fingerprint 직렬화가 종전과 바이트 단위로 같아 닫아 둔 이 이슈가 깨어나지 않고, 2.4.20 정식이 배포되는 순간 키가 생겨 fingerprint 가 바뀌면서 감사가 이 이슈를 자동으로 다시 연다.

    보류 근거는 그대로다 — 패치 하한 2.4.20-Beta1 이상은 Beta1·Beta2·RC·RC2 넷뿐이고 전부 프리릴리스, 정식 최신은 카탈로그가 이미 쓰는 2.4.10 이다. 공격면(Kotlin Build Cache 역직렬화)은 로컬 org.gradle.caching=false 와 PR job 전량 cache-read-only: true 로 이미 닫혀 있고 그 구조를 build-cache-policy.test.mjs 가 고정한다.

    깨어나면 그때 프리릴리스 채택 여부가 아니라 정식판으로 올리는 판단을 하면 된다.

  10. github-actions commented on Sep 13, 2026

    @github-actions
    ContributorAuthor

    주간 의존성 재검사

    OSV가 현재 해석된 org.jetbrains.kotlin:kotlin-gradle-plugin 2.4.10에서 보안 권고를 반환했습니다.

    정식 패치판 2.4.20 이 배포돼 있습니다 — 카탈로그를 이 버전 이상으로 올리면 해소됩니다.

  11. added
    pr-open이 이슈를 구현하는 PR 이 열려 있다 — base 가 기본 브랜치가 아니어도 드러낸다
    on Sep 20, 2026
  12. removed
    pr-open이 이슈를 구현하는 PR 이 열려 있다 — base 가 기본 브랜치가 아니어도 드러낸다
    on Oct 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

area:platformCI·빌드·릴리스·저장소 운영 영역bugSomething isn't workingdependency-audit의존성 감사가 발행·추적하는 이슈 — 닫으면 «이번 회차 대응 보류» 판정으로 존중된다

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions