Skip to content

Instantly share code, notes, and snippets.

@willglynn
Created October 4, 2012 02:01
Show Gist options
  • Save willglynn/3831050 to your computer and use it in GitHub Desktop.
Save willglynn/3831050 to your computer and use it in GitHub Desktop.
.gemsig Proposal

.gemsig Proposal

RubyGems.org has little in the way of defenses against tampering. Right now, new gems could be uploaded to S3 and distributed to users worldwide without detection, and the only thing preventing this is the security of the AWS credentials presently stored on world-facing web servers. S3 Versioning is a step that could be taken immediately to reduce the severity of compromise, but a larger solution is required.

This document proposes a .gemsig file as a means of verifying that a gem has not been modified during distribution. This file would be distributed alongside the .gem files, allowing clients to verify authenticity.

Format

While the exact file format is not relevant at this stage of discussion, in terms of requirements, a .gemsig file should contain:

  • The gem name and version number
  • The size of the gem in bytes
  • At least one cryptographic hash of the corresponding .gem

In principle, the name of the gem and a single cryptographic hash of the .gem should be sufficient. In practice, specifying multiple hashes as well as the length of the file assists in defending against collisions.

The information in the .gemsig must be itself cryptographically signed. Given the current reliance on OpenSSL, PKCS#7 seems appropriate.

Certificates

RubyGems.org should operate its own Certificate Authority. This CA should exist offline, signing keys for intermediate CAs as new intermediate CAs are required. This CA's certificate would be bundled with the rubygems package and associated with the rubygems.org source.

Gem Signing

The rubygems.org web servers receive new gems on an ongoing basis. These new gems must be signed automatically, but they need not be signed by the rubygems.org web servers directly. Instead, incoming gems could be signed by a signing server.

A signing server would operate on separate physical infrastructure. It should expose a single action: sign this .gem, returning its .gemsig. Upon receipt of a gem, the signing server would check its own local database to ensure it had not already signed that gem + version combination. If this gem is indeed new, it would sign the gem using its own intermediate certificate, record that signing event, and return the .gemsig.

The signing record must be as durable as possible. It may as well also be public. One option is to publish new signatures to an Amazon SNS topic, enabling any and all interested parties to receive a list of signatures as they happen.

Web servers must authenticate to the signing server, not just to control access, but to provide an audit trail in the event that a web server is compromised. This information should be included in the signing record. It might even make sense to eliminate the "signing record" as a separate step and instead recording all relevant information directly into the .gemsig -- after all, .gemsigs will be signed and widely-distributed already.

Verification

Whenever a client downloads a .gem from a secured source, it must also download a corresponding .gemsig file. A secured source must provide a .gemsig for all .gems -- after all, an attacker who can return a malicious .gem can also destroy (but not forge!) its corresponding .gemsig.

rubygems.org would be one such secured source with its expected certificate distributed as part of the rubygems package. It should be possible for others to create their own .gemsigs and configure their source to expect signatures descending from a particular set of keys.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment