Safeguard
Developer Tools•

Which SwiftPM version requirement: from, exact, branch or revision?

Swift Package Manager offers five ways to state a dependency version. Here is what each allows, what each risks, and which one to default to.

Safeguard Security Team
3 min read

Use from: for most Swift package dependencies. It accepts updates up to the next major version, which keeps you on compatible releases. Use a range when you need a tighter window, exact with a clear reason, and avoid branch and revision in anything you ship, because they bypass version meaning entirely.

The five requirement forms

The Swift Package Manager documentation lists five ways to declare a dependency in Package.swift. Three are version based and two point at source control.

FormWhat it acceptsUpdates arrive
from: "1.2.3"1.2.3 up to, not including, 2.0.0Yes, within the major version
.exact("1.2.3")That one versionNo
Range such as "1.2.3"..<"1.2.6"Versions inside the rangeYes, inside the window
.branch("develop")Whatever is at the branch tipEvery change on the branch
.revision("e74b07...")One commit hashNo

The documentation calls from: the recommended form and says exact is not recommended because it can cause conflicts when several packages depend on the same package.

Security trade offs of each

from. You receive patch releases automatically on the next resolve, which is how most security fixes reach you. The risk is that a compatible looking release still changes behaviour, so keep your resolved versions under review.

exact. You are stable, but you also stay on a vulnerable version until someone edits the manifest. Pinning is a decision to own the patching, not a way to avoid it.

range. Useful when a later minor release broke something. Revisit the upper bound on a schedule, since a forgotten ceiling quietly blocks fixes.

branch. The dependency changes whenever the branch does. The docs note a package with a branch requirement cannot be depended on by packages using version requirements. For security, the point is simpler: you cannot say which code you shipped from the requirement alone.

revision. Fixed and reproducible, but you get no updates. The documentation says to limit it to exceptional cases.

A sensible default

  1. Declare dependencies with from: at the version you tested.
  2. Commit the resolved file your build produces so every machine and CI run uses the same versions.
  3. Update on a regular cadence, and sooner when an advisory affects a package you use.
  4. Treat any branch or revision requirement as a temporary measure with an owner and a date.
  5. Keep a list of what you ship. Listing every dependency in an iOS app shows how.

Try it yourself

Click through it at your own pace, or open it full screen. Look at how direct and transitive packages appear in one inventory.

Safeguard builds an SBOM and scans your dependencies for known vulnerabilities, and you can run a free scan at gold.safeguard.sh/scan to see what your own project pulls in.

Quick check

Is exact pinning safer than from?

Not automatically. It prevents surprise changes, but it also blocks security fixes until you edit the manifest. Pin when you will own the update schedule.

Can I use a branch in a production app?

You can, but the requirement no longer tells you which code you shipped. Prefer a tagged version or a revision with a documented reason.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.