{"id":24669316,"url":"https://github.com/tpritc/verboten_keys","last_synced_at":"2025-10-08T05:32:13.092Z","repository":{"id":39679473,"uuid":"284959713","full_name":"tpritc/verboten_keys","owner":"tpritc","description":"Verboten Keys is a last line of defense to help prevent you and your team from accidentally leaking private information via your APIs.","archived":false,"fork":false,"pushed_at":"2025-07-22T05:48:54.000Z","size":80,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-29T05:48:54.541Z","etag":null,"topics":["rack","rails","ruby","security"],"latest_commit_sha":null,"homepage":"https://rubygems.org/gems/verboten_keys","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tpritc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-08-04T11:30:21.000Z","updated_at":"2025-06-22T19:39:46.000Z","dependencies_parsed_at":"2023-02-11T04:30:28.092Z","dependency_job_id":"b6fc35ce-0784-49f8-9ce4-be0bbc2dad6a","html_url":"https://github.com/tpritc/verboten_keys","commit_stats":{"total_commits":20,"total_committers":3,"mean_commits":6.666666666666667,"dds":"0.44999999999999996","last_synced_commit":"a6b1f8630249dee1e5d375506b867b6987295cbc"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/tpritc/verboten_keys","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpritc%2Fverboten_keys","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpritc%2Fverboten_keys/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpritc%2Fverboten_keys/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpritc%2Fverboten_keys/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tpritc","download_url":"https://codeload.github.com/tpritc/verboten_keys/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tpritc%2Fverboten_keys/sbom","scorecard":{"id":896205,"data":{"date":"2025-08-11","repo":{"name":"github.com/tpritc/verboten_keys","commit":"3c8f1d138c1d2910c475a13fca09fd2fdf93eb10"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","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":"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":"Maintained","score":7,"reason":"9 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 7","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/2 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":"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Info: no jobLevel write permissions found"],"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":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/tpritc/verboten_keys/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/tpritc/verboten_keys/ci.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/tpritc/verboten_keys/ci.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/tpritc/verboten_keys/ci.yml/main?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned"],"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":"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.txt:0","Info: FSF or OSI recognized license: MIT License: LICENSE.txt: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":-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 'main'"],"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 29 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"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-353f-x4gh-cqq8"],"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-24T13:48:32.415Z","repository_id":39679473,"created_at":"2025-08-24T13:48:32.415Z","updated_at":"2025-08-24T13:48:32.415Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278892199,"owners_count":26063950,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-08T02:00:06.501Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["rack","rails","ruby","security"],"created_at":"2025-01-26T09:29:13.609Z","updated_at":"2025-10-08T05:32:13.086Z","avatar_url":"https://github.com/tpritc.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Verboten Keys\n\nVerboten Keys is a last line of defense to help prevent you and your team from accidentally leaking private information via your APIs. It's Rack middleware that seamlessly integrates into any Rails or Sinatra application (or really anything that's based on Rack) and strips out any data that matches your list of forbidden keys.\n\nIt's a quick, easy, set-it-and-forget-it way to have the peace-of-mind that nothing's getting out of your API that shouldn't be.\n\n## What it does\n\nImagine you've got an API endpoint that returns a user's profile, and you've accidentally serialized the user incorrectly and it's now returning your entire user object serialized as JSON:\n\n```\nGET /api/v1/users/123\n{\n  'id': 123,\n  'name': 'Jane Doe',\n  'email': 'jane.doe@example.com',\n  'deepest_secret': 'Framed their sibling for a murder they commited'\n}\n```\n\nOh no, this is a disaster!\n\nIf only there was a way to automatically filter out accidents like this! This is where Verboten Keys helps out. If you had Verboten Keys in your application, and had `deepest_secret` set as a forbidden key, the exact same response would look like this:\n\n```\nGET /api/v1/users/123\n{\n  'id': 123,\n  'name': 'Jane Doe',\n  'email': 'jane.doe@example.com'\n}\n```\n\nVerboten Keys filtered out the leaking `deepest_secret` while leaving the rest of the request intact. When all else fails, we prevent you accidentally leaking sensitive data. Verboten Keys is your last line of defense.\n\n## Installation\n\nTo install Verboten Keys in your app, simply add this line to your application's `Gemfile` and run `bundle install`:\n\n```ruby\ngem 'verboten_keys'\n```\n\n### Rails\n\nIf you're using Rails, you don't need to do anything else to install Verboten Keys. The gem will automatically plug itself into Rails when your application boots.\n\n### Sinatra\n\nIf your application is using Sinatra, simply add the Verboten Keys middleware into your app the same way you would any other piece of middleware:\n\n```ruby\nrequire 'sinatra'\nrequire 'verboten_keys'\n\nuse Rack::Lint\nuse VerbotenKeys::Middleware\n\nget '/hello' do\n  { greeting: 'Hello, world!' }\nend\n```\n\nYou should include it last, so nothing gets missed when the middleware parses and evaluates your application's response.\n\n## Configuration\n\nEvery application has its own security needs, and Verboten Keys is designed to be configurable, so you can get it just so. To configure Verboten Keys, simply call its `configure` method, which yields a block with the current configuration:\n\n```ruby\n# In config/initializers/verboten_keys.rb:\n\nVerbotenKeys.configure do |config|\n  config.forbidden_keys = [:deepest_secret, :secret_token]\n  config.strategy = :remove\n  config.include_rails_filter_parameters = true\nend\n```\n\nThe `forbidden_keys` option lets you set the keys that will be filtered out of the response. It takes an array of symbols, and will raise an error if it's not in the right format. You should include all of the columns and attributes you absolutely do not want to ever leak from your API. The default value is `[]`, which means you need to set this up otherwise Verboten Keys won't do anything.\n\nThe `strategy` option lets you pick how Verboten Keys should handle a forbidden key it finds. The default value is `:remove`. Acceptable options are `:remove`, `:nullify`, and `:raise`:\n\n* `:remove` removes the key-value pair from the JSON response body, so it looks like the JSON object never had the key-value pair in the first place.\n* `:nullify` leaves the key in the JSON response, but it will nullify the value, so any forbidden values will always appear to be `nil`.\n* `:raise` will raise a `VerbotenKeys::ForbiddenKeyError` if a forbidden key is found in the response body.\n\nThe `include_rails_filter_parameters` option automatically includes Rails' existing `config.filter_parameters` in the forbidden keys list. The default value is `false`. When enabled with `true`, Verboten Keys automatically merges Rails' filter parameters with any custom `forbidden_keys` you specify.\n\n\u003e [!WARNING]\n\u003e This option is only available for Rails apps. If you enable it in a non-Rails app, it will raise an error.\n\n## Contributing\n\nBug reports and pull requests are welcome on [GitHub](https://github.com/tpritc/verboten-keys). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/tpritc/verboten-keys/blob/main/CODE_OF_CONDUCT.md) while interacting in the project's codebases, issue trackers, chat rooms, and mailing lists.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). If you or your organization need a custom, commercial license for any reason, [send me an email](mailto:tom@tpritc.com) and I'll be happy to set something up for you.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftpritc%2Fverboten_keys","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftpritc%2Fverboten_keys","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftpritc%2Fverboten_keys/lists"}