actionpack 5.2.0 → 6.1.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (156) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +408 -190
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -3
  5. data/lib/abstract_controller/base.rb +38 -4
  6. data/lib/abstract_controller/caching/fragments.rb +6 -22
  7. data/lib/abstract_controller/caching.rb +1 -1
  8. data/lib/abstract_controller/callbacks.rb +14 -2
  9. data/lib/abstract_controller/collector.rb +1 -2
  10. data/lib/abstract_controller/helpers.rb +106 -90
  11. data/lib/abstract_controller/railties/routes_helpers.rb +17 -1
  12. data/lib/abstract_controller/rendering.rb +9 -9
  13. data/lib/abstract_controller/translation.rb +11 -5
  14. data/lib/abstract_controller.rb +2 -0
  15. data/lib/action_controller/api.rb +4 -3
  16. data/lib/action_controller/base.rb +6 -9
  17. data/lib/action_controller/caching.rb +1 -3
  18. data/lib/action_controller/log_subscriber.rb +10 -7
  19. data/lib/action_controller/metal/basic_implicit_render.rb +1 -1
  20. data/lib/action_controller/metal/conditional_get.rb +19 -5
  21. data/lib/action_controller/metal/content_security_policy.rb +1 -2
  22. data/lib/action_controller/metal/cookies.rb +3 -1
  23. data/lib/action_controller/metal/data_streaming.rb +6 -7
  24. data/lib/action_controller/metal/default_headers.rb +17 -0
  25. data/lib/action_controller/metal/etag_with_template_digest.rb +4 -6
  26. data/lib/action_controller/metal/exceptions.rb +56 -2
  27. data/lib/action_controller/metal/flash.rb +5 -5
  28. data/lib/action_controller/metal/head.rb +7 -4
  29. data/lib/action_controller/metal/helpers.rb +14 -5
  30. data/lib/action_controller/metal/http_authentication.rb +25 -24
  31. data/lib/action_controller/metal/implicit_render.rb +5 -15
  32. data/lib/action_controller/metal/instrumentation.rb +13 -14
  33. data/lib/action_controller/metal/live.rb +39 -32
  34. data/lib/action_controller/metal/logging.rb +20 -0
  35. data/lib/action_controller/metal/mime_responds.rb +19 -4
  36. data/lib/action_controller/metal/parameter_encoding.rb +35 -4
  37. data/lib/action_controller/metal/params_wrapper.rb +33 -23
  38. data/lib/action_controller/metal/permissions_policy.rb +46 -0
  39. data/lib/action_controller/metal/redirecting.rb +7 -7
  40. data/lib/action_controller/metal/renderers.rb +4 -4
  41. data/lib/action_controller/metal/rendering.rb +8 -3
  42. data/lib/action_controller/metal/request_forgery_protection.rb +89 -36
  43. data/lib/action_controller/metal/rescue.rb +1 -1
  44. data/lib/action_controller/metal/streaming.rb +0 -1
  45. data/lib/action_controller/metal/strong_parameters.rb +181 -69
  46. data/lib/action_controller/metal/url_for.rb +1 -1
  47. data/lib/action_controller/metal.rb +12 -10
  48. data/lib/action_controller/railties/helpers.rb +1 -1
  49. data/lib/action_controller/renderer.rb +37 -13
  50. data/lib/action_controller/template_assertions.rb +1 -1
  51. data/lib/action_controller/test_case.rb +81 -70
  52. data/lib/action_controller.rb +7 -4
  53. data/lib/action_dispatch/http/cache.rb +34 -28
  54. data/lib/action_dispatch/http/content_disposition.rb +45 -0
  55. data/lib/action_dispatch/http/content_security_policy.rb +47 -24
  56. data/lib/action_dispatch/http/filter_parameters.rb +9 -8
  57. data/lib/action_dispatch/http/filter_redirect.rb +2 -3
  58. data/lib/action_dispatch/http/headers.rb +4 -4
  59. data/lib/action_dispatch/http/mime_negotiation.rb +31 -13
  60. data/lib/action_dispatch/http/mime_type.rb +43 -24
  61. data/lib/action_dispatch/http/parameters.rb +14 -23
  62. data/lib/action_dispatch/http/permissions_policy.rb +173 -0
  63. data/lib/action_dispatch/http/request.rb +45 -22
  64. data/lib/action_dispatch/http/response.rb +45 -25
  65. data/lib/action_dispatch/http/upload.rb +9 -1
  66. data/lib/action_dispatch/http/url.rb +82 -82
  67. data/lib/action_dispatch/journey/formatter.rb +55 -31
  68. data/lib/action_dispatch/journey/gtg/builder.rb +22 -37
  69. data/lib/action_dispatch/journey/gtg/simulator.rb +8 -7
  70. data/lib/action_dispatch/journey/gtg/transition_table.rb +6 -5
  71. data/lib/action_dispatch/journey/nfa/dot.rb +0 -11
  72. data/lib/action_dispatch/journey/nodes/node.rb +13 -11
  73. data/lib/action_dispatch/journey/parser.rb +13 -13
  74. data/lib/action_dispatch/journey/parser.y +1 -1
  75. data/lib/action_dispatch/journey/path/pattern.rb +21 -22
  76. data/lib/action_dispatch/journey/route.rb +10 -20
  77. data/lib/action_dispatch/journey/router/utils.rb +14 -12
  78. data/lib/action_dispatch/journey/router.rb +26 -34
  79. data/lib/action_dispatch/journey/routes.rb +1 -2
  80. data/lib/action_dispatch/journey/scanner.rb +10 -4
  81. data/lib/action_dispatch/journey/visitors.rb +1 -4
  82. data/lib/action_dispatch/journey.rb +0 -2
  83. data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
  84. data/lib/action_dispatch/middleware/callbacks.rb +2 -4
  85. data/lib/action_dispatch/middleware/cookies.rb +128 -109
  86. data/lib/action_dispatch/middleware/debug_exceptions.rb +43 -66
  87. data/lib/action_dispatch/middleware/debug_locks.rb +5 -5
  88. data/lib/action_dispatch/middleware/debug_view.rb +66 -0
  89. data/lib/action_dispatch/middleware/exception_wrapper.rb +75 -30
  90. data/lib/action_dispatch/middleware/flash.rb +2 -2
  91. data/lib/action_dispatch/middleware/host_authorization.rb +130 -0
  92. data/lib/action_dispatch/middleware/public_exceptions.rb +6 -3
  93. data/lib/action_dispatch/middleware/remote_ip.rb +14 -16
  94. data/lib/action_dispatch/middleware/request_id.rb +5 -6
  95. data/lib/action_dispatch/middleware/session/abstract_store.rb +15 -2
  96. data/lib/action_dispatch/middleware/session/cache_store.rb +11 -6
  97. data/lib/action_dispatch/middleware/session/cookie_store.rb +24 -19
  98. data/lib/action_dispatch/middleware/show_exceptions.rb +3 -2
  99. data/lib/action_dispatch/middleware/ssl.rb +20 -15
  100. data/lib/action_dispatch/middleware/stack.rb +57 -3
  101. data/lib/action_dispatch/middleware/static.rb +153 -93
  102. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  103. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  104. data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
  105. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +3 -1
  106. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  107. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +4 -2
  108. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +45 -35
  109. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
  110. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
  111. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +23 -4
  112. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
  113. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +6 -3
  114. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +4 -1
  115. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +104 -8
  116. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
  117. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  118. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +2 -2
  119. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -1
  120. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +2 -2
  121. data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
  122. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +24 -1
  123. data/lib/action_dispatch/railtie.rb +8 -2
  124. data/lib/action_dispatch/request/session.rb +17 -10
  125. data/lib/action_dispatch/request/utils.rb +28 -2
  126. data/lib/action_dispatch/routing/inspector.rb +101 -53
  127. data/lib/action_dispatch/routing/mapper.rb +156 -103
  128. data/lib/action_dispatch/routing/polymorphic_routes.rb +21 -19
  129. data/lib/action_dispatch/routing/redirection.rb +4 -4
  130. data/lib/action_dispatch/routing/route_set.rb +71 -69
  131. data/lib/action_dispatch/routing/url_for.rb +3 -3
  132. data/lib/action_dispatch/routing.rb +21 -20
  133. data/lib/action_dispatch/system_test_case.rb +54 -11
  134. data/lib/action_dispatch/system_testing/browser.rb +53 -16
  135. data/lib/action_dispatch/system_testing/driver.rb +11 -3
  136. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +49 -7
  137. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +8 -6
  138. data/lib/action_dispatch/testing/assertion_response.rb +0 -1
  139. data/lib/action_dispatch/testing/assertions/response.rb +4 -7
  140. data/lib/action_dispatch/testing/assertions/routing.rb +20 -8
  141. data/lib/action_dispatch/testing/assertions.rb +1 -1
  142. data/lib/action_dispatch/testing/integration.rb +61 -28
  143. data/lib/action_dispatch/testing/request_encoder.rb +3 -3
  144. data/lib/action_dispatch/testing/test_process.rb +29 -4
  145. data/lib/action_dispatch/testing/test_request.rb +3 -3
  146. data/lib/action_dispatch/testing/test_response.rb +4 -32
  147. data/lib/action_dispatch.rb +14 -7
  148. data/lib/action_pack/gem_version.rb +3 -3
  149. data/lib/action_pack.rb +1 -1
  150. metadata +39 -22
  151. data/lib/action_controller/metal/force_ssl.rb +0 -99
  152. data/lib/action_dispatch/http/parameter_filter.rb +0 -86
  153. data/lib/action_dispatch/journey/nfa/builder.rb +0 -78
  154. data/lib/action_dispatch/journey/nfa/simulator.rb +0 -49
  155. data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -120
  156. data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +0 -26
