To assert that "There exist supply-chain security risks" in any software ecosystem doesn't require a formal analysis nor multiple experts to peer review such a notion. It's kind of a given, especially with recent tech news.
However, it's not a new problem. We were vocal about it in 2015, when it was common practice for software projects to tell you to install their widget by running curl http://some-domain | sh
in a terminal window. This specific anti-pattern had already been criticized widely by others since at least 2013, but we were more interested in proposing a general solution to secure code delivery.
The only things that have really changed in the intervening years are:
- More people are aware of the risks today than 7 years ago,
- More disasters have been caused by the lack of supply-chain security for open source software, and
- We know it's a solvable problem.
That last item might seem bold, but we've been laying the groundwork for elegantly solving these problems for the PHP ecosystem since our company's inception. We had briefly introduced our complete solution when we announced that WordPress would cryptographically sign its automatic updates in 2019. (If you'd like more depth into this subject, we've previously written about supply-chain security in 2017 and automatic security updates in 2016.)
Part of making an acceptable solution even possible required getting modern cryptography into PHP and writing a pure-PHP polyfill of ext/sodium for legacy versions of PHP. (These are just two of the things that we're known for in the PHP community.)
So with all that in mind, let's take a quick look at Gossamer, our proposal for securing the software supply-chain for the PHP ecosystem.
Gossamer: Security Through Transparency
The elevator pitch for Gossamer is, Code-signing and third-party attestations published to a transparency log.
How Gossamer is Different
Code-signing isn't a novel concept; most of the applications on your computer or smartphone are digitally signed by some entity (hopefully the developer), and typically involves a lot of X.509 machinations to work. There are other code-signing proposals for solving supply chain woes today (e.g. TUF).
The use of a transparency log isn't quite unique either. This requirement was first outlined in the Triangle of Secure Code Delivery (Userbase Consistency Verification), and has been adopted by Sigstore.
What makes Gossamer distinct from proposals that offer code-signing and transparency logs is:
- Gossamer provides a mechanism for third-party review before updates are applied to dependencies
- We call these third-party reviews of a software update "attestations"
- There are currently several types of attestations specified, ranging from
spot-check
tosec-audit
; as well as avote-against
attestation for package updates that shouldn't be installed at all
- Gossamer requires no centralized Certificate Authorities, ever
- This largely mitigates the risk of extralegal government action
- Some ecosystems may optionally support a Super-Provider account that's capable of taking emergency action as a break-glass feature for mitigating emergencies
- Developers remain in control of their signing keys
- This is drastically different than, e.g., what Google does for Android apps
- Instead, publishers are mapped to a set of public keys, and all changes to this mapping are distinct messages appended to the transparency log.
Additionally, all changes to public keys, software updates, and attestations are published onto a single transparency log, rather than different ones for each purpose. This prevents a partial censorship attack (i.e. allow updates to go through, but not key revocations or attestations, thereby preventing targets from rejecting known malware).
Why Third-Party Attestations Matter
There's an old belief in the Free and Open Source Software community, rooted in something called Linus's Law: "Given enough eyeballs, all bugs are shallow."
Their reasoning goes: "If software is open source, it is necessarily more secure than closed source software because more people can review the source code to identify vulnerabilities. Consequently, vulnerabilities will persist longer in closed source software (due to less scrutiny). Therefore, the average security of an open source software project is expected to be greater than if it was closed source."
However, as we've seen over the years with GnuPG, OpenSSL, and Log4j (Did someone reading this just shout "BINGO"?), Linus's Law isn't a robust hypothesis. It assumes that, because anyone can inspect the code, then someone will. But there's no enforcement mechanism, so there will always be gaps, and there's no way for you or I to know where the gaps lie.
But what if we could prove whether or not a particular software update was inspected, and to what degree?
That's what Gossamer's Attestations do. In the current version of the Gossamer specification, there are five types of attestations permitted by the AttestUpdate
message:
-
vote-against
: "This is malicious; don't install it." -
reproduced
: "We were able to reproduce this update from the source code." Requires open source software. -
spot-check
: "We quickly looked at the code and didn't identify anything obviously malicious, like an infinite loop or a cryptocurrency miner. It's probably not terrible." -
code-review
: "We thoroughly reviewed this software update, and we have some concept of how the changes fit into the larger project, and we think it's fine." -
sec-audit
: "We're security experts and took the time to deliberately audit this update, its dependencies, how its dependencies are used, etc."
This data isn't just lying around inert on the transparency log collecting dust, either. You can directly configure an Attestation Policy for your update logic in a Gossamer client, too.
For example (with contrived usernames):
<?php
use ParagonIE\Gossamer\Client\AttestPolicy;
use ParagonIE\Gossamer\Client\PolicyRules\AttestedAt;
use ParagonIE\Gossamer\Client\PolicyRules\AttestedAtOrAbove;
use ParagonIE\Gossamer\Client\PolicyRules\GroupAnd;
use ParagonIE\Gossamer\Client\PolicyRules\GroupOr;
use ParagonIE\Gossamer\Client\PolicyRules\Not;
use ParagonIE\Gossamer\Client\TrustMode\LocalTrust;
use ParagonIE\Gossamer\Db\PDO as PDOAdapter;
// Trust mode (local for simplicity)
$db = new PDOAdapter(new PDO('sqlite:/path/to/database.sql'));
$myTrustMode = new LocalTrust($db);
// Attestation Policy:
$myAttestPolicy = (new AttestPolicy())
->addRule(
new GroupAnd(
new AttestedAt(
AttestPolicy::REPRODUCED,
['reproduced-bot']
),
new GroupOr(
new AttestedAtOrAbove(
AttestPolicy::SPOT_CHECK,
['paragonie', 'symfony', 'laravel', 'ncc'],
2
),
new AttestedAtOrAbove(
AttestPolicy::CODE_REVIEW,
['paragonie', 'ncc']
)
),
new Not(
new AttestedAt(
AttestPolicy::VOTE_AGAINST,
['jedisct1', 'muglug']
)
)
)
);
// Instantiate via dependency injection:
$gossamer = new GossamerClient(
$myTrustMode,
$myAttestPolicy
);
// Get an update record from the transparency log:
$record = $gossamer->getUpdate('symfony/polyfill-php80', 'v1.20.0');
// If it's valid...
if ($record->isFileValid($file)) {
// Install it!
my_custom_installer($file);
}
In this example, even if an attacker pushed a malicious version of symfony/polyfill-php80
to Packagist, it would not be installed by the client using this configuration unless all of the following conditions were met:
- It was confirmed as reproducible from the source code, by a hypothetical bot account that verifies this.
- Either...
- Two of the allow-listed vendors spot checked the release, or
- One of the more security-focused vendors code-reviewed it.
- Neither of two separate vendors published a
vote-against
about this update.
This is why Third-Party Attestations matter: They allow end users to prevent code from being installed when a developer goes rogue, without forcing end users to entirely in-house their review of third-party code.
What Happens if a Third Party is Compromised?
Attestations are immutable. There is no "revoke" feature for an attestation, only for keys and updates.
If an independent third-party publishes a bad attestation for an update, they have ceased to be trustworthy. The only recourse is to distrust said third party from your configuration.
This is an intentional feature of Gossamer's design; it forces security vendors to be transparent and accountable for the code they review.
What Happens if Nobody Publishes Attestations, Fearing This Immutability?
Would you trust a security vendor to protect you from attackers if they're completely unwilling to have some skin in the game and publicly stake their own reputation to help protect the open source community?
At the first sign of trouble, would they protect you and your customers, or clam up to cover their own asses? This would be a dumb problem to have, which is easily solved by getting better security vendors into the space.
Why Not Use Blockchain To Solve This?
When all you have is a hammer, every problem looks like a nail.
When all you have is a cryptocurrency, every problem looks like a good fit for blockchain technology.
Gossamer Project Status
We published libgossamer years ago, which includes all of the pieces needed to get Composer and WordPress to onboard the protocol.
We also created a standalone gossamer-server, which serves as a middleware between the Gossamer client and the transparency log (which is powered by Chronicle). (We have a TODO item to create an alternative server implementation as a WordPress plugin, but this might be better developed by someone else.)
What we haven't published yet is the command-line interface for communicating with a Gossamer Server. This is mostly due to our perfectionism; striking the right balance between code flexibility and user experience has resulted in a ton of iterations that we're not currently satisfied with. Usable security is hard. But we're making progress, so expect this to arrive in 2022.
If you'd like an up-to-date resource for the status of the Gossamer project, we created a dedicated website for it: https://gossamer.tools.
Note: Pay special attention to the Questions & Answers page. We've answered a lot of questions from previous discussions of Gossamer there, including questions you may have.