When a mobile team runs pod install or swift build, they are triggering a dependency resolution process that most security tools never actually observe — they only see the lockfile that comes out the other end. For iOS projects, that creates two very different scanning problems: CocoaPods produces a static Podfile.lock that can be parsed offline, while Swift Package Manager expects a live toolchain to resolve versions on demand. Snyk handles these two ecosystems with two distinct mechanisms — a dedicated lockfile parser for CocoaPods, and a CLI plugin that shells out to the swift binary itself for SwiftPM. Understanding how each one actually works — what files they need, what they can and can't see, and where they fall over — matters for any team deciding whether their iOS dependency graph is actually being scanned, or just partially sampled.
How does Snyk read a CocoaPods dependency tree?
Snyk reads it directly from Podfile.lock, using a dedicated open-source component called @snyk/cocoapods-lockfile-parser (now at v3.10.3 as of its June 22, 2026 release) to convert the lockfile into a dependency graph. CocoaPods' own lockfile format makes this feasible without invoking any tooling: a Podfile.lock contains a PODS section listing every resolved pod and its pinned version, a DEPENDENCIES section showing what the Podfile declared directly, a SPEC REPOS section identifying which spec source each pod came from, and a SPEC CHECKSUMS block with a SHA hash per pod for integrity verification. Because all of that is static text, Snyk's parser can build a full transitive graph — direct and indirect pods, version pins, and repo provenance — without running pod install or touching the network. Snyk's CLI test and monitor commands consume this same graph, and CocoaPods is one of the few iOS ecosystems in Snyk's supported-language matrix where CLI scanning, Git repository import, and license scanning are all documented as available together.
What happens when a Podfile.lock is out of sync with the Podfile?
Snyk can skip or fail the test rather than scan stale data, and it exposes a --strict-out-of-sync=true CLI flag specifically to enforce that behavior. This matters because Podfile.lock is a snapshot: if a developer edits the Podfile to bump a pod version or add a new dependency but forgets to run pod install, the lockfile still reflects the old resolution. CocoaPods itself tracks this drift internally through a PODFILE CHECKSUM entry at the bottom of the lockfile, which is a hash of the Podfile contents used to detect exactly this kind of mismatch. A vulnerability scanner reading only the lockfile has no way to know a newer, possibly still-vulnerable or newly-vulnerable version was intended — so out-of-sync detection is the difference between reporting on what's actually installed versus what a developer merely typed into a manifest weeks ago and never locked in.
How does Snyk resolve Swift Package Manager dependencies without a lockfile parser?
It doesn't parse Package.resolved as its primary source — instead, Snyk requires a Package.swift manifest to be present and runs the swift package show-dependencies command to have the Swift toolchain itself resolve and report the dependency tree. This is a fundamentally different approach from CocoaPods: rather than reading a static artifact, Snyk's snyk-swiftpm-plugin invokes the actual build tool and lets Swift do what it would do during a real build — fetch package manifests, resolve version ranges, and produce a live dependency graph, which the plugin then translates into Snyk's format. Snyk's documentation notes this explicitly: "Swift must resolve the dependencies as part of this process," and that resolution step is what can extend scan times noticeably compared to a pure lockfile read. Snyk's Open Source scanning covers Swift 3.0 through 6.2.x for this purpose, a wider range than Snyk Code's static analysis, which is supported only up to Swift 5.7.x (with Objective-C analysis available as an Enterprise-only Early Access feature).
Why would having a prebuilt .build folder speed up a Snyk scan?
Because it lets the Swift toolchain skip re-resolving packages it has already fetched, and Snyk's own documentation calls this out as a way to reduce CLI processing time. Since swift package show-dependencies triggers real dependency resolution rather than reading a cached lockfile, a cold scan on a CI runner with no .build directory has to hit package registries and Git remotes for every dependency before it can even begin graph construction. Teams running Snyk against SwiftPM projects in CI are effectively trading the offline-parseable convenience of CocoaPods for a scan that behaves more like an actual swift build invocation — which is faster when warm-started but heavier by default, and which introduces a network dependency into what is nominally a static analysis step.
What can't Snyk see in an iOS dependency graph?
Two specific gaps are worth knowing about: Snyk documents that SwiftPM projects don't support source-control-management (SCM) import the way CocoaPods projects do, and that dependencies introduced through custom post-processing or build-script steps — packages added outside the declared manifest, for instance via a build phase script that pulls in a framework directly — aren't detected by either the CocoaPods or SwiftPM integration. Snyk also states plainly that its Fix PR feature, which opens automated pull requests bumping a vulnerable dependency, is not available for Swift or Objective-C at all. That means remediation for an iOS project surfaced by Snyk still requires a manual pod update or manifest edit, unlike the automated fix workflow available for ecosystems like npm or Maven.
Does CocoaPods or Swift Package Manager give Snyk more complete visibility?
CocoaPods gives Snyk a more complete and cheaper-to-obtain picture, because the entire resolved graph — versions, transitive pods, checksums, and source repos — already exists in one committed text file before Snyk ever runs. SwiftPM's graph, by contrast, is reconstructed at scan time by re-running part of the actual build, which means its accuracy depends on the scanning environment having network access, a working Swift toolchain, and enough time for resolution to complete; a scan that times out or runs in a network-restricted CI sandbox can silently under-report the true dependency set. For teams shipping apps that mix both package managers — common during a multi-year CocoaPods-to-SwiftPM migration — this asymmetry means the CocoaPods half of the app is scanned from a stable, git-tracked source of truth, while the SwiftPM half depends on the resolution succeeding cleanly every single time a scan runs.
How Safeguard Helps
The mechanics above matter because they show that "scanning iOS dependencies" isn't one workflow — it's two, with different inputs, different failure modes, and different blind spots depending on which package manager a given target links against. Safeguard's approach to software supply chain security starts from the same premise: visibility has to account for how a dependency graph was actually produced, not just what a single manifest file claims. For mobile codebases that mix CocoaPods and SwiftPM — or migrate between them over multiple release cycles — Safeguard focuses on continuously tracking the resolved state of both lockfiles and toolchain-driven resolutions, flagging when a Podfile.lock drifts out of sync with its Podfile, and maintaining provenance records for dependencies pulled in through either ecosystem so that a build script or manifest change doesn't quietly introduce an unreviewed package. Combined with SBOM generation that spans both dependency formats, this gives security and mobile engineering teams a single, consistent view of what's actually shipping in an iOS binary — regardless of which package manager put it there.