@@ -26,6 +26,9 @@ module ActionDispatch # :nodoc:
26
26
# policy.report_uri "/csp-violation-report-endpoint"
27
27
# end
28
28
class ContentSecurityPolicy
29
+ class InvalidDirectiveError < StandardError
30
+ end
31
+
29
32
class Middleware
30
33
def initialize ( app )
31
34
@app = app
@@ -320,9 +323,9 @@ def build_directives(context, nonce, nonce_directives)
320
323
@directives . map do |directive , sources |
321
324
if sources . is_a? ( Array )
322
325
if nonce && nonce_directive? ( directive , nonce_directives )
323
- "#{ directive } #{ build_directive ( sources , context ) . join ( ' ' ) } 'nonce-#{ nonce } '"
326
+ "#{ directive } #{ build_directive ( directive , sources , context ) . join ( ' ' ) } 'nonce-#{ nonce } '"
324
327
else
325
- "#{ directive } #{ build_directive ( sources , context ) . join ( ' ' ) } "
328
+ "#{ directive } #{ build_directive ( directive , sources , context ) . join ( ' ' ) } "
326
329
end
327
330
elsif sources
328
331
directive
@@ -332,8 +335,22 @@ def build_directives(context, nonce, nonce_directives)
332
335
end
333
336
end
334
337
335
- def build_directive ( sources , context )
336
- sources . map { |source | resolve_source ( source , context ) }
338
+ def validate ( directive , sources )
339
+ sources . flatten . each do |source |
340
+ if source . include? ( ";" ) || source != source . gsub ( /[[:space:]]/ , "" )
341
+ raise InvalidDirectiveError , <<~MSG . squish
342
+ Invalid Content Security Policy #{ directive } : "#{ source } ".
343
+ Directive values must not contain whitespace or semicolons.
344
+ Please use multiple arguments or other directive methods instead.
345
+ MSG
346
+ end
347
+ end
348
+ end
349
+
350
+ def build_directive ( directive , sources , context )
351
+ resolved_sources = sources . map { |source | resolve_source ( source , context ) }
352
+
353
+ validate ( directive , resolved_sources )
337
354
end
338
355
339
356
def resolve_source ( source , context )
0 commit comments