February 26, 2021·5 min read·engineeringswiftpackagessecurity

Swift package collection signing separates curation from identity

The accepted SE-0291 amendment defines certificate-based signatures for package collections. Its trust model distinguishes an intact recommendation list from a list signed by the publisher a consumer actually intended.

A curated dependency list becomes a security concern when changing its contents changes which software people discover. A publisher can recommend a particular package, but a modified collection can direct the reader elsewhere without changing the surrounding workflow. Swift has accepted the package collection signing amendment to SE-0291 on February 26. The design gives collection consumers evidence about the author and integrity of the metadata they import.

The interesting problem is identifying the expected publisher. A signature made with a valid certificate can still belong to someone other than the intended curator. The accepted design therefore discusses both certificate validation and publisher-specific restrictions. Those checks answer different questions, and the distinction determines what the mechanism protects.

I find Swift appealing when its interfaces make assumptions explicit. Package discovery needs the same discipline. Trusting a recommendation list should be a visible decision with a defined meaning, especially when a convenient search interface makes the underlying metadata easy to overlook.

Collections distribute recommendations

The accepted proposal as it stands today describes collections as static JSON documents containing packages and associated metadata. A publisher can serve a document from a website, and a consumer can subscribe through SwiftPM. Collections give educators a way to distribute course dependencies and organizations a way to present vetted packages to engineers.

That design has a deliberately smaller hosting requirement than a service that stores package source. A collection describes packages that may live elsewhere. Its publisher controls the recommendation and metadata, while package hosting remains a separate concern. Importing a collection therefore establishes a source of discovery information. It does not establish that every package mentioned has passed an independent security assessment.

The proposed command interface supports adding and removing collections, searching their contents and describing packages. Search can use package metadata or a module name. These operations make the same curated information available through the command line and libSwiftPM, so other development tools can consume it. As an accepted design, this describes intended behavior rather than a claim that a released toolchain already provides every command.

For example, the proposal illustrates the following command shape for subscribing to a collection and searching its metadata. The example URL is a placeholder, not an actual collection to install.

swift package-collection add https://www.example.com/packages.json
swift package-collection search --keywords yaml

A useful consequence follows from the division between discovery and source distribution. Signing a collection protects the curator's statement about packages. It does not turn that statement into a signature over all the source code those packages contain. The security meaning needs to remain attached to the object that actually receives the signature.

Certificate validation supplies an identity framework

Yim Lee's original signing discussion explains why the proposal uses certificates. A public key alone does not tell a consumer who owns it. Another system must maintain that association. The discussion considers simpler key-based alternatives, but the proposed collection mechanism does not tie itself to a hosting service that already manages those mappings.

Publishers will supply the collection, a code signing certificate, its private key and the certificate chain to signing tooling. A signed collection carries an additional signature object, with verification information available to the consumer. The content check excludes that signature object itself. Verification must establish that the metadata matches what the signer signed and that the certificate satisfies the design's requirements.

Those requirements include validity at the time of signing or verification and the Code Signing extended key usage. The permitted keys are 256-bit elliptic-curve keys or 2048-bit RSA keys. Revocation checking requires an OCSP responder identified through the certificate authority information access extension. The chain must also terminate at a trusted root. Each requirement limits which otherwise usable certificate can authenticate a collection.

This introduces operational dependencies beyond possession of a private key. Certificate lifetime and revocation status matter to whether consumers can import the signed metadata. A publisher choosing this mechanism accepts those conditions as part of distributing recommendations. The design makes them explicit instead of treating any cryptographically valid signature as sufficient evidence of identity.

Platform trust stores are part of the behavior

The accepted text gives Apple and non-Apple platforms different initial root trust. Apple platforms trust the roots preinstalled with the operating system. Additional roots can be supplied in ~/.swiftpm/config/trust-root-certs. Non-Apple platforms initially trust only roots supplied in that directory.

That difference matters to a collection publisher whose readers use several operating systems. A certificate that verifies on an Apple machine does not establish that another machine has the required trusted root configured. The collection's contents can be identical while the local trust decision differs. Documentation for consumers must therefore explain the relevant roots as well as the collection URL.

The proposal also distinguishes skipping verification for a signed collection from explicitly trusting an unsigned one. Those are separate operations with separate flags. Keeping them distinct preserves information about what the consumer has accepted. An unsigned list has no signature to check, while a signed list can fail because its signature or certificate does not satisfy verification.

Valid signing and expected signing are different checks

The amendment review addresses a question about what signatures add when the collection already arrives over HTTPS. Lee points out that the hosting server itself can be compromised. Protecting the transport does not establish that the server is still serving the curator's intended document.

The accepted proposal identifies signature stripping and signature replacement as remaining attacks. Stripping changes the collection into an unsigned document. Replacement changes the document and signs it with another valid certificate. A consumer that accepts any valid signer has not established that the original publisher authorized the recommendation.

Publisher restrictions address those cases by requiring signatures and constraining the signing certificate. The review explains that restrictions can concern the leaf certificate's subject user ID, an object identifier or its chain. The described configuration process involves a pull request to SwiftPM's certificate pinning configuration. That process introduces maintenance work, but it provides a place to state which signer is expected for a particular publisher.

I regard that distinction as the most useful part of the amendment. A certificate chain can establish a valid identity relationship without establishing that the identity is appropriate for this collection. The additional publisher restriction supplies the missing association between the recommendation list and its intended author.