57 lines
2.3 KiB
Ruby
57 lines
2.3 KiB
Ruby
module Api
|
|
class CspController < ApplicationController
|
|
# CSP violation reports don't need authentication
|
|
skip_before_action :verify_authenticity_token
|
|
allow_unauthenticated_access
|
|
|
|
# POST /api/csp-violation-report
|
|
def violation_report
|
|
# Parse CSP violation report
|
|
report_data = JSON.parse(request.body.read)
|
|
csp_report = report_data['csp-report']
|
|
|
|
# Validate that we have a proper CSP report
|
|
unless csp_report.is_a?(Hash) && csp_report.present?
|
|
Rails.logger.warn "Received empty or invalid CSP violation report"
|
|
head :bad_request
|
|
return
|
|
end
|
|
|
|
# Log the violation for security monitoring
|
|
Rails.logger.warn "CSP Violation Report:"
|
|
Rails.logger.warn " Blocked URI: #{csp_report['blocked-uri']}"
|
|
Rails.logger.warn " Document URI: #{csp_report['document-uri']}"
|
|
Rails.logger.warn " Referrer: #{csp_report['referrer']}"
|
|
Rails.logger.warn " Violated Directive: #{csp_report['violated-directive']}"
|
|
Rails.logger.warn " Original Policy: #{csp_report['original-policy']}"
|
|
Rails.logger.warn " User Agent: #{request.user_agent}"
|
|
Rails.logger.warn " IP Address: #{request.remote_ip}"
|
|
|
|
# Emit structured event for CSP violation
|
|
# This allows multiple subscribers to process the event (Sentry, local logging, etc.)
|
|
Rails.event.notify("csp.violation", {
|
|
blocked_uri: csp_report['blocked-uri'],
|
|
document_uri: csp_report['document-uri'],
|
|
referrer: csp_report['referrer'],
|
|
violated_directive: csp_report['violated-directive'],
|
|
original_policy: csp_report['original-policy'],
|
|
disposition: csp_report['disposition'],
|
|
effective_directive: csp_report['effective-directive'],
|
|
source_file: csp_report['source-file'],
|
|
line_number: csp_report['line-number'],
|
|
column_number: csp_report['column-number'],
|
|
status_code: csp_report['status-code'],
|
|
user_agent: request.user_agent,
|
|
ip_address: request.remote_ip,
|
|
current_user_id: Current.user&.id,
|
|
timestamp: Time.current,
|
|
session_id: Current.session&.id
|
|
})
|
|
|
|
head :no_content
|
|
rescue JSON::ParserError => e
|
|
Rails.logger.error "Invalid CSP violation report: #{e.message}"
|
|
head :bad_request
|
|
end
|
|
end
|
|
end |