Skip to content

7.2 release - #566

Merged
fletchto99 merged 12 commits into
mainfrom
feature-7.2
Feb 20, 2026
Merged

7.2 release#566
fletchto99 merged 12 commits into
mainfrom
feature-7.2

Conversation

Comment threadlib/secure_headers/task_helper.rb Fixed
Comment threadlib/secure_headers/task_helper.rb Dismissed
Comment threadlib/secure_headers/task_helper.rb Fixed
Comment threadlib/secure_headers/task_helper.rb Fixed
@denn-os
denn-osforce-pushed the feature-7.2 branch 3 times, most recently from 4f5686e to 930157eCompareDecember 16, 2025 23:08
Do not join cookies with new like if they weren't before
fix(middleware): ensure headers are wrapped with `Rack::Headers`
Add `Rack::Headers` wrapping to middleware to
prevent header manipulation issues. Added a test
to verify cookies remain as an array when flagged
if already in array format.
obrieand others added 4 commits December 17, 2025 14:00
While this gem now uses lowercase headers, the Rails default configuration still
defines non-lowercase headers. As a result, our Railtie will not remove those
conflicting headers.
This change ensures that we're accounting for both lowercase and non-lowercase
default headers in Rails.
CSP3 more explicitly calls this out:
> If path A consists of one character that is equal to the U+002F
> SOLIDUS character (/) and path B is empty, return "Matches".
A URL like `example.com/foo` will match a connect-src of `example.com`,
as well as `example.com/`, so having two connect-srcs listed like this
is redundant.
fix: allow URIs with schema to have trailing slashes normalised
Co-authored-by: Dusty Greif <dgreif@users.noreply.github.com>
Fix rake task file count output message
CopilotAIand others added 2 commits December 19, 2025 13:07
Co-authored-by: fletchto99 <718681+fletchto99@users.noreply.github.com>m>
Co-authored-by: fletchto99 <718681+fletchto99@users.noreply.github.com>
fletchto99and others added 5 commits December 19, 2025 13:13
closes#512
## All PRs:
* [x] Has tests
* [x] Documentation updated
## Adding a new header (Reporting-Endpoints)
**Is the header supported by any user agent?*
Yes - Chrome 116+, Edge 116+, Opera 102+ (via Reporting API)
**What does it do?**
Defines HTTP reporting endpoints for CSP violations and other
security/performance reports using the HTTP Reporting API
**What are the valid values?**
Comma-separated pairs of [name="url"] where url must be HTTPS (e.g.,
csp-violations="https://example.com/reports")
**Where does the specification live?** [MDN
Reporting-Endpoints](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Reporting-Endpoints)
and [MDN report-to
directive](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/report-to)
## Adding a new CSP directive (report-to)
**Is the directive supported by any user agent?** Yes - Chrome 69+, Edge 79+, Firefox 110+, Safari 15.1+
**What does it do?**
Specifies a named reporting endpoint (defined via Reporting-Endpoints
header) where CSP violations should be reported, replacing or
complementing report-uri
**What are the valid values?**
A single string endpoint name (e.g., report-to csp-violations), must
match a name defined in the Reporting-Endpoints header
---------
Co-authored-by: Kylie Stradley <kyfast@users.noreply.github.com>
@denn-os
denn-os marked this pull request as ready for review January 27, 2026 20:54
CopilotAI review requested due to automatic review settings January 27, 2026 20:54

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Aggregates the 7.2 release changes, including Rack 3 / Rails compatibility fixes, CSP enhancements (reporting + HTTP/HTTPS behavior), and an opt-out mechanism to fully disable secure_headers.

Changes:

  • Add SecureHeaders::Configuration.disable! to fully disable header injection and middleware behavior.
  • Improve CSP features: support report-to + reporting-endpoints, normalize trailing slashes in CSP sources, and omit upgrade-insecure-requests on HTTP requests.
  • Improve framework compatibility: Rack 3 header/cookie handling updates and Railtie removal of Rails default headers regardless of header casing; refactor hash-generation rake task into a helper.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.