@@ -3,7 +3,6 @@
3
3
  require "rack/session/abstract/id"
4
4
  require "action_controller/metal/exceptions"
5
5
  require "active_support/security_utils"
6
- require "active_support/core_ext/string/strip"
7
6
 
8
7
  module ActionController #:nodoc:
9
8
  class InvalidAuthenticityToken < ActionControllerError #:nodoc:
@@ -18,7 +17,7 @@ module ActionController #:nodoc:
18
17
  # access. When a request reaches your application, \Rails verifies the received
19
18
  # token with the token in the session. All requests are checked except GET requests
20
19
  # as these should be idempotent. Keep in mind that all session-oriented requests
21
- # should be CSRF protected, including JavaScript and HTML requests.
20
+ # are CSRF protected by default, including JavaScript and HTML requests.
22
21
  #
23
22
  # Since HTML and JavaScript requests are typically made from the browser, we
24
23
  # need to ensure to verify request authenticity for the web browser. We can
@@ -31,31 +30,30 @@ module ActionController #:nodoc:
31
30
  # URL on your site. When your JavaScript response loads on their site, it executes.
32
31
  # With carefully crafted JavaScript on their end, sensitive data in your JavaScript
33
32
  # response may be extracted. To prevent this, only XmlHttpRequest (known as XHR or
