CodeVetter · Repo Unpack · Risk map
flutter/flutter
The biggest risk surface is the bootstrap supply chain: every fresh clone downloads and executes a Dart SDK and prebuilt engine artifacts over HTTPS, with host-overridable base URLs. Crash reporting and analytics exfiltrate command lines and stack traces (gated but present). Cross-platform shell logic is duplicated between .sh/.bat pairs that must be manually kept in sync. The locking scheme degrades to mkdir on NFS, and cache invalidation leans on file mtimes. The merged monorepo concentrates blast radius: .ci.yaml is ~7800 lines, DEPS pins a dozen external revisions, and 'isolated' files must not leak into google3 builds.
- Supply-chain: bin/internal/update_dart_sdk.sh downloads the Dart SDK from ${FLUTTER_STORAGE_BASE_URL:-https://storage.googleapis.com} at first run; cache.dart similarly downloads engine artifacts and CIPD packages from Google endpoints — a hostile mirror or MITM upstream would execute code on dev machines.
- Telemetry exfiltration: runner.dart sends analytics events and, on crashes, sends a report containing the full command line, exception type, stack trace, and flutter doctor output via CrashReportSender — suppressed on bots and for --local-engine runs but on by default.
- dev/bots/serviceaccount.enc is an encrypted service-account blob committed to the repo — a secrets-adjacent file whose decryption path lives in CI infrastructure.
- Duplicated bootstrap logic: bin/flutter, flutter.bat, shared.sh, and shared.bat carry mirrored logic and header comments explicitly warn to keep them consistent — drift between them is a recurring hazard.
- Upgrade locking degrades gracefully but unevenly: flock -> shlock -> mkdir fallback; flock errors are swallowed (NFS needs write fds), and the mkdir lock relies on atomic directory creation, so concurrent first-runs on exotic filesystems can race.
- Cache invalidation relies on pubspec.yaml-vs-pubspec.lock mtime comparison plus a hand-maintained compilekey (revision:FLUTTER_TOOL_ARGS); a NOP pub upgrade touches pubspec.lock (issue 171024 workaround) — subtle staleness bugs have occurred here.
- Hot restart correctness depends on a filename-swapping hack (.swap dill) because Windows embedders memory-map the previous dill — fragile coupling between tool behavior and embedder file semantics.
- google3 divergence: executable.main notes WebRunner/DevTools/mustache deps differ in google3 and files under lib/src/isolated are 'intentionally excluded from google3 tooling' — edits crossing that boundary break internal builds invisibly to OSS CI. (inferred)
- DEPS pins dart_revision, skia_revision, clang_version, reclient_version and more; comments warn that dart rolls must also update transitive deps via //tools/dart/create_updated_flutter_deps.py — manual edits produce skewed toolchains.
- .ci.yaml is ~7847 lines declaring hundreds of LUCI targets with pinned dependency versions (android_sdk 37v2, open_jdk 21, multiple gradle dists) — a single malformed property breaks scheduling across the fleet.
- The tool writes to shared mutable state in $FLUTTER_ROOT/bin/cache and only warns (with a paperclip) when run as root outside containers/CI — careless sudo usage corrupts the cache for the owning user.
- Error-handling depth: _handleToolErrorImpl nests a catch-all inside the crash-report path and deliberately throws ProcessExit(immediate) to break potential infinite error loops — complex error semantics easy to regress.