Safeguard
Developer Tools•

Should you commit Package.resolved for a Swift project?

Commit it for apps and other top-level projects. For a library it does not pin anything for your users. What SwiftPM docs say and what it means for scans.

Safeguard Security Team
3 min read

Commit Package.resolved for an app or any top-level Swift project, because it records the exact dependency versions your builds use. For a library, committing it does not pin versions for the people who depend on you, since SwiftPM ignores a dependency's own Package.resolved during resolution.

What the file is

The Swift Package Manager documentation says the package manager records the result of dependency resolution in a file named Package.resolved at the top level of the package. When you resolve dependencies for the top-level (leaf) package, the file acts as a cache of the versions of the dependencies.

For an app that adds a package inside Xcode, the file sits inside the project or workspace bundle rather than next to a Package.swift.

Apps versus libraries

Project typeCommit Package.resolvedWhy
App or tool (leaf package)YesGives every build the same versions
Library used by other projectsOptionalYour consumers ignore it, they get the latest eligible versions
Container or CI buildPass it inThe docs suggest resolving locally and passing it to a build

The documentation states that the file does not provide dependency pinning for libraries or packages used as dependencies of other Swift projects. If your package has the file checked in, those versions are ignored by a package that depends on it.

What happens without it

If no Package.resolved exists, each user or build system resolves versions separately, only updating when they run the update command, and new users start with the latest eligible version of each dependency. Two developers can then build different dependency sets from the same Package.swift.

Forcing the recorded versions

swift package resolve --force-resolved-versions

The docs say this makes the resolve command use the dependencies written into Package.resolved. Use it in CI so a build fails rather than quietly resolving something new.

To move forward on purpose, run the update command. It moves dependencies to the latest eligible versions and rewrites Package.resolved, and you review that diff in a pull request.

What a scanner should read

The recorded file gives exact versions, which is what advisory matching needs. A scan that reads only Package.swift sees version ranges, not the versions that were built. GitHub's dependency graph lists Package.resolved as its recommended file for Swift, which fits the same logic.

Try it yourself

Click through it at your own pace, or open it full screen.

Check how an exact resolved version differs from a declared range in the inventory.

Quick check

Does my library's Package.resolved protect my users?

No. The SwiftPM docs say it is ignored when your package is resolved as a dependency of another project.

How do I stop CI from picking up newer versions?

Commit Package.resolved and run resolve with the force resolved versions option so the build uses what is recorded.

Safeguard's SBOM and dependency scanning builds a component inventory from project files like these and checks it against known advisories. Try the free scan.

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.