34
- # Ajax) requests are allowed to make GET requests for JavaScript responses.
33
+ # Ajax) requests are allowed to make requests for JavaScript responses.
35
34
  #
36
- # It's important to remember that XML or JSON requests are also affected and if
37
- # you're building an API you should change forgery protection method in
38
- # <tt>ApplicationController</tt> (by default: <tt>:exception</tt>):
35
+ # Subclasses of <tt>ActionController::Base</tt> are protected by default with the
36
+ # <tt>:exception</tt> strategy, which raises an
37
+ # <tt>ActionController::InvalidAuthenticityToken</tt> error on unverified requests.
38
+ #
39
+ # APIs may want to disable this behavior since they are typically designed to be
40
+ # state-less: that is, the request API client handles the session instead of Rails.
41
+ # One way to achieve this is to use the <tt>:null_session</tt> strategy instead,
42
+ # which allows unverified requests to be handled, but with an empty session:
39
43
  #
40
44
  # class ApplicationController < ActionController::Base
41
- # protect_from_forgery unless: -> { request.format.json? }
45
+ # protect_from_forgery with: :null_session
42
46
  # end
43
47
  #
44
- # CSRF protection is turned on with the <tt>protect_from_forgery</tt> method.
45
- # By default <tt>protect_from_forgery</tt> protects your session with
46
- # <tt>:null_session</tt> method, which provides an empty session
47
- # during request.
48
- #
49
- # We may want to disable CSRF protection for APIs since they are typically
50
- # designed to be state-less. That is, the request API client will handle
51
- # the session for you instead of Rails.
48
+ # Note that API only applications don't include this module or a session middleware
49
+ # by default, and so don't require CSRF protection to be configured.
52
50
  #
53
51
  # The token parameter is named <tt>authenticity_token</tt> by default. The name and
54
52
  # value of this token must be added to every layout that renders forms by including
55
53
  # <tt>csrf_meta_tags</tt> in the HTML +head+.
56
54
  #
57
55
  # Learn more about CSRF attacks and securing your application in the
58
- # {Ruby on Rails Security Guide}[http://guides.rubyonrails.org/security.html].
56
+ # {Ruby on Rails Security Guide}[https://guides.rubyonrails.org/security.html].
59
57
  module RequestForgeryProtection
60
58
  extend ActiveSupport::Concern
61
59
 
@@ -92,6 +90,10 @@ module ActionController #:nodoc:
92
90
  config_accessor :default_protect_from_forgery
93
91
  self.default_protect_from_forgery = false
94
92
 
93
+ # Controls whether URL-safe CSRF tokens are generated.
94
+ config_accessor :urlsafe_csrf_tokens, instance_writer: false
95
+ self.urlsafe_csrf_tokens = false
96
+
95
97
  helper_method :form_authenticity_token
