{"id":39283665,"url":"https://github.com/danizen/confsecrets","last_synced_at":"2026-01-18T01:06:04.304Z","repository":{"id":57417517,"uuid":"125573547","full_name":"danizen/confsecrets","owner":"danizen","description":"A simple utility module to symmetrically encrypt/decrypt application secrets","archived":false,"fork":false,"pushed_at":"2022-03-10T01:38:48.000Z","size":365,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-11-08T08:14:58.489Z","etag":null,"topics":["django","encryption-library","security-tools"],"latest_commit_sha":null,"homepage":"https://danizen.github.io/confsecrets/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/danizen.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":"2018-03-16T21:52:36.000Z","updated_at":"2022-03-10T01:25:09.000Z","dependencies_parsed_at":"2022-09-17T22:01:55.870Z","dependency_job_id":null,"html_url":"https://github.com/danizen/confsecrets","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/danizen/confsecrets","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danizen%2Fconfsecrets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danizen%2Fconfsecrets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danizen%2Fconfsecrets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danizen%2Fconfsecrets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danizen","download_url":"https://codeload.github.com/danizen/confsecrets/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danizen%2Fconfsecrets/sbom","scorecard":{"id":320960,"data":{"date":"2025-08-11","repo":{"name":"github.com/danizen/confsecrets","commit":"74aa9b89ff061cf1abbf742e01061c750520ba98"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.8,"checks":[{"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":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","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":"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":"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":"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":"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":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU General Public License v3.0: LICENSE:0"],"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":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact 0.0.1 not signed: https://api.github.com/repos/danizen/confsecrets/releases/14377357","Warn: release artifact 0.0.1 does not have provenance: https://api.github.com/repos/danizen/confsecrets/releases/14377357"],"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":"Vulnerabilities","score":2,"reason":"8 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-3ww4-gg4f-jr7f","Warn: Project is vulnerable to: GHSA-9v9h-cgj8-h64p","Warn: Project is vulnerable to: PYSEC-2021-62 / GHSA-hggm-jpg3-v476","Warn: Project is vulnerable to: PYSEC-2017-8 / GHSA-q3cj-2r34-2cwc","Warn: Project is vulnerable to: PYSEC-2021-142 / GHSA-8q59-q68h-6hv4","Warn: Project is vulnerable to: PYSEC-2018-49 / GHSA-rprw-h62v-c2w7","Warn: Project is vulnerable to: GHSA-29gw-9793-fvw7","Warn: Project is vulnerable to: PYSEC-2022-12 / GHSA-pq7m-3gw7-gq5x"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T01:21:21.450Z","repository_id":57417517,"created_at":"2025-08-18T01:21:21.450Z","updated_at":"2025-08-18T01:21:21.450Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28525515,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T00:39:45.795Z","status":"ssl_error","status_checked_at":"2026-01-18T00:39:39.467Z","response_time":85,"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":["django","encryption-library","security-tools"],"created_at":"2026-01-18T01:05:59.803Z","updated_at":"2026-01-18T01:06:04.294Z","avatar_url":"https://github.com/danizen.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# confsecrets\n[![Build Status](https://travis-ci.org/danizen/confsecrets.svg?branch=master)](https://travis-ci.org/danizen/confsecrets) [![Coverage Status](https://coveralls.io/repos/github/danizen/confsecrets/badge.svg?branch=master)](https://coveralls.io/github/danizen/confsecrets?branch=master)\n\nA simple utility module to symmetrically encrypt/decrypt application secrets.\n\n## Description\n\nIt is often difficult for developers to secure passwords for databases, search\nengines, directory services, etc.  Security wishes to make sure these secrets\nare centralized, but this adds a dependency on an external service, not to\nmention code complexity.\n\nSeveral solutions exist, but these are often silos without any abstraction built\naround them.\n\nThe goal of this project is to provide APIs that wrap the simplest solutions that\nare actually solutions, namely:\n - Keeping passwords as encrypted values on the filesystem, with a passphrase in the code.\n\nFuture versions will add the ability to keep the encrypted material in S3, or\nanother cloud storage provider, and to keep the passphrase from which a key is\nderived also in cloud storage.\n\n## Other Tools\n\n### pyjks\n\n- Doesn't support saving jceks\n- Can load from string, so we could use it as keystore format and add S3 and stuff\n\n### keyczar\n\n- Manages encryption, but doesn't support MFA keys - e.g. not a vault in which to store\n  encrypted material.\n- Doesn't directly support use of S3 or HashiCorp vault as a backend, only itself.\n- Doesn't offer management of secrets, just management of keys.\n\n### dynaconf\n\nSee https://www.dynaconf.com/ - this provides a superset of the features in confsecrets at present,\nbut also appears more complicated to use. I also cannot say dynaconf is up to U.S.Federal Government standards.\n\n### EC2 Secrets Manager\n\n- Again, this is a central play, and locks you in somewhat to the vendor.\n\n## Concept of Operation\n\nThe goal here is to reach the point where we can keep multiple secrets in the same \nencrypted wodge, decrypted with the same passwords, and provide some command-line over \nthem that is easily integrated into Django.  We want to act locally but think globally.\n\nHow about this:\n  - implement `confsecrets\\vault.py` which contains a `Vault` class that is a subclass of UserDict, maybe OrderedDict.\n  - The vault has the following init:\n\n          Vault(key=, salt=, path=)\n\n  - It encrypts using the the salt and key, converting the crypttext to base64.\n  - Encrypting immediately flushes the file that has been loaded\n  - On decrypt, it checks to see if the file has changed, and reloads the underlying data in that case.\n  - On decrypt, it reverses the process.\n\nThere is a concept of a \"default vault\" whose configuration is controlled by environment variables or through the API.\nThe \"default vault\" is is a singleton.   \n\nDjango integration is provided via a `confsecrets.django` application that allows the configuration to be provided by settings:\n\n    CONFSECRETS_SALT = b'89982hto'\n    CONFSECRETS_KEY = 'This is not an example'\n    CONFSECRETS_VAULT = os.path.join(BASE_DIR, 'vault.yaml')\n\nThis initializes the default vault during configuration freeze. Otherwise, the default vault's configuration is controlled by the environment variables.\n\nThis is secure as long as the vault file is not stored in git, and then it becomes obfuscation. Alternatively, the vault file\ncould be stored in the project, but the key is external to the git repository.\n\nSaving secrets becomes easy through a command-line/management command to populate the vault:\n\n  * `list` - lists the secrets stored in the vault, along with their value\n  * `write \u003cname\u003e \u003cvalue\u003e` - uses value if present, otherwise uses stdin\n  * `read \u003cname\u003e` - typical options, outputs the secret to the stdout\n  * `rm \u003cname\u003e` - removes an encrypted value from the vault\n\nWith the system configured, dealing with the vault becomes as easy as using Secret objects:\n\n    ELASTICSEARCH_PASSWORD = Secret('name')\n\nTo access it, you can treat it like a string:\n\n    from django.conf import settings\n\n    settings.ES_PASSWORD.decrypt()\n\nThe secret also acts like a string:\n\n    int(str(settings.ES_PASSWORD))\n\nor:\n\n    auth_string = \"%s:%s\" % (username, settings.ES_PASSWORD)\n  \nThis will fail for a number of reasons with clear exceptions:\n   - If  the configuration is not available via settings or environment variables\n   - If the vault is not-present\n   - If the vault doesn't have that key in it\n\nVault would then know how to deal with the operations described above.\n\n## Self-critique\n\nThis way of doing things does not fully comply the [Twelve-Factor App](https://12factor.net/) way of managing the environment.  Django's settings are similarly response to the environment while recognizing that configuration solely via the environment is complicated.\n\n## Roadmap\n\nNot sure on the priority of these:\n\n- Add support for placing the vault on S3.  Vault becomes polymorphic because if path is an URL, then we will create a different sub-class of `Vault` using an override of `__new__`.  A local path vault is still standard.\n\n- Separate cli from Django management commands.\n\n- Add support for placing the passphrase on S3 similarly.\n\n- Support secret versioning, so that it is possible for a developer to push a new value for a password from the desktop,\n  and then change the password to some backend.\n\n- Add support for a default value for a secret, so that you get the default instead of KeyError\n\n- Add support/integration for Flask - it can surely be used without this because pbe, secret, and vault sub-modules are independent.\n\n- Move to cryptodome once that package is out of Beta.\n\n## Status\n\nHave implemented the `Vault`, `DefaultVault`, and initial `Secret` facilities.  Django management commands and integration needs tests.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanizen%2Fconfsecrets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanizen%2Fconfsecrets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanizen%2Fconfsecrets/lists"}