File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1+ ## 2024-05-24 - [ Missing Default Security Headers]
2+ ** Vulnerability:** Newly generated Amber framework apps omit foundational HTTP security headers (e.g., XSS Protection, Content-Type Options).
3+ ** Learning:** The pipeline configuration in ` routes.cr.ecr ` lacked a dedicated middleware pipe to enforce baseline security headers for web routes.
4+ ** Prevention:** Always include a SecureHeaders middleware in the default web pipeline to ensure a defense-in-depth posture out of the box.
Original file line number Diff line number Diff line change 1+ require " ../../spec_helper"
2+
3+ module Amber::Pipe
4+ describe SecureHeaders do
5+ it " adds security headers to the response" do
6+ request = HTTP ::Request .new(" GET" , " /" )
7+ response = HTTP ::Server ::Response .new(IO ::Memory .new)
8+ context = HTTP ::Server ::Context .new(request, response)
9+
10+ pipe = SecureHeaders .new
11+ pipe.next = HTTP ::Handler ::HandlerProc .new { |ctx | }
12+
13+ pipe.call(context)
14+
15+ context.response.headers[" X-Content-Type-Options" ].should eq " nosniff"
16+ context.response.headers[" X-XSS-Protection" ].should eq " 1; mode=block"
17+ context.response.headers[" X-Frame-Options" ].should eq " SAMEORIGIN"
18+ context.response.headers[" Strict-Transport-Security" ].should eq " max-age=31536000; includeSubDomains"
19+ end
20+ end
21+ end
Original file line number Diff line number Diff line change @@ -10,6 +10,7 @@ Amber::Server.configure do
1010 plug Amber::Pipe::Session.new
1111 plug Amber::Pipe::Flash.new
1212 plug Amber::Pipe::CSRF.new
13+ plug Amber::Pipe::SecureHeaders.new
1314 end
1415
1516 pipeline :api do
Original file line number Diff line number Diff line change 1+ module Amber
2+ module Pipe
3+ # The SecureHeaders pipe sets security-related HTTP headers to help
4+ # protect against common vulnerabilities like XSS, clickjacking, and MIME sniffing.
5+ class SecureHeaders < Base
6+ def call (context : HTTP ::Server ::Context )
7+ headers = context.response.headers
8+
9+ # Prevent browser from guessing the MIME type
10+ headers[" X-Content-Type-Options" ] ||= " nosniff"
11+
12+ # Enable XSS filtering in browsers
13+ headers[" X-XSS-Protection" ] ||= " 1; mode=block"
14+
15+ # Prevent clickjacking by not allowing the page to be framed
16+ headers[" X-Frame-Options" ] ||= " SAMEORIGIN"
17+
18+ # Enforce HTTPS connections (if using HTTPS)
19+ # Note: In a real production app, you might want to configure max-age or includeSubDomains
20+ headers[" Strict-Transport-Security" ] ||= " max-age=31536000; includeSubDomains"
21+
22+ call_next(context)
23+ end
24+ end
25+ end
26+ end
You can’t perform that action at this time.
0 commit comments