96
98
  helper_method :protect_against_forgery?
97
99
  end
@@ -145,7 +147,6 @@ module ActionController #:nodoc:
145
147
  end
146
148
 
147
149
  private
148
-
149
150
  def protection_method_class(name)
150
151
  ActionController::RequestForgeryProtection::ProtectionMethods.const_get(name.to_s.classify)
151
152
  rescue NameError
@@ -169,7 +170,6 @@ module ActionController #:nodoc:
169
170
  end
170
171
 
171
172
  private
172
-
173
173
  class NullSessionHash < Rack::Session::Abstract::SessionHash #:nodoc:
174
174
  def initialize(req)
175
175
  super(nil, req)
@@ -276,7 +276,7 @@ module ActionController #:nodoc:
276
276
 
277
277
  # Check for cross-origin JavaScript responses.
278
278
  def non_xhr_javascript_response? # :doc:
279
- content_type =~ %r(\Atext/javascript) && !request.xhr?
279
+ %r(\A(?:text|application)/javascript).match?(media_type) && !request.xhr?
280
280
  end
281
281
 
282
282
  AUTHENTICITY_TOKEN_LENGTH = 32
@@ -318,13 +318,10 @@ module ActionController #:nodoc:
318
318
  action_path = normalize_action_path(action)
319
319
  per_form_csrf_token(session, action_path, method)
320
320
  else
321
- real_csrf_token(session)
321
+ global_csrf_token(session)
322
322
  end
323
323
 
324
- one_time_pad = SecureRandom.random_bytes(AUTHENTICITY_TOKEN_LENGTH)
325
- encrypted_csrf_token = xor_byte_strings(one_time_pad, raw_token)
326
- masked_token = one_time_pad + encrypted_csrf_token
327
- Base64.strict_encode64(masked_token)
324
+ mask_token(raw_token)
328
325
  end
329
326
 
330
327
  # Checks the client's masked token to see if it matches the
@@ -336,7 +333,7 @@ module ActionController #:nodoc:
336
333
  end
337
334
 
338
335
  begin
339
- masked_token = Base64.strict_decode64(encoded_masked_token)
336
+ masked_token = decode_csrf_token(encoded_masked_token)
340
337
  rescue ArgumentError # encoded_masked_token is invalid Base64
341
338
  return false
342
339
  end
@@ -354,7 +351,8 @@ module ActionController #:nodoc:
354
351
  elsif masked_token.length == AUTHENTICITY_TOKEN_LENGTH * 2
355
352
  csrf_token = unmask_token(masked_token)
356
353
 
357
- compare_with_real_token(csrf_token, session) ||
354
+ compare_with_global_token(csrf_token, session) ||
355
+ compare_with_real_token(csrf_token, session) ||
358
356
  valid_per_form_csrf_token?(csrf_token, session)
359
357
  else
360
358
  false # Token is malformed.
@@ -369,15 +367,26 @@ module ActionController #:nodoc:
369
367
  xor_byte_strings(one_time_pad, encrypted_csrf_token)
370
368
  end
371
369
 
370
+ def mask_token(raw_token) # :doc:
371
+ one_time_pad = SecureRandom.random_bytes(AUTHENTICITY_TOKEN_LENGTH)
372
+ encrypted_csrf_token = xor_byte_strings(one_time_pad, raw_token)
373
+ masked_token = one_time_pad + encrypted_csrf_token
374
+ encode_csrf_token(masked_token)
375
+ end
376
+
372
377
  def compare_with_real_token(token, session) # :doc:
373
378
  ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, real_csrf_token(session))
374
379
  end
375
380
 
381
+ def compare_with_global_token(token, session) # :doc:
382
+ ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, global_csrf_token(session))
383
+ end
384
+
376
385
  def valid_per_form_csrf_token?(token, session) # :doc:
377
386
  if per_form_csrf_tokens
378
387
  correct_token = per_form_csrf_token(
379
388
  session,
380
- normalize_action_path(request.fullpath),
389
+ request.path.chomp("/"),
381
390
  request.request_method
382
391
  )
383
392
 
@@ -388,22 +397,38 @@ module ActionController #:nodoc:
388
397
  end
389
398
 
390
399
  def real_csrf_token(session) # :doc:
391
- session[:_csrf_token] ||= SecureRandom.base64(AUTHENTICITY_TOKEN_LENGTH)
392
- Base64.strict_decode64(session[:_csrf_token])
400
+ session[:_csrf_token] ||= generate_csrf_token
401
+ decode_csrf_token(session[:_csrf_token])
393
402
  end
