Last active
September 19, 2015 20:21
-
-
Save cheeyeo/fc41b675d3036d477740 to your computer and use it in GitHub Desktop.
CSP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module GitHub | |
module CSP | |
# Public: Constants for CSP keywords | |
NONE = "'none'".freeze | |
SELF = "'self'".freeze | |
UNSAFE_INLINE = "'unsafe-inline'".freeze | |
UNSAFE_EVAL = "'unsafe-eval'".freeze | |
# Public: Constants for CSP directive names | |
BASE_URI = "base-uri".freeze | |
CHILD_SRC = "child-src".freeze | |
CONNECT_SRC = "connect-src".freeze | |
DEFAULT_SRC = "default-src".freeze | |
FONT_SRC = "font-src".freeze | |
FORM_ACTION = "form-action".freeze | |
FRAME_ANCESTORS = "frame-ancestors".freeze | |
FRAME_SRC = "frame-src".freeze | |
IMG_SRC = "img-src".freeze | |
MEDIA_SRC = "media-src".freeze | |
OBJECT_SRC = "object-src".freeze | |
PLUGIN_TYPES = "plugin-types".freeze | |
REFERRER = "referrer".freeze | |
REFLECTED_XSS = "reflected-xss".freeze | |
REPORT_URI = "report-uri".freeze | |
SANDBOX = "sandbox".freeze | |
SCRIPT_SRC = "script-src".freeze | |
STYLE_SRC = "style-src".freeze | |
# Internal: Mapping of valid directive names to the type of values. | |
DIRECTIVE_VALUE_TYPES = { | |
BASE_URI => :source_list, | |
CHILD_SRC => :source_list, | |
CONNECT_SRC => :source_list, | |
DEFAULT_SRC => :source_list, | |
FONT_SRC => :source_list, | |
FORM_ACTION => :source_list, | |
FRAME_ANCESTORS => :source_list, | |
FRAME_SRC => :source_list, | |
IMG_SRC => :source_list, | |
MEDIA_SRC => :source_list, | |
OBJECT_SRC => :source_list, | |
PLUGIN_TYPES => :media_type_list, | |
REFERRER => :string, | |
REFLECTED_XSS => :string, | |
REPORT_URI => :uri, | |
SANDBOX => :string, | |
SCRIPT_SRC => :source_list, | |
STYLE_SRC => :source_list | |
}.freeze | |
# Public: Convert CSP policy structure into a String. | |
# | |
# policy - Array of directives where [directive_name, directive_value] | |
# directive_name - String name | |
# directive_value - String or Array | |
# | |
# Returns a String or raises a TypeError if the policy has unknown | |
# directives. | |
def self.stringify(policy) | |
policy.map { |name, value| | |
unless directive_type = DIRECTIVE_VALUE_TYPES[name] | |
raise TypeError, "unknown directive name: #{name.inspect}" | |
end | |
case directive_type | |
when :string, :uri | |
[name, value].compact.join(" ") | |
when :source_list, :media_type_list | |
([name] + value).compact.join(" ") | |
else | |
raise TypeError, "unknown directive type: #{directive_type.inspect}" | |
end | |
}.join("; ") | |
end | |
# Internal: Minify CSP policy. | |
# | |
# Removes duplicate sources. | |
# Removes sources that already match an existing wild card. | |
# | |
# policy - Array of directives. See `stringify`. | |
# | |
# Returns Array policy. | |
def self.minify(policy) | |
policy.map do |name, value| | |
if DIRECTIVE_VALUE_TYPES[name] == :source_list | |
sources = dedup_source_list(value.compact) | |
sources = sources.map { |source| strip_source_scheme(source) } | |
[name, sources] | |
else | |
[name, value] | |
end | |
end | |
end | |
# Internal: Strips scheme from URI source. | |
# | |
# Sources without a scheme default to the page's scheme. This saves some | |
# bytes in our header. | |
# | |
# source - String | |
# | |
# Returns source String. | |
def self.strip_source_scheme(source) | |
source.sub(/^https?:\/\//, "") | |
end | |
# Internal: Dedup source list values. | |
# | |
# Removes duplicate sources. | |
# Removes sources that already match an existing wild card. | |
# | |
# sources - Array of String sources. | |
# | |
# Returns Array of sources. | |
def self.dedup_source_list(sources) | |
sources = sources.uniq | |
wild_sources = sources.select { |source| source =~ /\*/ } | |
if wild_sources.any? | |
sources.reject do |source| | |
!wild_sources.include?(source) && | |
wild_sources.any? { |pattern| File.fnmatch(pattern, source) } | |
end | |
else | |
sources | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment