My opinionated ruby on rails template
at main 97 lines 3.7 kB view raw
1# frozen_string_literal: true 2 3say 'Setting up security hardening...', :green 4 5gem 'rack-cors' 6# bundler-audit included by Rails 8 7 8say ' Content Security Policy disabled by default (can be enabled in initializer)...', :cyan 9initializer 'content_security_policy.rb', <<~RUBY 10 # frozen_string_literal: true 11 12 # Content Security Policy (CSP) is disabled by default for flexibility. 13 # Uncomment and configure the policy below if you need stricter security controls. 14 # See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy 15 16 # Rails.application.configure do 17 # config.content_security_policy do |policy| 18 # policy.default_src :self 19 # policy.font_src :self, :data, 'https://fonts.gstatic.com' 20 # policy.img_src :self, :data, :blob 21 # policy.object_src :none 22 # policy.script_src :self 23 # policy.style_src :self, :unsafe_inline, 'https://fonts.googleapis.com' 24 # policy.frame_ancestors :self 25 # policy.base_uri :self 26 # policy.form_action :self 27 # 28 # # Allow connections to same origin and websockets 29 # policy.connect_src :self, :wss 30 # 31 # # Report violations to your error tracking service 32 # # policy.report_uri '/csp-report' 33 # end 34 # 35 # # Generate nonce for inline scripts/styles 36 # # Use <%= csp_meta_tag %> in your layout and 37 # # <%= javascript_tag nonce: true %> for inline scripts 38 # config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } 39 # config.content_security_policy_nonce_directives = %w[script-src style-src] 40 # 41 # # Report CSP violations without enforcing (useful for rollout) 42 # # config.content_security_policy_report_only = true 43 # end 44RUBY 45 46say ' Configuring CORS...', :cyan 47initializer 'cors.rb', <<~RUBY 48 # frozen_string_literal: true 49 50 # Configure Cross-Origin Resource Sharing (CORS) 51 # See: https://github.com/cyu/rack-cors 52 53 Rails.application.config.middleware.insert_before 0, Rack::Cors do 54 allow do 55 # Allow requests from your frontend domain 56 origins Rails.env.development? ? 'localhost:3000' : ENV.fetch('CORS_ORIGINS', '').split(',') 57 58 resource '/api/*', 59 headers: :any, 60 methods: %i[get post put patch delete options head], 61 credentials: true, 62 max_age: 86_400 63 64 # Health checks should be accessible 65 resource '/health*', 66 headers: :any, 67 methods: [:get] 68 end 69 end 70RUBY 71 72say ' Adding security headers...', :cyan 73initializer 'secure_headers.rb', <<~RUBY 74 # frozen_string_literal: true 75 76 # Additional security headers configured via middleware 77 Rails.application.config.action_dispatch.default_headers = { 78 'X-Frame-Options' => 'SAMEORIGIN', 79 'X-Content-Type-Options' => 'nosniff', 80 'X-XSS-Protection' => '0', # Disabled as per modern best practices 81 'X-Permitted-Cross-Domain-Policies' => 'none', 82 'Referrer-Policy' => 'strict-origin-when-cross-origin', 83 'Permissions-Policy' => 'accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()' 84 } 85RUBY 86 87say ' Skipping CSP meta tag...', :cyan 88# CSP meta tag is not added since CSP is disabled by default 89# Uncomment below if you enable CSP in the initializer 90# inject_into_file 'app/views/layouts/application.html.erb', after: "<%= csrf_meta_tags %>\n" do 91# " <%= csp_meta_tag %>\n" 92# end 93 94say 'Security hardening configured!', :green 95say ' CSP headers disabled by default (review initializer to enable)', :cyan 96say ' CORS configured for API routes', :cyan 97say ' Run `bundle audit` to check for vulnerabilities', :yellow