{"id":13428144,"url":"https://github.com/github/secure_headers","last_synced_at":"2026-02-20T21:27:05.084Z","repository":{"id":5903857,"uuid":"7122663","full_name":"github/secure_headers","owner":"github","description":"Manages application of security headers with many safe defaults","archived":false,"fork":false,"pushed_at":"2026-02-09T17:38:38.000Z","size":10677,"stargazers_count":3303,"open_issues_count":21,"forks_count":253,"subscribers_count":166,"default_branch":"main","last_synced_at":"2026-02-16T19:37:56.910Z","etag":null,"topics":["content-security-policy","cookie","csp","hsts","middleware","rack","referrer-policy","ruby","secure-headers","xframe-options"],"latest_commit_sha":null,"homepage":"","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/github.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2012-12-12T01:41:57.000Z","updated_at":"2026-02-15T14:53:49.000Z","dependencies_parsed_at":"2024-11-19T09:06:22.751Z","dependency_job_id":"eb188bad-b4e3-475f-a0da-fba9fe35be12","html_url":"https://github.com/github/secure_headers","commit_stats":{"total_commits":833,"total_committers":106,"mean_commits":"7.8584905660377355","dds":0.7214885954381753,"last_synced_commit":"7a23cb6b350b024a786e163e81c902552b9c484f"},"previous_names":["twitter/secureheaders","twitter/secure_headers"],"tags_count":93,"template":false,"template_full_name":null,"purl":"pkg:github/github/secure_headers","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github%2Fsecure_headers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github%2Fsecure_headers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github%2Fsecure_headers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github%2Fsecure_headers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/github","download_url":"https://codeload.github.com/github/secure_headers/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/github%2Fsecure_headers/sbom","scorecard":{"id":428226,"data":{"date":"2025-08-11","repo":{"name":"github.com/github/secure_headers","commit":"8b1029ca6d9a424b903b5beebcd88cbdadf43f4b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":6.7,"checks":[{"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":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":"Code-Review","score":9,"reason":"Found 14/15 approved changesets -- score normalized to 9","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":"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":"Token-Permissions","score":9,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: jobLevel 'contents' permission set to 'write': .github/workflows/github-release.yml:11","Info: topLevel 'contents' permission set to 'read': .github/workflows/build.yml:5","Warn: no topLevel permission defined: .github/workflows/github-release.yml:1"],"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":"Pinned-Dependencies","score":6,"reason":"dependency not pinned by hash detected -- score normalized to 6","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/github/secure_headers/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/github-release.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/github/secure_headers/github-release.yml/main?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   1 out of   1 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":"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":"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: MIT License: 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":-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":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: github.com/github/.github/SECURITY.md:1","Info: Found linked content: github.com/github/.github/SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: github.com/github/.github/SECURITY.md:1","Info: Found text in security policy: github.com/github/.github/SECURITY.md:1"],"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":"Branch-Protection","score":3,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'main'","Info: 'force pushes' disabled on branch 'main'","Info: 'branch protection settings apply to administrators' is required to merge on branch 'main'","Warn: branch 'main' does not require approvers","Warn: codeowners review is not required on branch 'main'","Info: status check found to merge onto on branch 'main'","Warn: PRs are not required to make changes on branch 'main'; or we don't have data to detect it.If you think it might be the latter, make sure to run Scorecard with a PAT or use Repo Rules (that are always public) instead of Branch Protection settings"],"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":4,"reason":"SAST tool is not run on all commits -- score normalized to 4","details":["Warn: 13 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"}}]},"last_synced_at":"2025-08-19T02:43:20.993Z","repository_id":5903857,"created_at":"2025-08-19T02:43:20.993Z","updated_at":"2025-08-19T02:43:20.993Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29665237,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-20T19:49:36.704Z","status":"ssl_error","status_checked_at":"2026-02-20T19:44:05.372Z","response_time":59,"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":["content-security-policy","cookie","csp","hsts","middleware","rack","referrer-policy","ruby","secure-headers","xframe-options"],"created_at":"2024-07-31T01:00:47.279Z","updated_at":"2026-02-20T21:27:05.047Z","avatar_url":"https://github.com/github.png","language":"Ruby","readme":"# Secure Headers [![Build + Test](https://github.com/github/secure_headers/actions/workflows/build.yml/badge.svg)](https://github.com/github/secure_headers/actions/workflows/build.yml)\n\n**main branch represents 7.x line**. See the [upgrading to 4.x doc](docs/upgrading-to-4-0.md), [upgrading to 5.x doc](docs/upgrading-to-5-0.md), [upgrading to 6.x doc](docs/upgrading-to-6-0.md) or [upgrading to 7.x doc](docs/upgrading-to-7-0.md) for instructions on how to upgrade. Bug fixes should go in the `6.x` branch for now.\n\nThe gem will automatically apply several headers that are related to security.  This includes:\n- Content Security Policy (CSP) - Helps detect/prevent XSS, mixed-content, and other classes of attack.  [CSP 2 Specification](https://www.w3.org/TR/CSP2/)\n  - https://csp.withgoogle.com\n  - https://csp.withgoogle.com/docs/strict-csp.html\n  - https://csp-evaluator.withgoogle.com\n- HTTP Strict Transport Security (HSTS) - Ensures the browser never visits the http version of a website. Protects from SSLStrip/Firesheep attacks.  [HSTS Specification](https://tools.ietf.org/html/rfc6797)\n- X-Frame-Options (XFO) - Prevents your content from being framed and potentially clickjacked. [X-Frame-Options Specification](https://tools.ietf.org/html/rfc7034)\n- X-XSS-Protection - [Cross site scripting heuristic filter for IE/Chrome](https://msdn.microsoft.com/en-us/library/dd565647\\(v=vs.85\\).aspx)\n- X-Content-Type-Options - [Prevent content type sniffing](https://msdn.microsoft.com/library/gg622941\\(v=vs.85\\).aspx)\n- x-download-options - [Prevent file downloads opening](https://msdn.microsoft.com/library/jj542450(v=vs.85).aspx)\n- x-permitted-cross-domain-policies - [Restrict Adobe Flash Player's access to data](https://www.adobe.com/devnet/adobe-media-server/articles/cross-domain-xml-for-streaming.html)\n- referrer-policy - [Referrer Policy draft](https://w3c.github.io/webappsec-referrer-policy/)\n- expect-ct - Only use certificates that are present in the certificate transparency logs. [expect-ct draft specification](https://datatracker.ietf.org/doc/draft-stark-expect-ct/).\n- clear-site-data - Clearing browser data for origin. [clear-site-data specification](https://w3c.github.io/webappsec-clear-site-data/).\n\nIt can also mark all http cookies with the Secure, HttpOnly and SameSite attributes. This is on default but can be turned off by using `config.cookies = SecureHeaders::OPT_OUT`.\n\n`secure_headers` is a library with a global config, per request overrides, and rack middleware that enables you customize your application settings.\n\n## Documentation\n\n- [Named overrides and appends](docs/named_overrides_and_appends.md)\n- [Per action configuration](docs/per_action_configuration.md)\n- [Cookies](docs/cookies.md)\n- [Hashes](docs/hashes.md)\n- [Sinatra Config](docs/sinatra.md)\n\n## Configuration\n\nIf you do not supply a `default` configuration, exceptions will be raised. If you would like to use a default configuration (which is fairly locked down), just call `SecureHeaders::Configuration.default` without any arguments or block.\n\nAll `nil` values will fallback to their default values. `SecureHeaders::OPT_OUT` will disable the header entirely.\n\n**Word of caution:**  The following is not a default configuration per se. It serves as a sample implementation of the configuration. You should read more about these headers and determine what is appropriate for your requirements.\n\n```ruby\nSecureHeaders::Configuration.default do |config|\n  config.cookies = {\n    secure: true, # mark all cookies as \"Secure\"\n    httponly: true, # mark all cookies as \"HttpOnly\"\n    samesite: {\n      lax: true # mark all cookies as SameSite=lax\n    }\n  }\n  # Add \"; preload\" and submit the site to hstspreload.org for best protection.\n  config.hsts = \"max-age=#{1.week.to_i}\"\n  config.x_frame_options = \"DENY\"\n  config.x_content_type_options = \"nosniff\"\n  config.x_xss_protection = \"1; mode=block\"\n  config.x_download_options = \"noopen\"\n  config.x_permitted_cross_domain_policies = \"none\"\n  config.referrer_policy = %w(origin-when-cross-origin strict-origin-when-cross-origin)\n  config.csp = {\n    # \"meta\" values. these will shape the header, but the values are not included in the header.\n    preserve_schemes: true, # default: false. Schemes are removed from host sources to save bytes and discourage mixed content.\n    disable_nonce_backwards_compatibility: true, # default: false. If false, `unsafe-inline` will be added automatically when using nonces. If true, it won't. See #403 for why you'd want this.\n\n    # directive values: these values will directly translate into source directives\n    default_src: %w('none'),\n    base_uri: %w('self'),\n    child_src: %w('self'), # if child-src isn't supported, the value for frame-src will be set.\n    connect_src: %w(wss:),\n    font_src: %w('self' data:),\n    form_action: %w('self' github.com),\n    frame_ancestors: %w('none'),\n    img_src: %w(mycdn.com data:),\n    manifest_src: %w('self'),\n    media_src: %w(utoob.com),\n    object_src: %w('self'),\n    sandbox: true, # true and [] will set a maximally restrictive setting\n    plugin_types: %w(application/x-shockwave-flash),\n    script_src: %w('self'),\n    script_src_elem: %w('self'),\n    script_src_attr: %w('self'),\n    style_src: %w('unsafe-inline'),\n    style_src_elem: %w('unsafe-inline'),\n    style_src_attr: %w('unsafe-inline'),\n    worker_src: %w('self'),\n    upgrade_insecure_requests: true, # see https://www.w3.org/TR/upgrade-insecure-requests/\n    report_uri: %w(https://report-uri.io/example-csp)\n  }\n  # This is available only from 3.5.0; use the `report_only: true` setting for 3.4.1 and below.\n  config.csp_report_only = config.csp.merge({\n    img_src: %w(somewhereelse.com),\n    report_uri: %w(https://report-uri.io/example-csp-report-only)\n  })\nend\n```\n\n### Deprecated Configuration Values\n* `block_all_mixed_content` - this value is deprecated in favor of `upgrade_insecure_requests`. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/block-all-mixed-content for more information.\n\n## Default values\n\nAll headers except for PublicKeyPins and ClearSiteData have a default value. The default set of headers is:\n\n```\ncontent-security-policy: default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline'\nstrict-transport-security: max-age=631138519\nx-content-type-options: nosniff\nx-download-options: noopen\nx-frame-options: sameorigin\nx-permitted-cross-domain-policies: none\nx-xss-protection: 0\n```\n\n## API configurations\n\nWhich headers you decide to use for API responses is entirely a personal choice. Things like X-Frame-Options seem to have no place in an API response and would be wasting bytes. While this is true, browsers can do funky things with non-html responses. At the minimum, we suggest CSP:\n\n```ruby\nSecureHeaders::Configuration.override(:api) do |config|\n  config.csp = { default_src: 'none' }\n  config.hsts = SecureHeaders::OPT_OUT\n  config.x_frame_options = SecureHeaders::OPT_OUT\n  config.x_content_type_options = SecureHeaders::OPT_OUT\n  config.x_xss_protection = SecureHeaders::OPT_OUT\n  config.x_permitted_cross_domain_policies = SecureHeaders::OPT_OUT\nend\n```\n\nHowever, I would consider these headers anyways depending on your load and bandwidth requirements.\n\n## Acknowledgements\n\nThis project originated within the Security team at Twitter. An archived fork from the point of transition is here: https://github.com/twitter-archive/secure_headers.\n\nContributors include:\n* Neil Matatall @oreoshake\n* Chris Aniszczyk\n* Artur Dryomov\n* Bjørn Mæland\n* Arthur Chiu\n* Jonathan Viney\n* Jeffrey Horn\n* David Collazo\n* Brendon Murphy\n* William Makley\n* Reed Loden\n* Noah Kantrowitz\n* Wyatt Anderson\n* Salimane Adjao Moustapha\n* Francois Chagnon\n* Jeff Hodges\n* Ian Melven\n* Darío Javier Cravero\n* Logan Hasson\n* Raul E Rangel\n* Steve Agalloco\n* Nate Collings\n* Josh Kalderimis\n* Alex Kwiatkowski\n* Julich Mera\n* Jesse Storimer\n* Tom Daniels\n* Kolja Dummann\n* Jean-Philippe Doyle\n* Blake Hitchcock\n* vanderhoorn\n* orthographic-pedant\n* Narsimham Chelluri\n\nIf you've made a contribution and see your name missing from the list, make a PR and add it!\n\n## Similar libraries\n\n* Rack [rack-secure_headers](https://github.com/frodsan/rack-secure_headers)\n* Node.js (express) [helmet](https://github.com/helmetjs/helmet) and [hood](https://github.com/seanmonstar/hood)\n* Node.js (hapi) [blankie](https://github.com/nlf/blankie)\n* ASP.NET - [NWebsec](https://github.com/NWebsec/NWebsec/wiki)\n* Python - [django-csp](https://github.com/mozilla/django-csp) + [commonware](https://github.com/jsocol/commonware/); [django-security](https://github.com/sdelements/django-security), [secure](https://github.com/TypeError/secure)\n* Go - [secureheader](https://github.com/kr/secureheader)\n* Elixir [secure_headers](https://github.com/anotherhale/secure_headers)\n* Dropwizard [dropwizard-web-security](https://github.com/palantir/dropwizard-web-security)\n* Ember.js [ember-cli-content-security-policy](https://github.com/rwjblue/ember-cli-content-security-policy/)\n* PHP [secure-headers](https://github.com/BePsvPT/secure-headers)\n","funding_links":[],"categories":["Testing","Ruby","Ruby (88)","Hardening"],"sub_categories":["Security","WebServers"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgithub%2Fsecure_headers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgithub%2Fsecure_headers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgithub%2Fsecure_headers/lists"}