Priority: P1
Context
Ten open Dependabot alerts (#35–#44) name io.netty:netty-codec, netty-codec-http, and netty-codec-http2.
This is the third wave of the same recurring finding (#2–#28 → #151, #29–#32 → #264/PR #265). The mechanism is unchanged and is documented in CLAUDE.md: AGP's Unified Test Platform pulls io.grpc:grpc-netty → io.netty onto two :app project configurations (unified-test-platform-core, unified-test-platform-android-test-plugin-host-emulator-control), and GitHub's Automatic Dependency Submission surfaces it.
The existing pin is not broken — its target went bad. app/build.gradle.kts:308-318 still resolves every UTP netty path 4.1.93/4.1.110 → 4.1.135.Final exactly as designed. Ten advisories published 2026-07-22 / 07-31 moved the vulnerable range up to and including 4.1.135.Final.
Correction worth recording
manifest_path = "settings.gradle.kts" on these alerts is a constant, information-free label that Automatic Dependency Submission stamps on the entire force-resolved graph. It does not mean the settings/plugin classpath — GraphQL reports settings.gradle.kts dependenciesCount: 0, i.e. nothing is parsed from that file at all. Every Maven alert this repo has ever had carries the same label. Do not read it as a classpath hint.
Evidence
Impact
No user-facing impact — netty is absent from every shipped classpath. The cost is a permanently noisy alert surface, which erodes the value of the gate (the reasoning already recorded in app/build.gradle.kts:277-283).
Proposed fix
app/build.gradle.kts:311 — one token:
- useVersion("4.1.135.Final")
+ useVersion("4.1.137.Final")
The startsWith("4.1.") guard on line 310 still matches; no structural change.
⚠️ The target must be 4.1.137.Final, NOT 4.1.136.Final
All ten alerts declare first_patched_version = 4.1.136.Final. That is already stale: GHSA-8c42-7qj2-3j46 (published 2026-08-17) covers io.netty:netty-codec-http <= 4.1.136.Final, fixed in 4.1.137.Final.
Pinning 4.1.136 would close ten alerts and open an eleventh. Verified clean: gh api '/advisories?ecosystem=maven&affects=io.netty:<module>@4.1.137.Final' returns 0 for netty-codec, -codec-http, -codec-http2, -handler, -common, -codec-socks, -handler-proxy, -transport.
That same advisory also covers the currently-resolved 4.1.135.Final, so an 11th netty alert may appear before this lands — expected, not a regression. Landing 4.1.137 pre-empts it.
Also refresh the comment block (app/build.gradle.kts:291-307)
It currently cites only the wave-1 CVEs and "≤ 4.1.134.Final". Update the wave narrative, list the wave-2 GHSA ids (-6jqx-86gh-f27w, -mvh2-crg5-v77c, -jppx-w49h-x2qq, -6cqp-g7gg-8hr5, -4mp9-239f-g9hg, -q4f6-jm68-57ww, -c69g-56f8-xwqj, -558v-64gr-wgg4, -gcjf-9mgh-3p7g, -93wv-jw9v-4972), note that 4.1.136 is already vulnerable, and change the drop-condition on line 302 to > 4.1.137.Final.
Acceptance criteria
Stop rule
If any of #35–#44 is still open ~24 h after merge and a dependency-submission run has succeeded on develop, that is the stale-snapshot / orphaned-correlator failure mode — do not re-engineer the pin; dismiss as tolerable_risk instead.
Do not dismiss #35–#44 before merging. A dismissal destroys the observation that proves the pin worked.
Related: #151, #264, PR #265. Consider landing together with the BouncyCastle fix as one PR.
Priority: P1
Context
Ten open Dependabot alerts (#35–#44) name
io.netty:netty-codec,netty-codec-http, andnetty-codec-http2.This is the third wave of the same recurring finding (#2–#28 → #151, #29–#32 → #264/PR #265). The mechanism is unchanged and is documented in
CLAUDE.md: AGP's Unified Test Platform pullsio.grpc:grpc-netty→io.nettyonto two:appproject configurations (unified-test-platform-core,unified-test-platform-android-test-plugin-host-emulator-control), and GitHub's Automatic Dependency Submission surfaces it.The existing pin is not broken — its target went bad.
app/build.gradle.kts:308-318still resolves every UTP netty path4.1.93/4.1.110 → 4.1.135.Finalexactly as designed. Ten advisories published 2026-07-22 / 07-31 moved the vulnerable range up to and including 4.1.135.Final.Correction worth recording
manifest_path = "settings.gradle.kts"on these alerts is a constant, information-free label that Automatic Dependency Submission stamps on the entire force-resolved graph. It does not mean the settings/plugin classpath — GraphQL reportssettings.gradle.kts dependenciesCount: 0, i.e. nothing is parsed from that file at all. Every Maven alert this repo has ever had carries the same label. Do not read it as a classpath hint.Evidence
./gradlew :app:dependencies— every UTP coordinate resolves4.1.93.Final -> 4.1.135.Final/4.1.110.Final -> 4.1.135.Final; the pin is functioning.releaseRuntimeClasspath/debugRuntimeClasspath; zero netty inapp/gradle.lockfile. Build-time test tooling only — never ships in the APK.state: fixedat2026-06-15T13:00:13Z, 53 seconds after PR security(deps): pin AGP UTP Netty transitive to patched 4.1.135.Final #265 merged at12:59:20Z.Impact
No user-facing impact — netty is absent from every shipped classpath. The cost is a permanently noisy alert surface, which erodes the value of the gate (the reasoning already recorded in
app/build.gradle.kts:277-283).Proposed fix
app/build.gradle.kts:311— one token:The
startsWith("4.1.")guard on line 310 still matches; no structural change.All ten alerts declare
first_patched_version = 4.1.136.Final. That is already stale:GHSA-8c42-7qj2-3j46(published 2026-08-17) coversio.netty:netty-codec-http <= 4.1.136.Final, fixed in4.1.137.Final.Pinning 4.1.136 would close ten alerts and open an eleventh. Verified clean:
gh api '/advisories?ecosystem=maven&affects=io.netty:<module>@4.1.137.Final'returns 0 fornetty-codec,-codec-http,-codec-http2,-handler,-common,-codec-socks,-handler-proxy,-transport.That same advisory also covers the currently-resolved 4.1.135.Final, so an 11th netty alert may appear before this lands — expected, not a regression. Landing 4.1.137 pre-empts it.
Also refresh the comment block (
app/build.gradle.kts:291-307)It currently cites only the wave-1 CVEs and "≤ 4.1.134.Final". Update the wave narrative, list the wave-2 GHSA ids (
-6jqx-86gh-f27w,-mvh2-crg5-v77c,-jppx-w49h-x2qq,-6cqp-g7gg-8hr5,-4mp9-239f-g9hg,-q4f6-jm68-57ww,-c69g-56f8-xwqj,-558v-64gr-wgg4,-gcjf-9mgh-3p7g,-93wv-jw9v-4972), note that 4.1.136 is already vulnerable, and change the drop-condition on line 302 to> 4.1.137.Final.Acceptance criteria
./gradlew -q :app:dependencies | grep -i 'io\.netty' | grep -v '4\.1\.137'produces no output./gradlew :app:dependencies --write-locksleavesapp/gradle.lockfileandsettings-gradle.lockfilebyte-identical (git diff --statempty) — proves nothing shipped changedbuild+androidTestchecks green (androidTestis the gate that actually exercises UTP)state: fixedafter merge todevelopStop rule
If any of #35–#44 is still open ~24 h after merge and a dependency-submission run has succeeded on
develop, that is the stale-snapshot / orphaned-correlator failure mode — do not re-engineer the pin; dismiss astolerable_riskinstead.Related: #151, #264, PR #265. Consider landing together with the BouncyCastle fix as one PR.