Audits 12 vectors with hard evidence, scores findings via a weighted matrix, and executes the single highest-value/lowest-risk first step — then verifies it green.
Target repository:
android-monorepo(~/Desktop/workspace/android-monorepo). A large production Android (Kotlin/Gradle, ~41 modules) + Flutter add-to-app monorepo. Scanned across the 12 vectors; every finding is evidence-backed. The #1 item was executed in the working tree and verified with a real green./gradlewrun. Date: 2026-06-17.Repo-safety note: the executed change is a single safe line left uncommitted in the working tree for review via the team's normal MR process — it was not committed or pushed to the production repo. This A4 record is saved in the Task_Eval
Advanced/repo-modernization/folder as requested. Build depth: a full Gradle/Android build was not run (Android SDK toolchain) — so the chosen first step was deliberately one verifiable without a full build (the Gradle wrapper bootstrap).
distributionSha256Sum (supply-chain integrity for the build toolchain).gradle/wrapper/gradle-wrapper.propertiesgradle-8.12-all.zip over the network with no integrity
verification (verified: no distributionSha256Sum line) — a real supply-chain risk (a tampered
or MITM'd distribution would execute with full build privileges on every developer/CI machine).
This is the top of the matrix (PS 4.4): highest Business Value (security, 5), one-line
additive change (Complexity 5), and completely safe (Risk 5) because the pinned hash was
proven to equal BOTH the locally-cached distribution the repo already uses AND Gradle's official
published checksum — so it cannot break the build. It is also one of the few high-value items
verifiable here without the Android SDK, via ./gradlew --version (bootstraps + checksum-verifies
the distribution, no project build).gradle/wrapper/gradle-wrapper.properties (lines 1–6, pre-change)distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
# $ grep distributionSha256Sum gradle-wrapper.properties -> (no match) NO checksum verification
./gradlew invocation (dev + CI) downloads and executes a Gradle distribution
with no integrity check. A compromised mirror / MITM / corrupted download runs arbitrary code in
the build. Industry best practice (and Gradle's own guidance) is to pin distributionSha256Sum.:base_app only (coverage gap)bitbucket-pipelines.yml (Unit Tests step) and .gitlab-ci.yml (test job)bitbucket-pipelines.yml:713 ./gradlew -Pci :base_app:testProductionDebugUnitTest --no-daemon
.gitlab-ci.yml:118 ./gradlew -Pci testDevelopmentDebugUnitTest
# equity_sdk (~303 unit tests) and Flutter pml-flutter (~212) are NOT executed by the Bitbucket job
:equity_sdk / Flutter land undetected. Two CI systems (GitLab + Bitbucket) also duplicate config.-all distributiongradle/wrapper/gradle-wrapper.properties:4distributionUrl=...gradle-8.12-all.zip # "-all" = binaries + sources + docs (~2x size)
-all downloads sources+docs that builds/CI don't need; -bin is the recommended
default and roughly halves the wrapper download/cold-CI time. (Left for a follow-up because it
changes the distribution and warrants a CI download re-verify.)gradle/libs.versions.toml (MISSING); versions live in a versions map in build.gradle$ ls gradle/libs.versions.toml -> MISSING
build.gradle:216 'androidToolPlugin' : "com.android.tools.build:gradle:${versions.androidPlugin}"
libs.versions.toml. (High effort — flagged, not executed.).pre-commit-config.yaml (MISSING)$ [ -f .pre-commit-config.yaml ] && echo PRESENT || echo MISSING -> MISSINGVectors scanned and found healthy (no finding):
.editorconfigPRESENT,.gitattributesPRESENT, rootREADME.mdPRESENT, detekt configured (detekt.gradle→default-detekt-config.ymlPRESENT, 23 KB), ktlint configured (ktlint.gradle). This is a relatively mature repo — the gaps are in build-supply-chain integrity and CI coverage, not basic hygiene.
PS = (BV × 0.3) + (EV × 0.3) + (R × 0.2) + (CE × 0.2) — R & CE: higher = safer / easier.
| ID | Finding Description | BV | EV | R | CE | Priority Score |
|---|---|---|---|---|---|---|
| 1 | F1 Pin Gradle distribution via distributionSha256Sum | 5 | 3 | 5 | 5 | 4.4 |
| 2 | F2 Extend CI to run equity_sdk + Flutter unit tests | 4 | 4 | 3 | 2 | 3.4 |
| 3 | F3 Switch wrapper -all → -bin (faster cold builds) | 2 | 3 | 4 | 5 | 3.3 |
| 4 | F5 Add .pre-commit-config.yaml (detekt/ktlint on commit) | 2 | 3 | 5 | 4 | 3.3 |
| 5 | F4 Migrate dependency versions to libs.versions.toml | 3 | 4 | 3 | 1 | 2.9 |
Sorted descending by PS. Executed: #1 (F1).
grep distributionSha256Sum gradle/wrapper/gradle-wrapper.properties$ grep distributionSha256Sum gradle/wrapper/gradle-wrapper.properties
# (no output — line absent; no integrity verification)
$ shasum -a 256 ~/.gradle/wrapper/dists/gradle-8.12-all/ejduaidbjup3bmmkhw3rie4zb/gradle-8.12-all.zip
7ebdac923867a3cec0098302416d1e3c6c0c729fc4e2e05c10637a8af33a76c5 (the repo's cached distribution)
$ curl -sL https://services.gradle.org/distributions/gradle-8.12-all.zip.sha256
7ebdac923867a3cec0098302416d1e3c6c0c729fc4e2e05c10637a8af33a76c5 (Gradle's official published hash)
# MATCH ✓ -> the pinned value is authoritative and cannot break the build.
gradle/wrapper/gradle-wrapper.properties (one added line) distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip
+distributionSha256Sum=7ebdac923867a3cec0098302416d1e3c6c0c729fc4e2e05c10637a8af33a76c5
zipStoreBase=GRADLE_USER_HOME
./gradlew --version$ ./gradlew --version
Gradle 8.12
Kotlin: 2.0.21
Launcher JVM: 17.0.18 (Homebrew 17.0.18+0)
100% green. With distributionSha256Sum set, the wrapper recomputes the SHA-256 of the
distribution and compares it before use. The successful Gradle 8.12 banner means the integrity
check passed. (Negative-test logic: a mismatched hash makes Gradle abort with
Verification of Gradle distribution failed! and a non-zero exit — so a green version banner is
proof the check is active and satisfied.) No project build was run; no application code touched.
gradle/wrapper/gradle-wrapper.properties (one line added; uncommitted)git -C android-monorepo checkout -- gradle/wrapper/gradle-wrapper.properties
(or, once committed via MR, git revert <commit_hash>)../gradlew now verifies the distribution checksum. Because the pinned hash equals
the official + the already-cached distribution, every existing dev/CI machine continues to work
unchanged. The single realistic failure mode — a future Gradle version bump without updating
this hash — fails fast and loudly at wrapper bootstrap (not in prod; there is no prod runtime
impact, this is build-time only) with a clear "Verification ... failed" message. Mitigation: update
the hash in the same commit that bumps distributionUrl (and gradle-wrapper-validation CI action
as a follow-up).distributionSha256Sum), the matrix scores, and
the single-line change.shasum of the
repo's actual cached zip and Gradle's official published .sha256) and confirmed they MATCH,
so the pin is provably safe rather than a guess that could brick the build../gradlew --version and captured the real green output proving the checksum is enforced
and satisfied — not asserted.distributionSha256Sum pin) in the working tree../gradlew --version → Gradle 8.12).