Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
fb2af6f8
R
rails
项目概览
张重言
/
rails
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rails
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
fb2af6f8
编写于
4月 19, 2018
作者:
A
Andrew White
提交者:
GitHub
4月 19, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' into fix-as-timezone-all
上级
7d25b651
ef2af628
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
155 addition
and
26 deletion
+155
-26
actionpack/CHANGELOG.md
actionpack/CHANGELOG.md
+6
-0
actionpack/lib/action_dispatch/http/content_security_policy.rb
...npack/lib/action_dispatch/http/content_security_policy.rb
+17
-12
actionpack/test/dispatch/content_security_policy_test.rb
actionpack/test/dispatch/content_security_policy_test.rb
+71
-2
actionview/CHANGELOG.md
actionview/CHANGELOG.md
+6
-0
actionview/lib/action_view/digestor.rb
actionview/lib/action_view/digestor.rb
+7
-2
actionview/lib/action_view/helpers/asset_tag_helper.rb
actionview/lib/action_view/helpers/asset_tag_helper.rb
+8
-0
actionview/lib/action_view/helpers/translation_helper.rb
actionview/lib/action_view/helpers/translation_helper.rb
+5
-1
actionview/test/template/asset_tag_helper_test.rb
actionview/test/template/asset_tag_helper_test.rb
+8
-0
activemodel/lib/active_model/validations/inclusion.rb
activemodel/lib/active_model/validations/inclusion.rb
+1
-1
activesupport/CHANGELOG.md
activesupport/CHANGELOG.md
+5
-0
activesupport/lib/active_support/cache/redis_cache_store.rb
activesupport/lib/active_support/cache/redis_cache_store.rb
+13
-6
guides/source/asset_pipeline.md
guides/source/asset_pipeline.md
+2
-2
guides/source/security.md
guides/source/security.md
+6
-0
未找到文件。
actionpack/CHANGELOG.md
浏览文件 @
fb2af6f8
*
Output only one Content-Security-Policy nonce header value per request.
Fixes #35297.
*Andrey Novikov*, *Andrew White*
*
Move default headers configuration into their own module that can be included in controllers.
*Kevin Deisz*
...
...
actionpack/lib/action_dispatch/http/content_security_policy.rb
浏览文件 @
fb2af6f8
...
...
@@ -21,13 +21,8 @@ def call(env)
return
response
if
policy_present?
(
headers
)
if
policy
=
request
.
content_security_policy
if
policy
.
directives
[
"script-src"
]
if
nonce
=
request
.
content_security_policy_nonce
policy
.
directives
[
"script-src"
]
<<
"'nonce-
#{
nonce
}
'"
end
end
headers
[
header_name
(
request
)]
=
policy
.
build
(
request
.
controller_instance
)
nonce
=
request
.
content_security_policy_nonce
headers
[
header_name
(
request
)]
=
policy
.
build
(
request
.
controller_instance
,
nonce
)
end
response
...
...
@@ -136,7 +131,9 @@ def generate_content_security_policy_nonce
worker_src:
"worker-src"
}.
freeze
private_constant
:MAPPINGS
,
:DIRECTIVES
NONCE_DIRECTIVES
=
%w[script-src]
.
freeze
private_constant
:MAPPINGS
,
:DIRECTIVES
,
:NONCE_DIRECTIVES
attr_reader
:directives
...
...
@@ -205,8 +202,8 @@ def upgrade_insecure_requests(enabled = true)
end
end
def
build
(
context
=
nil
)
build_directives
(
context
).
compact
.
join
(
"; "
)
def
build
(
context
=
nil
,
nonce
=
nil
)
build_directives
(
context
,
nonce
).
compact
.
join
(
"; "
)
end
private
...
...
@@ -229,10 +226,14 @@ def apply_mapping(source)
end
end
def
build_directives
(
context
)
def
build_directives
(
context
,
nonce
)
@directives
.
map
do
|
directive
,
sources
|
if
sources
.
is_a?
(
Array
)
"
#{
directive
}
#{
build_directive
(
sources
,
context
).
join
(
' '
)
}
"
if
nonce
&&
nonce_directive?
(
directive
)
"
#{
directive
}
#{
build_directive
(
sources
,
context
).
join
(
' '
)
}
'nonce-
#{
nonce
}
'"
else
"
#{
directive
}
#{
build_directive
(
sources
,
context
).
join
(
' '
)
}
"
end
elsif
sources
directive
else
...
...
@@ -261,5 +262,9 @@ def resolve_source(source, context)
raise
RuntimeError
,
"Unexpected content security policy source:
#{
source
.
inspect
}
"
end
end
def
nonce_directive?
(
directive
)
NONCE_DIRECTIVES
.
include?
(
directive
)
end
end
end
actionpack/test/dispatch/content_security_policy_test.rb
浏览文件 @
fb2af6f8
...
...
@@ -200,7 +200,7 @@ def test_multiple_directives
end
def
test_dynamic_directives
request
=
Struct
.
new
(
:host
).
new
(
"www.example.com"
)
request
=
ActionDispatch
::
Request
.
new
(
"HTTP_HOST"
=>
"www.example.com"
)
controller
=
Struct
.
new
(
:request
).
new
(
request
)
@policy
.
script_src
->
{
request
.
host
}
...
...
@@ -209,7 +209,9 @@ def test_dynamic_directives
def
test_mixed_static_and_dynamic_directives
@policy
.
script_src
:self
,
->
{
"foo.com"
},
"bar.com"
assert_equal
"script-src 'self' foo.com bar.com"
,
@policy
.
build
(
Object
.
new
)
request
=
ActionDispatch
::
Request
.
new
({})
controller
=
Struct
.
new
(
:request
).
new
(
request
)
assert_equal
"script-src 'self' foo.com bar.com"
,
@policy
.
build
(
controller
)
end
def
test_invalid_directive_source
...
...
@@ -241,6 +243,73 @@ def test_raises_runtime_error_when_unexpected_source
end
end
class
DefaultContentSecurityPolicyIntegrationTest
<
ActionDispatch
::
IntegrationTest
class
PolicyController
<
ActionController
::
Base
def
index
head
:ok
end
end
ROUTES
=
ActionDispatch
::
Routing
::
RouteSet
.
new
ROUTES
.
draw
do
scope
module:
"default_content_security_policy_integration_test"
do
get
"/"
,
to:
"policy#index"
end
end
POLICY
=
ActionDispatch
::
ContentSecurityPolicy
.
new
do
|
p
|
p
.
default_src
:self
p
.
script_src
:https
end
class
PolicyConfigMiddleware
def
initialize
(
app
)
@app
=
app
end
def
call
(
env
)
env
[
"action_dispatch.content_security_policy"
]
=
POLICY
env
[
"action_dispatch.content_security_policy_nonce_generator"
]
=
proc
{
"iyhD0Yc0W+c="
}
env
[
"action_dispatch.content_security_policy_report_only"
]
=
false
env
[
"action_dispatch.show_exceptions"
]
=
false
@app
.
call
(
env
)
end
end
APP
=
build_app
(
ROUTES
)
do
|
middleware
|
middleware
.
use
PolicyConfigMiddleware
middleware
.
use
ActionDispatch
::
ContentSecurityPolicy
::
Middleware
end
def
app
APP
end
def
test_adds_nonce_to_script_src_content_security_policy_only_once
get
"/"
get
"/"
assert_policy
"default-src 'self'; script-src https: 'nonce-iyhD0Yc0W+c='"
end
private
def
assert_policy
(
expected
,
report_only:
false
)
assert_response
:success
if
report_only
expected_header
=
"Content-Security-Policy-Report-Only"
unexpected_header
=
"Content-Security-Policy"
else
expected_header
=
"Content-Security-Policy"
unexpected_header
=
"Content-Security-Policy-Report-Only"
end
assert_nil
response
.
headers
[
unexpected_header
]
assert_equal
expected
,
response
.
headers
[
expected_header
]
end
end
class
ContentSecurityPolicyIntegrationTest
<
ActionDispatch
::
IntegrationTest
class
PolicyController
<
ActionController
::
Base
content_security_policy
only: :inline
do
|
p
|
...
...
actionview/CHANGELOG.md
浏览文件 @
fb2af6f8
*
Add the
`nonce: true`
option for
`javascript_include_tag`
helper to
support automatic nonce generation for Content Security Policy.
Works the same way as
`javascript_tag nonce: true`
does.
*Yaroslav Markin*
*
Remove
`ActionView::Helpers::RecordTagHelper`
.
*Yoshiyuki Hirano*
...
...
actionview/lib/action_view/digestor.rb
浏览文件 @
fb2af6f8
...
...
@@ -71,11 +71,16 @@ def tree(name, finder, partial = false, seen = {})
private
def
find_template
(
finder
,
*
args
)
name
=
args
.
first
prefixes
=
args
[
1
]
||
[]
partial
=
args
[
2
]
||
false
keys
=
args
[
3
]
||
[]
options
=
args
[
4
]
||
{}
finder
.
disable_cache
do
if
format
=
finder
.
rendered_format
finder
.
find_all
(
*
args
,
formats:
[
format
]).
first
||
finder
.
find_all
(
*
arg
s
).
first
finder
.
find_all
(
name
,
prefixes
,
partial
,
keys
,
options
.
merge
(
formats:
[
format
])).
first
||
finder
.
find_all
(
name
,
prefixes
,
partial
,
keys
,
option
s
).
first
else
finder
.
find_all
(
*
arg
s
).
first
finder
.
find_all
(
name
,
prefixes
,
partial
,
keys
,
option
s
).
first
end
end
end
...
...
actionview/lib/action_view/helpers/asset_tag_helper.rb
浏览文件 @
fb2af6f8
...
...
@@ -55,6 +55,8 @@ module AssetTagHelper
# that path.
# * <tt>:skip_pipeline</tt> - This option is used to bypass the asset pipeline
# when it is set to true.
# * <tt>:nonce<tt> - When set to true, adds an automatic nonce value if
# you have Content Security Policy enabled.
#
# ==== Examples
#
...
...
@@ -79,6 +81,9 @@ module AssetTagHelper
#
# javascript_include_tag "http://www.example.com/xmlhr.js"
# # => <script src="http://www.example.com/xmlhr.js"></script>
#
# javascript_include_tag "http://www.example.com/xmlhr.js", nonce: true
# # => <script src="http://www.example.com/xmlhr.js" nonce="..."></script>
def
javascript_include_tag
(
*
sources
)
options
=
sources
.
extract_options!
.
stringify_keys
path_options
=
options
.
extract!
(
"protocol"
,
"extname"
,
"host"
,
"skip_pipeline"
).
symbolize_keys
...
...
@@ -90,6 +95,9 @@ def javascript_include_tag(*sources)
tag_options
=
{
"src"
=>
href
}.
merge!
(
options
)
if
tag_options
[
"nonce"
]
==
true
tag_options
[
"nonce"
]
=
content_security_policy_nonce
end
content_tag
(
"script"
.
freeze
,
""
,
tag_options
)
}.
join
(
"
\n
"
).
html_safe
...
...
actionview/lib/action_view/helpers/translation_helper.rb
浏览文件 @
fb2af6f8
...
...
@@ -60,7 +60,11 @@ module TranslationHelper
def
translate
(
key
,
options
=
{})
options
=
options
.
dup
has_default
=
options
.
has_key?
(
:default
)
remaining_defaults
=
Array
(
options
.
delete
(
:default
)).
compact
if
has_default
remaining_defaults
=
Array
(
options
.
delete
(
:default
)).
compact
else
remaining_defaults
=
[]
end
if
has_default
&&
!
remaining_defaults
.
first
.
kind_of?
(
Symbol
)
options
[
:default
]
=
remaining_defaults
...
...
actionview/test/template/asset_tag_helper_test.rb
浏览文件 @
fb2af6f8
...
...
@@ -29,6 +29,10 @@ def url_for(*args)
"http://www.example.com"
end
def
content_security_policy_nonce
"iyhD0Yc0W+c="
end
AssetPathToTag
=
{
%(asset_path(""))
=>
%()
,
%(asset_path(" "))
=>
%()
,
...
...
@@ -421,6 +425,10 @@ def test_javascript_include_tag_default_protocol
assert_dom_equal
%(<script src="//assets.example.com/javascripts/prototype.js"></script>)
,
javascript_include_tag
(
"prototype"
)
end
def
test_javascript_include_tag_nonce
assert_dom_equal
%(<script src="/javascripts/bank.js" nonce="iyhD0Yc0W+c="></script>)
,
javascript_include_tag
(
"bank"
,
nonce:
true
)
end
def
test_stylesheet_path
StylePathToTag
.
each
{
|
method
,
tag
|
assert_dom_equal
(
tag
,
eval
(
method
))
}
end
...
...
activemodel/lib/active_model/validations/inclusion.rb
浏览文件 @
fb2af6f8
...
...
@@ -19,7 +19,7 @@ module HelperMethods
# particular enumerable object.
#
# class Person < ActiveRecord::Base
# validates_inclusion_of :
gender, in: %w( m f
)
# validates_inclusion_of :
role, in: %w( admin contributor
)
# validates_inclusion_of :age, in: 0..99
# validates_inclusion_of :format, in: %w( jpg gif png ), message: "extension %{value} is not included in the list"
# validates_inclusion_of :states, in: ->(person) { STATES[person.country] }
...
...
activesupport/CHANGELOG.md
浏览文件 @
fb2af6f8
...
...
@@ -3,6 +3,11 @@
*Dominik Sander*
*
Redis cache store:
`delete_matched`
no longer blocks the Redis server.
(Switches from evaled Lua to a batched SCAN + DEL loop.)
*Gleb Mazovetskiy*
*
Fix bug where
`ActiveSupport::Cache`
will massively inflate the storage
size when compression is enabled (which is true by default). This patch
does not attempt to repair existing data: please manually flush the cache
...
...
activesupport/lib/active_support/cache/redis_cache_store.rb
浏览文件 @
fb2af6f8
...
...
@@ -62,8 +62,9 @@ class RedisCacheStore < Store
end
end
DELETE_GLOB_LUA
=
"for i, name in ipairs(redis.call('KEYS', ARGV[1])) do redis.call('DEL', name); end"
private_constant
:DELETE_GLOB_LUA
# The maximum number of entries to receive per SCAN call.
SCAN_BATCH_SIZE
=
1000
private_constant
:SCAN_BATCH_SIZE
# Support raw values in the local cache strategy.
module
LocalCacheWithRaw
# :nodoc:
...
...
@@ -231,12 +232,18 @@ def read_multi(*names)
# Failsafe: Raises errors.
def
delete_matched
(
matcher
,
options
=
nil
)
instrument
:delete_matched
,
matcher
do
case
matcher
when
String
redis
.
with
{
|
c
|
c
.
eval
DELETE_GLOB_LUA
,
[],
[
namespace_key
(
matcher
,
options
)]
}
else
unless
String
===
matcher
raise
ArgumentError
,
"Only Redis glob strings are supported:
#{
matcher
.
inspect
}
"
end
redis
.
with
do
|
c
|
pattern
=
namespace_key
(
matcher
,
options
)
cursor
=
"0"
# Fetch keys in batches using SCAN to avoid blocking the Redis server.
begin
cursor
,
keys
=
c
.
scan
(
cursor
,
match:
pattern
,
count:
SCAN_BATCH_SIZE
)
c
.
del
(
*
keys
)
unless
keys
.
empty?
end
until
cursor
==
"0"
end
end
end
...
...
guides/source/asset_pipeline.md
浏览文件 @
fb2af6f8
...
...
@@ -728,8 +728,8 @@ Rails.application.config.assets.precompile += %w( admin.js admin.css )
NOTE. Always specify an expected compiled filename that ends with
`.js`
or
`.css`
,
even if you want to add Sass or CoffeeScript files to the precompile array.
The task also generates a
`.sprockets-manifest-
md5hash.json`
(where
`md5hash
`
is
a
n MD5 hash
) that contains a list with all your assets and their respective
The task also generates a
`.sprockets-manifest-
randomhex.json`
(where
`randomhex
`
is
a
16-byte random hex string
) that contains a list with all your assets and their respective
fingerprints. This is used by the Rails helper methods to avoid handing the
mapping requests back to Sprockets. A typical manifest file looks like:
...
...
guides/source/security.md
浏览文件 @
fb2af6f8
...
...
@@ -1182,6 +1182,12 @@ as part of `html_options`. Example:
<% end -%>
```
The same works with
`javascript_include_tag`
:
```
html+erb
<%= javascript_include_tag "script", nonce: true %>
```
Use
[
`csp_meta_tag`
](
http://api.rubyonrails.org/classes/ActionView/Helpers/CspHelper.html#method-i-csp_meta_tag
)
helper to create a meta tag "csp-nonce" with the per-session nonce value
for allowing inline
`<script>`
tags.
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录