# `MobDev.KotlinGradlePlugin`
[🔗](https://github.com/genericjam/mob_dev/blob/master/lib/mob_dev/kotlin_gradle_plugin.ex#L1)

Detects an Android build still on a Kotlin Gradle plugin (KGP) below 2.4.20,
which has CVE-2026-53914 (GHSA-r937-wjx7-w2jp): code execution through
unsafe deserialization of Gradle build-cache metadata (MOB-497).

Apps generated by mob_new before its Kotlin 2 migration pin
`org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.22`. The Gradle files are
app-owned, so `mix mob.doctor` reports and never rewrites them (see
`decisions/2026-08-25-detect-dont-autopatch-native-source.md`).

Read from the root, settings and app build scripts (Groovy or Kotlin DSL)
and `gradle/libs.versions.toml`:

  * the `org.jetbrains.kotlin:kotlin-gradle-plugin` coordinate, or
    `org.jetbrains.kotlin:compose-compiler-gradle-plugin` (whose POM
    requires KGP at the same version), with a literal version, a `$var`
    resolved from an assignment in the same file, or a
    `strictly`/`require`/`prefer` block;
  * the plugin ids that resolve to KGP or pin it (`org.jetbrains.kotlin.`
    `android`, `jvm`, `multiplatform`, `kapt`, `js`, `native.cocoapods`,
    `android.extensions`, `plugin.compose`, `plugin.parcelize`, and the
    `kotlin("…")` shorthand) with a version;
  * catalog `[libraries]` and `[plugins]` entries for any of them, with
    `version = "…"` or `version.ref` resolved through `[versions]`.

Only those count. Other Kotlin plugins (serialization), look-alike
artifacts (`kotlin-gradle-plugin-api`), a `kotlin` catalog key that
nothing above references, and commented-out lines are ignored. A version
that can't be resolved to a literal (`version kotlinVersion`, an unknown
`$var`) still declares KGP but is never guessed: doctor only warns, so a
false positive would tell a fixed app it is still exposed every time it
runs.

AGP 9 compiles Kotlin itself and depends on KGP 2.2.10 at runtime, so an
AGP 9 build that declares no KGP at all is on 2.2.10 and is reported too.

# `finding`

```elixir
@type finding() ::
  {:vulnerable, Path.t(), [String.t()]}
  | {:builtin_kotlin_unpinned, Path.t(), String.t()}
```

A reason to warn, with the project-relative file it was read from.

# `below_fix?`

```elixir
@spec below_fix?(String.t()) :: boolean()
```

True when `version` is a parseable version below the CVE-2026-53914 fix.

# `check`

```elixir
@spec check(Path.t()) :: [finding()]
```

The findings for the Android project under `root`, sorted by file. `[]`
when every declared KGP is at or above 2.4.20 (or there is no Android
build to read).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
