{"id":13472029,"url":"https://github.com/codahale/sneaker","last_synced_at":"2026-01-25T03:08:13.876Z","repository":{"id":26639555,"uuid":"30095459","full_name":"codahale/sneaker","owner":"codahale","description":"A tool for securely storing secrets on S3 using Amazon KMS.","archived":false,"fork":false,"pushed_at":"2020-10-01T08:30:42.000Z","size":673,"stargazers_count":800,"open_issues_count":4,"forks_count":34,"subscribers_count":29,"default_branch":"master","last_synced_at":"2024-11-02T06:59:23.646Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codahale.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-01-30T23:25:26.000Z","updated_at":"2024-10-01T16:30:36.000Z","dependencies_parsed_at":"2022-09-01T13:51:01.927Z","dependency_job_id":null,"html_url":"https://github.com/codahale/sneaker","commit_stats":null,"previous_names":["stripe/sneaker"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/codahale/sneaker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codahale%2Fsneaker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codahale%2Fsneaker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codahale%2Fsneaker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codahale%2Fsneaker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codahale","download_url":"https://codeload.github.com/codahale/sneaker/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codahale%2Fsneaker/sbom","scorecard":{"id":295432,"data":{"date":"2025-08-11","repo":{"name":"github.com/codahale/sneaker","commit":"76cfcf0b7e3fa50d925d79b5448b6b7ef20bc39d"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.8,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Code-Review","score":6,"reason":"Found 9/15 approved changesets -- score normalized to 6","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 25 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-17T19:22:50.980Z","repository_id":26639555,"created_at":"2025-08-17T19:22:50.987Z","updated_at":"2025-08-17T19:22:50.987Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28742973,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T02:46:29.005Z","status":"ssl_error","status_checked_at":"2026-01-25T02:44:29.968Z","response_time":113,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T16:00:51.276Z","updated_at":"2026-01-25T03:08:13.830Z","avatar_url":"https://github.com/codahale.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# Sneaker\n\n[![Build Status](https://travis-ci.org/codahale/sneaker.svg?branch=master)](https://travis-ci.org/codahale/sneaker)\n[![Apache V2 License](http://img.shields.io/badge/license-Apache%20V2-blue.svg)](https://github.com/codahale/sneaker/blob/master/LICENSE)\n\n*Setec Astronomy? Keynote Shogun.*\n\n`sneaker` is a utility for storing sensitive information on AWS using S3\nand the Key Management Service (KMS) to provide durability,\nconfidentiality, and integrity.\n\nSecrets are stored on S3, encrypted with AES-256-GCM and single-use,\nKMS-generated data keys.\n\n## Table Of Contents\n\n* [WARNING](#warning)\n* [Installing](#installing)\n* [Using](#using)\n  * [Configuring Access To AWS](#configuring-access-to-aws)\n  * [Setting Up The Environment](#setting-up-the-environment)\n  * [Basic Operations](#basic-operations)\n  * [Packing Secrets](#packing-secrets)\n  * [Unpacking Secrets](#unpacking-secrets)\n  * [Encryption Contexts](#encryption-contexts)\n  * [Maintenance Operations](#maintenance-operations)\n* [Implementation Details](#implementation-details)\n* [Architecture](#architecture)\n* [Threat Model](#threat-model)\n  * [Assumptions](#assumptions)\n  * [Threats From A KMS Compromise](#threats-from-a-kms-compromise)\n  * [Threats From An S3 Compromise](#threats-from-an-s3-compromise)\n  * [Threats From Seizure Or Compromise Of The User's Computer](#threats-from-seizure-or-compromise-of-the-users-computer)\n\n## WARNING\n\n**This project has not been reviewed by security professionals. Its\ninternals, data formats, and interfaces may change at any time in the\nfuture without warning.**\n\n## Installing\n\n```shell\ngo get -d -u github.com/codahale/sneaker\ncd $GOPATH/src/github.com/codahale/sneaker\nmake install\nsneaker version\n```\n\n## Using\n\n### Configuring Access to AWS\n\n`sneaker` requires access to AWS APIs, which means it needs a set of AWS\ncredentials. It will look for the `AWS_ACCESS_KEY_ID` and\n`AWS_SECRET_ACCESS_KEY` environment variables, the default credentials\nprofile (e.g. `~/.aws/credentials`), and finally any instance profile\ncredentials for systems running on EC2 instances.\n\nIn general, if the `aws` command works, `sneaker` should work as well.\n\nIf you have multi-factor authentication enabled for your AWS account\n(**and you should**), you may need to provide a token via the\n`AWS_SESSION_TOKEN` environment variable.\n\nIf you're using IAM instance roles, you may need to set the `AWS_REGION`\nenvironment variable to the AWS region you're using (e.g. `us-east-1`).\n\n### Setting Up The Environment\n\nSneaker requires two things: a KMS master key and an S3 bucket.\n\nYou can create a KMS key via the AWS Console or using a recent version\nof `aws`. When you've created the key, store its ID (a UUID) in the\n`SNEAKER_MASTER_KEY` environment variable:\n\n```shell\nexport SNEAKER_MASTER_KEY=\"9ed356fb-5f0f-4792-983d-91866faa3705\"\n```\n\nAs with the key, you can create an S3 bucket via the AWS Console or with\nthe `aws` command. You can either use a dedicated bucket or use a\ndirectory in a common bucket, but we recommend you do two things:\n\n1. Use a `Private` ACL. In addition to the cryptographic controls of\n   `sneaker`, access control is critical in preventing security\n   breaches.\n\n2. Enable access logging, ideally to a tightly-controlled, secure\n   bucket. While Amazon's CloudTrail provides audit logging for the vast\n   majority of AWS services, it does not do so for S3 access.\n\nOnce you're done, set the `SNEAKER_S3_PATH` environment variable to the\nlocation where secrets should be stored (e.g. `s3://bucket1/secrets/`):\n\n```shell\nexport SNEAKER_S3_PATH=\"s3://bucket1/secrets/\"\n```\n\n(That will store the encrypted secrets in the bucket `bucket1` prefixed\nwith `secrets/`.)\n\n### Basic Operations\n\nOnce you've got `sneaker` configured, try listing the secrets:\n\n```shell\nsneaker ls\n```\n\nThis will print out a table of all uploaded secrets. You haven't\nuploaded anything yet, so the table will be empty.\n\nLet's create an example secret file and upload it:\n\n```shell\necho \"This is a secret!\" \u003e secret.txt\nsneaker upload secret.txt example/secret.txt\n```\n\nThis will use KMS to generate a random, 256-bit data key, encrypt the\nsecret with AES-256-GCM, and upload the encrypted secret and an\nencrypted copy of the data key to S3. Running `sneaker ls` should\ndisplay a table with the file in it.\n\nIf your file is so sensitive it shouldn't be stored on disk, using `-`\ninstead of a filename will make `sneaker` read the data from `STDIN`.\n\nYou can download a single file:\n\n```shell\nsneaker download example/secret.txt secret.txt\n```\n\nFinally, you can delete the file:\n\n```shell\nsneaker rm example/secret.txt\n```\n\n### Packing Secrets\n\nTo install a secret on a machine, you'll need to pack them into a\ntarball:\n\n```shell\nsneaker pack example/*,extra.txt example.tar.enc\n```\n\nThis will perform the following steps:\n\n1. Download and decrypt all secrets matching any of the patterns:\n   `example/*` or `extra.txt`.\n\n2. Package all the decrypted secrets into a `TAR` file in memory.\n\n3. Generate a new data key using KMS.\n\n4. Use the data key to encrypt the `TAR` file with AES-GCM.\n\n5. Write both the encrypted data key and the encrypted `TAR` file to\n   `example.tar.enc`.\n\nUsing `-` as the output path will make `sneaker` write the data to\n`STDOUT`.\n\nThe result is safe to store and transmit -- only those with access to\nthe `Decrypt` operation of the KMS key being used will be able to\ndecrypt the data.\n\nYou can also use a different KMS key than your `SNEAKER_MASTER_KEY` when\npacking secrets by using the `--key-id` flag:\n\n```shell\nsneaker pack example/* example.tar.enc --key-id=deb207cd-d3a7-4777-aca0-01fbceb4c927\n```\n\nThis allows you to unpack your secrets in environments which don't have\naccess to the key used to store your secrets.\n\n### Unpacking Secrets\n\nTo unpack the secrets, run the following:\n\n```shell\nsneaker unpack example.tar.enc example.tar\n```\n\nThis will perform the following steps:\n\n1. Read `example.tar.enc`.\n\n2. Extract the encrypted data key and encrypted `TAR` file.\n\n3. Use KMS to decrypt the data key.\n\n4. Decrypt the `TAR` file and write the result to `example.tar`.\n\nUsing `-` instead of a filename will make `sneaker` read the data from\n`STDIN`. Likewise, using `-` as the output path will make `sneaker`\nwrite the data to `STDOUT`. This allows you to pipe the output directly\nto a `tar` process, for example.\n\n### Encryption Contexts\n\nKMS supports the notion of an\n[Encryption Context](http://docs.aws.amazon.com/kms/latest/developerguide/encrypt-context.html):\nsemi-structured data used in the encryption of data which is then\nrequired for resulting decryption operations to be successful.\n\n`sneaker` uses the `SNEAKER_MASTER_CONTEXT` environment variable as the\ndefault encryption context for the secrets which are stored in S3. In\naddition, `sneaker` also includes the full S3 path, including bucket and\nprefix. Because of this, secrets in S3 cannot be renamed; they can only\nbe deleted and re-uploaded.\n\n**Note:** there is currently no way to change the contents of\n`SNEAKER_MASTER_CONTEXT` in place. If you want to change it, you'll need\nto download all your secrets and re-upload them with the new context.\n\nFor packing and unpacking secrets you can specify a different encryption\ncontext on the command line:\n\n```shell\nsneaker pack example/* secrets.tar.enc --context=\"hostname=web1.example.com,version=20\"\n```\n\nThat same context (`hostname=web1.example.com,version=20`) **must** be\nused to unpack those secrets:\n\n```shell\nsneaker unpack secrets.tar.enc secrets.tar --context=\"hostname=web1.example.com,version=20\"\n```\n\nAll data in the encryption contexts are logged via CloudTrail, which\nallows you to track when and where particular secrets are packed and\nunpacked.\n\n### Maintenance Operations\n\nA common maintenance task is key rotation. To rotate the data keys used\nto encrypt the secrets, run `sneaker rotate`. It will download and\ndecrypt each secret, generate a new data key, and upload a re-encrypted\ncopy.\n\nTo rotate the KMS key used for each secret, simply specify a different\n`SNEAKER_MASTER_KEY` and run `sneaker rotate`.\n\n## Implementation Details\n\nAll data is encrypted with AES-256-GCM using random KMS data keys and\nrandom nonces. The ID of the KMS key is used as authenticated data.\n\nThe final result is the concatentation of the following:\n\n* A four-byte header of the length of the encrypted KMS data key, in\n  bytes, in network order.\n\n* The encrypted KMS data key, verbatim. (This is an opaque Amazon format\n  which includes the key ID.)\n\n* The AES-256-GCM ciphertext and tag of the secret.\n\n## Architecture\n\n![Sneaker Architecture](https://raw.githubusercontent.com/codahale/sneaker/master/architecture.png)\n\n## Threat Model\n\nThe threat model is defined in terms of what each possible attacker can\nachieve. The list is intended to be exhaustive, i.e. if an entity can do\nsomething that is not listed here then that should count as a break of\nSneaker.\n\nIn broad strokes, the confidentiality and integrity of content stored\nwith Sneaker is predicated on the integrity of Sneaker, the\nconfidentiality and integrity of KMS, and the integrity of S3.\n\n### Assumptions\n\n* The user must act reasonably and in their best interest. They must not\n  reveal secrets or allow unauthorized access to secrets.\n\n* The user must run a copy of Sneaker which has not been suborned.\n\n* The user's computer must function correctly and not be compromised by\n  malware.\n\n* Communications with Amazon have confidentiality and integrity ensured\n  by the use of TLS.\n\n* Key Management Service is reasonably secure: its keys will not be\n  compromised, its random numbers are unguessable to adversaries, its\n  cryptographic algorithms are correct.\n\n* The authentication and access control functionality of both KMS and S3\n  are secure.\n\n* AES-256 and GCM's security guarantees are valid.\n\n### Threats From A KMS Compromise\n\nAn attacker who suborns KMS can:\n\n* Create forged secret packages.\n* Decrypt packaged tarballs.\n* Deny the ability to decrypt secrets, either temporarily or\n  permanently.\n\n### Threats From An S3 Compromise:\n\nAn attacker who suborns S3 can:\n\n* Delete or modify secrets such that they are no longer valid.\n\n### Threats From Seizure Or Compromise Of The User's Computer\n\nAn attacker who physically seizes the user's computer (or compromises\nthe user's backups) or otherwise compromises it can:\n\n* Recover AWS credentials and pose as the user. If multi-factor\n  authentication is not enabled, this would allow the attacker to\n  extract all secrets, modify secrets, etc.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodahale%2Fsneaker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodahale%2Fsneaker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodahale%2Fsneaker/lists"}