header_guard 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c75619d9c42867f9748a930f0b82569401db387229f99fff65338652df173fd5
4
+ data.tar.gz: cb0c87a39bfd0157ef054f8386aaa38a78c6f207de292d857509ed210cda3e6a
5
+ SHA512:
6
+ metadata.gz: 1f1845082fd922cc7636d97023edad724ac94fe36e702c71dee42d354fda3f9e2dc012a3e77af9f6ecc65f31d171c424219a7cc0b5746ef094a9b038dc5a8dcb
7
+ data.tar.gz: 724b5061a5c62e729b25c13ddf51e9af95e5926f6d97689116534353f7ec1f6228d8e0894bd75a5613602c0277052ecd4a6f769a75d9acbab199a783949ba1ee
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in header_guard.gemspec
6
+ gemspec
7
+
8
+ # Dependencies for development and testing
9
+ group :development, :test do
10
+ gem "rack"
11
+ gem "rspec", "~> 3.12"
12
+ gem "rack-test"
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,38 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ header_guard (0.1.0)
5
+ rack (~> 3.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ diff-lcs (1.6.2)
11
+ rack (3.2.3)
12
+ rack-test (2.2.0)
13
+ rack (>= 1.3)
14
+ rspec (3.13.1)
15
+ rspec-core (~> 3.13.0)
16
+ rspec-expectations (~> 3.13.0)
17
+ rspec-mocks (~> 3.13.0)
18
+ rspec-core (3.13.5)
19
+ rspec-support (~> 3.13.0)
20
+ rspec-expectations (3.13.5)
21
+ diff-lcs (>= 1.2.0, < 2.0)
22
+ rspec-support (~> 3.13.0)
23
+ rspec-mocks (3.13.6)
24
+ diff-lcs (>= 1.2.0, < 2.0)
25
+ rspec-support (~> 3.13.0)
26
+ rspec-support (3.13.6)
27
+
28
+ PLATFORMS
29
+ x86_64-linux
30
+
31
+ DEPENDENCIES
32
+ header_guard!
33
+ rack
34
+ rack-test
35
+ rspec (~> 3.12)
36
+
37
+ BUNDLED WITH
38
+ 2.4.22
data/README.md ADDED
@@ -0,0 +1,167 @@
1
+ HeaderGuard
2
+ ===========
3
+
4
+ A robust and simple-to-use Rack middleware for enforcing modern HTTP security headers, including a highly configurable Content Security Policy (CSP).
5
+
6
+ HeaderGuard is designed to automatically inject essential security headers like HSTS, X-Content-Type-Options, X-Frame-Options, and a customizable Content Security Policy, making your application significantly more resilient against XSS, clickjacking, and other common attacks.
7
+
8
+ Installation
9
+ ------------
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'header_guard'
15
+ ```
16
+ And then execute:
17
+
18
+ ```bash
19
+ $ bundle install
20
+
21
+ ```
22
+ Usage
23
+ -----
24
+
25
+ ### Basic Setup (Recommended)
26
+
27
+ To enable all default, secure headers, simply include the middleware in your Rack application (e.g., in a Rails config/application.rb or a Rack config.ru).
28
+
29
+ **For Rails (in `config/application.rb`:**
30
+
31
+ ```ruby
32
+ config.middleware.use HeaderGuard::Middleware
33
+ ```
34
+ **For generic Rack apps (in config.ru):**
35
+
36
+ ```ruby
37
+ require 'header_guard'
38
+ use HeaderGuard::Middleware
39
+ run YourApp.new
40
+ ```
41
+ #### Environment-Specific Configuration (Development & Testing)
42
+ For local development and testing, you often need to disable the strictest headers, like HSTS (which forces HTTPS) or the CSP (which can block inline scripts for tools).
43
+ #### A. Disabling Headers in Development
44
+ The simplest approach is to conditionally skip the middleware based on the Rails/Rack environment.
45
+
46
+ **For Rails (in `config/application.rb`):**
47
+ ```ruby
48
+ unless Rails.env.development? || Rails.env.test?
49
+ config.middleware.use HeaderGuard::Middleware
50
+ end
51
+
52
+ ```
53
+ #### B. Relaxing Specific Headers for Development
54
+
55
+ If you only want to relax one or two headers (like HSTS) but keep the others, you can conditionally override the configuration.
56
+
57
+ **For Rails (in an initializer like `config/initializers/header_guard.rb`):**
58
+ ```ruby
59
+ # Start with an empty configuration hash
60
+ header_options = {}
61
+
62
+ if Rails.env.development? || Rails.env.test?
63
+ # 1. Disable Strict-Transport-Security for local HTTP development
64
+ header_options["Strict-Transport-Security"] = ""
65
+
66
+ # 2. Relax CSP to allow development tools that rely on 'unsafe-inline' scripts/styles
67
+ # NOTE: The HeaderGuard default CSP uses 'script-src "self"'. This adds the required dev overrides.
68
+ dev_csp = "script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';"
69
+ header_options[:content_security_policy] = dev_csp
70
+ end
71
+
72
+ # Apply the middleware with the environment-specific configuration
73
+ Rails.application.config.middleware.use HeaderGuard::Middleware, header_options
74
+
75
+ ```
76
+
77
+
78
+
79
+ ### Configuration Options for Customization
80
+
81
+ When integrating `HeaderGuard` into your project, you can pass an options hash to the middleware to customize or override any of the default security settings.
82
+
83
+ #### 1\. Overriding Standard Headers
84
+
85
+ Any key/value pair passed to the middleware that matches a standard header will override the default value.
86
+
87
+ | Header | Default Value | Purpose |
88
+ | ----- | ----- | ----- |
89
+ | `Strict-Transport-Security` | `max-age=31536000; includeSubDomains; preload` | Enforces HTTPS usage. |
90
+ | `X-Content-Type-Options` | `nosniff` | Prevents browser MIME-sniffing. |
91
+ | `X-Frame-Options` | `DENY` | Prevents clickjacking (set to SAMEORIGIN to allow framing on the same site). |
92
+ | `Referrer-Policy` | `strict-origin-when-cross-origin` | Controls referrer information sent with requests. |
93
+
94
+ **Example: Overriding X-Frame-Options and Referrer-Policy:**
95
+ ```ruby
96
+ # In a Rails initializer or config.ru
97
+ config.middleware.use HeaderGuard::Middleware,
98
+ "X-Frame-Options" => "SAMEORIGIN",
99
+ "Referrer-Policy" => "no-referrer"
100
+ ```
101
+ #### 2\. Custom Content Security Policy (CSP)
102
+
103
+ You can define a custom CSP string to replace the secure default provided by HeaderGuard.
104
+
105
+ ```ruby
106
+ custom_csp = "default-src 'self'; script-src 'self' [https://trusted.cdn.com](https://trusted.cdn.com);"
107
+ use HeaderGuard::Middleware, content_security_policy: custom_csp
108
+
109
+ ```
110
+ #### 3\. Report-Only Mode
111
+
112
+ To test a new CSP without enforcing it, set the report\_only option to true. This will use the Content-Security-Policy-Report-Only header instead of the standard Content-Security-Policy header.
113
+
114
+ ```ruby
115
+ # The browser will report violations but will not block resources.
116
+ config.middleware.use HeaderGuard::Middleware, report_only: true
117
+
118
+ ```
119
+
120
+ How It Works
121
+ ------------
122
+
123
+ HeaderGuard hooks into the Rack request lifecycle and performs the following actions on responses with a 2xx status code and a Content-Type of text/html:
124
+
125
+ 1. **Header Merging:** It takes the default security headers and merges them with any custom headers supplied during initialization, ensuring user configuration takes precedence.
126
+
127
+ 2. **Injection:** It injects the final set of standard security headers.
128
+
129
+ 3. **CSP Injection:** It injects the configured Content Security Policy, using either the standard enforcement header or the Report-Only header.
130
+
131
+
132
+ Development
133
+ -----------
134
+
135
+ After checking out the repository, run bundle install to install dependencies. Then, run rspec to execute the tests.
136
+ This gem uses RSpec and Rack::Test for its testing suite.
137
+ #### Prerequisites
138
+ To set up the development environment, you will need:
139
+ Ruby (version 2.6.6 or higher, as defined in the .gemspec)
140
+
141
+ Bundler
142
+ #### Setup and Testing
143
+ 1. Clone the repository:
144
+
145
+ ```bash
146
+ git clone https://github.com/danielefrisanco/headerguard
147
+ cd header_guard
148
+ ```
149
+
150
+ 2. Install all development and testing dependencies:
151
+
152
+ ```bash
153
+ bundle install
154
+ ```
155
+
156
+ 3. Run the test suite using RSpec:
157
+
158
+ ```bash
159
+ bundle exec rspec
160
+ ```
161
+
162
+ (This ensures all tests, including the critical configuration override tests, are passing.)
163
+
164
+ Contributing
165
+ ------------
166
+
167
+ Bug reports and pull requests are welcome on GitHub at [https://github.com/danielefrisanco/headerguard](https://github.com/danielefrisanco/headerguard).
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/header_guard/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "header_guard"
7
+ spec.version = HeaderGuard::VERSION
8
+ spec.authors = ["Gemini AI", "Daniele Frisanco"]
9
+ spec.email = ["daniele.frisanco@gmail.com"]
10
+
11
+ spec.summary = "A robust Rack middleware for enforcing modern HTTP security headers, including a highly configurable Content Security Policy (CSP)."
12
+ spec.description = "Designed for applications that require strong browser-side security, HeaderGuard automatically injects HSTS, X-Content-Type-Options, X-Frame-Options, and a customizable CSP. Ideal for SSO and high-security web services."
13
+ spec.homepage = "https://github.com/placeholder/header_guard"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 2.6.6"
16
+ # Specify which files should be added to the gem when it is released.
17
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
18
+ `git ls-files -z`.split("\x0").reject do |f|
19
+ (f == spec.full_name + ".gem") ||
20
+ f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
21
+ end
22
+ end
23
+ spec.bindir = "exe"
24
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
25
+ spec.require_paths = ["lib"]
26
+
27
+ # Runtime dependencies
28
+ spec.add_runtime_dependency "rack", "~> 3.0"
29
+
30
+ # Development dependencies
31
+ spec.add_development_dependency "rspec", "~> 3.12"
32
+ spec.add_development_dependency "rack-test"
33
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HeaderGuard
4
+ # The Rack middleware class responsible for injecting security headers.
5
+ class Middleware
6
+ # Initializes the middleware. It merges user-defined options over defaults.
7
+ #
8
+ # @param app [Object] The next application in the Rack stack.
9
+ # @param options [Hash] Configuration options for headers and CSP.
10
+ def initialize(app, options = {})
11
+ @app = app
12
+
13
+ # Use a copy of options for configuration extraction
14
+ config = options.dup
15
+
16
+ # Extract special configuration settings
17
+ custom_csp = config.delete(:content_security_policy)
18
+ @report_only = config.delete(:report_only) || false
19
+
20
+ # 1. Start with DEFAULT_HEADERS (from header_guard.rb)
21
+ # 2. Merge remaining options (which are custom headers) over the defaults.
22
+ # THIS IS THE FIX: By merging 'config' (which now only contains headers)
23
+ # over the defaults, the user's header values take precedence.
24
+ @headers = DEFAULT_HEADERS.merge(config).freeze
25
+
26
+ # Set the final CSP value and the header key based on report_only setting
27
+ @csp_value = custom_csp || DEFAULT_CSP
28
+ @csp_header_key = @report_only ? "Content-Security-Policy-Report-Only" : "Content-Security-Policy"
29
+ end
30
+
31
+ # The Rack application call method.
32
+ def call(env)
33
+ status, headers, body = @app.call(env)
34
+
35
+ # Only inject headers on successful (2xx) responses with HTML content.
36
+ # Exclude redirects, errors, and non-HTML assets (like JSON or images).
37
+ if (200..299).include?(status) && headers["Content-Type"]&.include?("text/html")
38
+
39
+ # Inject the standard headers
40
+ @headers.each do |key, value|
41
+ # We use assignment (=) here, not `||=`, to ensure the middleware
42
+ # overwrites any headers set by the application before it,
43
+ # adhering to the strong security posture.
44
+ headers[key] = value
45
+ end
46
+
47
+ # Inject the configured CSP header
48
+ headers[@csp_header_key] = @csp_value
49
+ end
50
+
51
+ [status, headers, body]
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HeaderGuard
4
+ # The current version of the HeaderGuard gem.
5
+ VERSION = "0.1.0"
6
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "header_guard/version"
4
+ require_relative "header_guard/middleware"
5
+
6
+ module HeaderGuard
7
+ # Standard security headers applied by default.
8
+ DEFAULT_HEADERS = {
9
+ # Strictly enforce HTTPS, preventing protocol downgrade attacks.
10
+ # 1 year (31536000 seconds) max-age is standard best practice.
11
+ "Strict-Transport-Security" => "max-age=31536000; includeSubDomains; preload",
12
+ # Prevent the browser from trying to guess the content type,
13
+ # which can lead to XSS attacks if it misinterprets a file as a script.
14
+ "X-Content-Type-Options" => "nosniff",
15
+ # Tells the browser which referrer information to include with requests.
16
+ # origin-when-cross-origin is a good balance of security and functionality.
17
+ "X-Frame-Options" => "DENY",
18
+ # Tells the browser which referrer information to include with requests.
19
+ # origin-when-cross-origin is a good balance of security and functionality.
20
+ "Referrer-Policy" => "strict-origin-when-cross-origin"
21
+ }.freeze
22
+
23
+ # Default Content Security Policy. This is a secure baseline.
24
+ # This serves as a strong baseline, allowing resources only from the same origin ('self'),
25
+ # and explicitly blocking all plugins, base tags, and object embeds.
26
+ #
27
+ # Note: A real application will likely need to customize this heavily
28
+ # to allow CDNs, analytics scripts, etc.
29
+ DEFAULT_CSP = (
30
+ "default-src 'self';" \
31
+ "base-uri 'self';" \
32
+ "font-src 'self' https: data:;" \
33
+ "form-action 'self';" \
34
+ "frame-ancestors 'none';" \
35
+ "object-src 'none';" \
36
+ "script-src 'self';" \
37
+ "style-src 'self' 'unsafe-inline' https:;" \
38
+ "upgrade-insecure-requests;" \
39
+ "block-all-mixed-content"
40
+ ).freeze
41
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: header_guard
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Gemini AI
8
+ - Daniele Frisanco
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2025-10-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rack
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '3.0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '3.0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rspec
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '3.12'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '3.12'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rack-test
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ description: Designed for applications that require strong browser-side security,
57
+ HeaderGuard automatically injects HSTS, X-Content-Type-Options, X-Frame-Options,
58
+ and a customizable CSP. Ideal for SSO and high-security web services.
59
+ email:
60
+ - daniele.frisanco@gmail.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - Gemfile
66
+ - Gemfile.lock
67
+ - README.md
68
+ - header_guard.gemspec
69
+ - lib/header_guard.rb
70
+ - lib/header_guard/middleware.rb
71
+ - lib/header_guard/version.rb
72
+ homepage: https://github.com/placeholder/header_guard
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 2.6.6
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubygems_version: 3.2.3
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: A robust Rack middleware for enforcing modern HTTP security headers, including
95
+ a highly configurable Content Security Policy (CSP).
96
+ test_files: []