Show a summary per file
FileDescription
spec/spec_helper.rbAdds reset helper for new disabled/noop configuration state.
spec/lib/secure_headers_spec.rbAdds/extends specs for disable!, CSP upgrade-insecure-requests behavior, report-to/reporting-endpoints.
spec/lib/secure_headers/task_helper_spec.rbNew specs for extracted rake-task helper behavior.
spec/lib/secure_headers/railtie_spec.rbNew specs to validate case-insensitive Rails default header removal.
spec/lib/secure_headers/middleware_spec.rbAdds coverage for Rack::Headers conversion, cookie handling, and disabled behavior.
spec/lib/secure_headers/headers/reporting_endpoints_spec.rbNew unit tests for Reporting-Endpoints header generation/validation.
spec/lib/secure_headers/headers/policy_management_spec.rbAdds validation coverage for new report_to directive type.
spec/lib/secure_headers/headers/content_security_policy_spec.rbAdds CSP tests for trailing-slash normalization and report-to formatting/order.
spec/lib/secure_headers/configuration_spec.rbAdds coverage for Configuration.disable! lifecycle and interactions.
lib/tasks/tasks.rakeRefactors hash generation task to use extracted helper and improves output message.
lib/secure_headers/task_helper.rbExtracts rake-task hashing logic into a reusable helper module.
lib/secure_headers/railtie.rbRemoves conflicting Rails default headers case-insensitively.
lib/secure_headers/middleware.rbImproves Rack 3 compatibility (Rack::Headers) and preserves Set-Cookie arrays when present.
lib/secure_headers/headers/reporting_endpoints.rbIntroduces Reporting-Endpoints header support + config validation.
lib/secure_headers/headers/policy_management.rbAdds report_to directive support and validation wiring.
lib/secure_headers/headers/content_security_policy.rbAdds report-to directive rendering and CSP source trailing-slash normalization.
lib/secure_headers/configuration.rbAdds disable!/disabled? and new reporting_endpoints configuration attribute + dup support.
lib/secure_headers.rbWires in reporting-endpoints, HTTP-specific CSP behavior, and documents upgrade-insecure-requests behavior in code comments.
README.mdDocuments report-to/reporting-endpoints usage and how to fully disable secure_headers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

# formatted header value based on the config.
def make_header(config = nil)
return if config.nil? || config == OPT_OUT
validate_config!(config)

CopilotAIJan 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make_header will emit a reporting-endpoints header with an empty value when config is an empty Hash (since format_endpoints({}) returns "" and generate_headers treats empty string as truthy). Consider treating an empty Hash like nil/OPT_OUT (return no header) or making validate_config! reject empty configs.

Suggested change
validate_config!(config)
validate_config!(config)
returnifconfig.is_a?(Hash) && config.empty?

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,123 @@
# frozen_string_literal: true
require "spec_helper"
require "secure_headers/task_helper"

CopilotAIJan 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This spec uses Tempfile.create but never requires the tempfile stdlib, which will cause NameError: uninitialized constant Tempfile in a clean test run. Add require "tempfile" near the top of the file (or in spec_helper.rb).

Suggested change
require"secure_headers/task_helper"
require"secure_headers/task_helper"
require"tempfile"

Copilot uses AI. Check for mistakes.
end
}.not_to raise_error

# After reset_config, disabled? returns nil (not false) because @disabled is removed

CopilotAIJan 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says disabled? returns nil (not false), but Configuration.disabled? is implemented as defined?(@disabled) && @disabled, which returns false when @disabled is removed. Please update the comment to match the actual behavior to avoid confusion.

Suggested change
# After reset_config, disabled? returns nil (not false) because @disabled is removed
# After reset_config, disabled? returns a falsy value because @disabled is removed

Copilot uses AI. Check for mistakes.
Comment on lines +164 to +173
def normalize_uri_paths(source_list)
source_list.map do |source|
# Normalize domains ending in a single / as without omitting the slash accomplishes the same.
# https://www.w3.org/TR/CSP3/#match-paths § 6.6.2.10 Step 2
begin
uri = URI(source)
if uri.path == "/"
next source.chomp("/")
end
rescue URI::InvalidURIError

CopilotAIJan 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

normalize_uri_paths calls URI(source)/rescues URI::InvalidURIError, but this file never requires the stdlib uri. In a clean Ruby process this will raise NameError: uninitialized constant URI. Add require "uri" (or equivalent) before using URI.

Copilot uses AI. Check for mistakes.
@fletchto99
fletchto99 merged commit 7f83b93 into mainFeb 20, 2026
21 checks passed
@fletchto99
fletchto99 deleted the feature-7.2 branch February 20, 2026 19:07
@tmaiertmaier mentioned this pull request Apr 1, 2026
2 tasks
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

10 participants

@denn-os@github-advanced-security@fletchto99@deril@obrie@keithamus@rahearn@KyFaSt