Flutter has exploded in popularity for cross-platform mobile development. With that growth, the pub.dev package ecosystem has expanded rapidly -- over 40,000 packages and counting. But the security tooling for Dart and Flutter dependencies lags behind what npm, PyPI, and Maven ecosystems offer.
This gap matters. A compromised Flutter dependency can end up running on millions of mobile devices, with access to cameras, GPS, contacts, and payment systems.
The pub.dev Security Model
pub.dev, Dart's official package repository, has several security-relevant features:
Verified publishers. Organizations can verify their identity, and packages from verified publishers display a badge. This helps distinguish official packages from impersonators, but verification does not imply security auditing.
Package scoring. pub.dev assigns scores based on documentation, maintenance, and code quality. While not a security metric, poorly maintained packages with low scores are higher-risk dependencies.
License detection. Automated license detection helps identify packages with unexpected licenses, which can be a signal of suspicious activity.
Automated analysis. pub.dev runs the Dart analyzer on uploaded packages and flags issues. However, this analysis focuses on code quality rather than security vulnerabilities.
What pub.dev does not have is a built-in vulnerability database or security advisory system comparable to npm's advisory database or Go's vulnerability database.
Attack Vectors
Dependency confusion. Dart's package resolution looks at pub.dev by default. If your organization uses private packages with names that do not exist on pub.dev, an attacker could claim those names and publish malicious packages. When a developer or CI system accidentally resolves from pub.dev instead of the private registry, the malicious package gets installed.
Native plugin compromise. Flutter plugins often include platform-specific native code (Kotlin/Java for Android, Swift/Objective-C for iOS). This native code has full platform access and is not sandboxed differently from your own code. A compromised plugin with native code is particularly dangerous.
Build-time execution. While Dart itself does not have an equivalent to npm install scripts, Flutter's build process executes native build systems (Gradle for Android, Xcode for iOS). Malicious native code in a plugin can execute during the build, not just at runtime.
Transitive dependency depth. Flutter projects commonly have deep dependency trees. A single high-level package can pull in dozens of transitive dependencies. Each one is a potential attack surface.
Security Scanning Options
The tooling is more limited than in other ecosystems, but options exist:
dart pub outdated shows which dependencies have newer versions available. While not a security scanner, keeping dependencies updated is a baseline defense.
OSV (Open Source Vulnerabilities) database includes Dart/Flutter advisories. The osv-scanner tool from Google can scan pubspec.lock files for known vulnerabilities.
Snyk and Dependabot have added Dart/Flutter support, though coverage of the advisory database is still growing.
Custom analysis. For critical projects, consider running the Dart analyzer with custom lint rules that flag security-sensitive patterns: insecure HTTP usage, disabled certificate verification, excessive permission requests.
Dependency Auditing Practices
Before adding a new package to your Flutter project, check:
Publisher verification. Is the package from a verified publisher? Unverified packages from unknown publishers are higher risk.
Maintenance activity. When was the last commit? When was the last release? A package that has not been updated in over a year may have unpatched vulnerabilities.
Native code. Does the package include native Android or iOS code? If so, what permissions does it require? A package that requests camera and location permissions for a feature that should not need them is suspicious.
Dependency tree. How many transitive dependencies does the package bring in? Each one expands your attack surface.
License. Unexpected license changes between versions can indicate a package takeover.
Pinning and Lockfiles
Always commit your pubspec.lock to version control. This ensures that every developer and CI build uses exactly the same dependency versions. Without the lockfile, pub get resolves to the latest compatible versions, which could include a newly published malicious version.
Consider using exact version constraints in pubspec.yaml for critical dependencies rather than version ranges. While this creates more maintenance work for updates, it prevents automatic adoption of potentially compromised new versions.
Platform Permission Auditing
Flutter plugins request platform permissions through AndroidManifest.xml and Info.plist entries. When a plugin update adds new permissions, your app gains capabilities it did not have before. This can happen silently through transitive dependency updates.
Regularly audit your app's effective permissions. On Android, review the merged AndroidManifest.xml to see all permissions requested by all dependencies. On iOS, review Info.plist for usage descriptions that indicate capability requests.
Unexpected permission additions from dependency updates are a red flag that warrants investigation before the update is accepted.
How Safeguard.sh Helps
Safeguard.sh provides dependency vulnerability scanning for Dart and Flutter projects, filling the gap in pub.dev's native security tooling. It generates SBOMs that capture your full dependency tree including transitive dependencies, monitors for newly disclosed vulnerabilities affecting your packages, and alerts you when a dependency in your Flutter project requires attention. For organizations with multiple Flutter applications, Safeguard.sh provides a centralized view of dependency risk across your entire mobile portfolio.