394
403
 
395
404
  def per_form_csrf_token(session, action_path, method) # :doc:
405
+ csrf_token_hmac(session, [action_path, method.downcase].join("#"))
406
+ end
407
+
408
+ GLOBAL_CSRF_TOKEN_IDENTIFIER = "!real_csrf_token"
409
+ private_constant :GLOBAL_CSRF_TOKEN_IDENTIFIER
410
+
411
+ def global_csrf_token(session) # :doc:
412
+ csrf_token_hmac(session, GLOBAL_CSRF_TOKEN_IDENTIFIER)
413
+ end
414
+
415
+ def csrf_token_hmac(session, identifier) # :doc:
396
416
  OpenSSL::HMAC.digest(
397
417
  OpenSSL::Digest::SHA256.new,
398
418
  real_csrf_token(session),
399
- [action_path, method.downcase].join("#")
419
+ identifier
400
420
  )
401
421
  end
402
422
 
403
423
  def xor_byte_strings(s1, s2) # :doc:
404
- s2_bytes = s2.bytes
405
- s1.each_byte.with_index { |c1, i| s2_bytes[i] ^= c1 }
406
- s2_bytes.pack("C*")
424
+ s2 = s2.dup
425
+ size = s1.bytesize
426
+ i = 0
427
+ while i < size
428
+ s2.setbyte(i, s1.getbyte(i) ^ s2.getbyte(i))
429
+ i += 1
430
+ end
431
+ s2
407
432
  end
408
433
 
409
434
  # The form's authenticity parameter. Override to provide your own.
@@ -416,11 +441,11 @@ module ActionController #:nodoc:
416
441
  allow_forgery_protection
417
442
  end
418
443
 
419
- NULL_ORIGIN_MESSAGE = <<-MSG.strip_heredoc
444
+ NULL_ORIGIN_MESSAGE = <<~MSG
420
445
  The browser returned a 'null' origin for a request with origin-based forgery protection turned on. This usually
421
- means you have the 'no-referrer' Referrer-Policy header enabled, or that you the request came from a site that
446
+ means you have the 'no-referrer' Referrer-Policy header enabled, or that the request came from a site that
422
447
  refused to give its origin. This makes it impossible for Rails to verify the source of the requests. Likely the
423
- best solution is to change your referrer policy to something less strict like same-origin or strict-same-origin.
448
+ best solution is to change your referrer policy to something less strict like same-origin or strict-origin.
424
449
  If you cannot change the referrer policy, you can disable origin checking with the
425
450
  Rails.application.config.action_controller.forgery_protection_origin_check setting.
426
451
  MSG
@@ -441,5 +466,33 @@ module ActionController #:nodoc:
441
466
  uri = URI.parse(action_path)
442
467
  uri.path.chomp("/")
443
468
  end
469
+
470
+ def generate_csrf_token # :nodoc:
471
+ if urlsafe_csrf_tokens
472
+ SecureRandom.urlsafe_base64(AUTHENTICITY_TOKEN_LENGTH, padding: false)
473
+ else
474
+ SecureRandom.base64(AUTHENTICITY_TOKEN_LENGTH)
475
+ end
476
+ end
477
+
478
+ def encode_csrf_token(csrf_token) # :nodoc:
479
+ if urlsafe_csrf_tokens
480
+ Base64.urlsafe_encode64(csrf_token, padding: false)
481
+ else
482
+ Base64.strict_encode64(csrf_token)
483
+ end
484
+ end
485
+
486
+ def decode_csrf_token(encoded_csrf_token) # :nodoc:
487
+ if urlsafe_csrf_tokens
488
+ Base64.urlsafe_decode64(encoded_csrf_token)
489
+ else
490
+ begin
491
+ Base64.strict_decode64(encoded_csrf_token)
492
+ rescue ArgumentError
493
+ Base64.urlsafe_decode64(encoded_csrf_token)
494
+ end
495
+ end
496
+ end
444
497
  end
445
498
  end
@@ -18,7 +18,7 @@ module ActionController #:nodoc:
18
18
  end
19
19
 
20
20
  private
21
- def process_action(*args)
21
+ def process_action(*)
22
22
  super
23
23
  rescue Exception => exception
24
24
  request.env["action_dispatch.show_detailed_exceptions"] ||= show_detailed_exceptions?
@@ -196,7 +196,6 @@ module ActionController #:nodoc:
196
196
  extend ActiveSupport::Concern
197
197
 
198
198
  private
199
-
200
199
  # Set proper cache control and transfer encoding when streaming
201
200
  def _process_options(options)
202
201
  super