jekyll-content-security-policy-generator 1.0.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +6 -0
- data/LICENSE +21 -0
- data/Makefile +36 -0
- data/README.md +37 -0
- data/jekyll-content-security-policy-generator.gemspec +21 -0
- data/lib/jekyll-content-security-policy-generator.rb +5 -0
- data/lib/jekyll-content-security-policy-generator/hook.rb +268 -0
- data/lib/jekyll-content-security-policy-generator/version.rb +3 -0
- metadata +30 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec29dad0ececf9db2097db0a584d176f845047a4e680e64aee0e574606de95e9
|
4
|
+
data.tar.gz: 57d57a9c9f96944d3e252161cc167959a2d943debe285339f26f4308e99c6b9f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: edaf01605a12f29c012a795219467a81d7c785380c205aac2e78e0b3cb8ac1d4a21e34112e0fb94113ba77e011ce412c5cee90dfeac9fc49c73cf83eb5d45ff4
|
7
|
+
data.tar.gz: 8ff8a12e60688ba77ae30dbd5c0844f94f8dba0786574549e656f5f3f280bfc9d14f6efc7b6f19e2b027520880a40a5e745886ca493e8444fffb068142072988
|
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2021 strongscot <mail@strongscot.com> (https://strongscot.com
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/Makefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
CWD := $(shell pwd)
|
2
|
+
|
3
|
+
.PHONY: all
|
4
|
+
all: build
|
5
|
+
|
6
|
+
.PHONY: start
|
7
|
+
start:
|
8
|
+
@bundle exec jekyll serve --verbose
|
9
|
+
|
10
|
+
.PHONY: build
|
11
|
+
build: clean
|
12
|
+
@gem build *.gemspec
|
13
|
+
@echo ::: BUILD :::
|
14
|
+
|
15
|
+
.PHONY: install
|
16
|
+
install: deps
|
17
|
+
-@rm -f Gemfile.lock &>/dev/null || true
|
18
|
+
@bundle install
|
19
|
+
@echo ::: INSTALL :::
|
20
|
+
|
21
|
+
.PHONY: push
|
22
|
+
push: build
|
23
|
+
@gem push *.gem
|
24
|
+
@echo ::: PUSH :::
|
25
|
+
|
26
|
+
.PHONY: clean
|
27
|
+
clean:
|
28
|
+
-@rm -rf *.gem &>/dev/null || true
|
29
|
+
@echo ::: CLEAN :::
|
30
|
+
|
31
|
+
.PHONY: deps
|
32
|
+
deps: bundle
|
33
|
+
@echo ::: DEPS :::
|
34
|
+
.PHONY: bundle
|
35
|
+
bundle:
|
36
|
+
@if ! o=$$(which bundle); then gem install bundle jekyll; fi
|
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# jekyll-content-security-policy-generator Plugin
|
2
|
+
|
3
|
+
This Jekyll plugin automatically builds an HTML content-security-policy for a Jekyll site. The plugin
|
4
|
+
will scan ```.html``` files generated by Jekyll and attempt to locate images, styles, scripts, frames etc and build a
|
5
|
+
content security policy HTML meta tag. The script will also generate SHA256 hashes for inline scripts and styles. If
|
6
|
+
the script finds elements with style attributes ```<div style="color: red"></div>```, the script will extract the style
|
7
|
+
information and build a style element to which will also pass through the content security policy generation.
|
8
|
+
|
9
|
+
## Goal
|
10
|
+
|
11
|
+
To speed up development of Jekyll based sites whilst also helping to generate secure HTMl files protected from XSS.
|
12
|
+
|
13
|
+
## Features
|
14
|
+
|
15
|
+
* Scans for ```.html``` files generated by Jekyll.
|
16
|
+
* Finds inline scripts such as ```<script>alert("Hello World!");</script>``` and generates an SHA256 hash.
|
17
|
+
* Finds inline styles such as ```<style>.hello { color: "red"; }</style>``` and generates an SHA256 hash.
|
18
|
+
* Creates or reuses an HTTP meta tag for the content security policy.
|
19
|
+
* Finds all images, styles, scripts and frames with external URLs and builds CSP.
|
20
|
+
* Converts style attributes into ```<style>``` elements.
|
21
|
+
|
22
|
+
## Installation
|
23
|
+
|
24
|
+
Install the gem:
|
25
|
+
|
26
|
+
```gem install jekyll-content-security-policy-generator```
|
27
|
+
|
28
|
+
Then add this to your _config.yml:
|
29
|
+
|
30
|
+
```
|
31
|
+
plugins:
|
32
|
+
- jekyll-content-security-policy-generator
|
33
|
+
```
|
34
|
+
|
35
|
+
## Support
|
36
|
+
|
37
|
+
https://strongscot.com
|
@@ -0,0 +1,21 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "jekyll-content-security-policy-generator/version"
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = "jekyll-content-security-policy-generator"
|
6
|
+
spec.summary = "Helps generate a content security policy."
|
7
|
+
spec.description = "Helps generate a content security policy. Locates inline scripts, images, frames etc."
|
8
|
+
spec.version = JekyllContentSecurityPolicyGenerator::VERSION
|
9
|
+
spec.authors = ["strongscot"]
|
10
|
+
spec.email = ["mail@strongscot.com"]
|
11
|
+
spec.homepage = "https://github.com/strongscot/jekyll-content-security-policy-generator"
|
12
|
+
spec.licenses = ["MIT"]
|
13
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r!^(test|spec|features)/!) }
|
14
|
+
spec.require_paths = ["lib"]
|
15
|
+
spec.add_dependency "jekyll"
|
16
|
+
spec.add_dependency "nokogiri"
|
17
|
+
spec.add_dependency "digest"
|
18
|
+
spec.add_development_dependency "rake"
|
19
|
+
spec.add_development_dependency "rspec"
|
20
|
+
spec.add_development_dependency "rubocop"
|
21
|
+
end
|
@@ -0,0 +1,268 @@
|
|
1
|
+
require 'jekyll'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'digest'
|
4
|
+
require 'open-uri'
|
5
|
+
|
6
|
+
##
|
7
|
+
# Provides the ability to generate a content security policy for inline scripts and styles.
|
8
|
+
# Will reuse an existing CSP or generate a new one and insert in HEAD.
|
9
|
+
module Jekyll
|
10
|
+
|
11
|
+
module JekyllContentSecurityPolicyGenerator
|
12
|
+
|
13
|
+
##
|
14
|
+
# Provides the ability to generate a content security policy for inline scripts and styles.
|
15
|
+
# Will reuse an existing CSP or generate a new one and insert in HEAD.
|
16
|
+
class ContentSecurityPolicyGenerator
|
17
|
+
def initialize(document_html)
|
18
|
+
@document_html = document_html
|
19
|
+
@nokogiri = Nokogiri::HTML(document_html)
|
20
|
+
|
21
|
+
@csp_frame_src = ['\'self\'']
|
22
|
+
@csp_image_src = ['\'self\'']
|
23
|
+
@csp_style_src = ['\'self\'']
|
24
|
+
@csp_script_src = ['\'self\'']
|
25
|
+
@csp_unknown = []
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Creates an HTML content security policy meta tag.
|
30
|
+
def generate_convert_security_policy_meta_tag
|
31
|
+
meta_content = ""
|
32
|
+
|
33
|
+
if @csp_frame_src.length > 0
|
34
|
+
meta_content += "frame-src " + @csp_frame_src.join(' ') + '; '
|
35
|
+
end
|
36
|
+
|
37
|
+
if @csp_image_src.length > 0
|
38
|
+
meta_content += "img-src " + @csp_image_src.join(' ') + '; '
|
39
|
+
end
|
40
|
+
|
41
|
+
if @csp_style_src.length > 0
|
42
|
+
meta_content += "style-src " + @csp_style_src.join(' ') + '; '
|
43
|
+
end
|
44
|
+
|
45
|
+
if @csp_script_src.length > 0
|
46
|
+
meta_content += "script-src " + @csp_script_src.join(' ') + '; '
|
47
|
+
end
|
48
|
+
|
49
|
+
if @csp_unknown.length > 0
|
50
|
+
@csp_unknown.each do |find|
|
51
|
+
find_name = find[0]
|
52
|
+
find = find.drop(1)
|
53
|
+
meta_content += find_name + " " + find.join(' ') + '; '
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
if @nokogiri.at("head")
|
58
|
+
Jekyll.logger.info "Generated content security policy, inserted in HEAD."
|
59
|
+
@nokogiri.at("head") << "<meta http-equiv=\"Content-Security-Policy\" content=\"" + meta_content + "\">"
|
60
|
+
elsif @nokogiri.at("body")
|
61
|
+
Jekyll.logger.info "Generated content security policy, inserted in BODY."
|
62
|
+
@nokogiri.at("body") << "<meta http-equiv=\"Content-Security-Policy\" content=\"" + meta_content + "\">"
|
63
|
+
else
|
64
|
+
Jekyll.logger.error "Generated content security policy but found no-where to insert it."
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Parse an existing content security policy meta tag
|
71
|
+
def parse_existing_meta_element()
|
72
|
+
csp = @nokogiri.at('meta[http-equiv="Content-Security-Policy"]')
|
73
|
+
|
74
|
+
if csp
|
75
|
+
content = csp.attr('content')
|
76
|
+
content = content.strip! || content
|
77
|
+
policies = content.split(';')
|
78
|
+
|
79
|
+
policies.each do |policy|
|
80
|
+
policy = policy.strip! || policy
|
81
|
+
|
82
|
+
if policy.include? ' '
|
83
|
+
policy_parts = policy.split(' ')
|
84
|
+
|
85
|
+
if policy_parts[0] == 'script-src'
|
86
|
+
@csp_script_src.concat(policy_parts.drop(1))
|
87
|
+
@csp_script_src = @csp_script_src.uniq
|
88
|
+
elsif policy_parts[0] == 'style-src'
|
89
|
+
@csp_style_src.concat(policy_parts.drop(1))
|
90
|
+
@csp_style_src = @csp_style_src.uniq
|
91
|
+
elsif policy_parts[0] == 'image-src'
|
92
|
+
@csp_image_src.concat(policy_parts.drop(1))
|
93
|
+
@csp_image_src = @csp_image_src.uniq
|
94
|
+
elsif policy_parts[0] == 'frame-src'
|
95
|
+
@csp_frame_src.concat(policy_parts.drop(1))
|
96
|
+
@csp_frame_src = @csp_frame_src.uniq
|
97
|
+
else
|
98
|
+
@csp_unknown.concat([policy_parts])
|
99
|
+
end
|
100
|
+
|
101
|
+
else
|
102
|
+
Jekyll.logger.warn "Incorrect existing content security policy meta tag found, skipping."
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
##
|
109
|
+
# This function converts elements with style="color:red" attributes into inline styles
|
110
|
+
def convert_all_inline_styles_attributes
|
111
|
+
@nokogiri.css('*').each do |find|
|
112
|
+
find_src = find.attr('style')
|
113
|
+
|
114
|
+
if find_src
|
115
|
+
if find.attr('id')
|
116
|
+
element_id = find.attr('id')
|
117
|
+
else
|
118
|
+
element_id = Digest::MD5.hexdigest find_src + "#{Random.rand(11)}"
|
119
|
+
find["id"] = element_id
|
120
|
+
end
|
121
|
+
|
122
|
+
new_element = "<style>#" + element_id + " { " + find_src + " } </style>"
|
123
|
+
find.remove_attribute("style")
|
124
|
+
|
125
|
+
if @nokogiri.at('head')
|
126
|
+
@nokogiri.at('head') << new_element
|
127
|
+
Jekyll.logger.info'Converting style attribute to inline style, inserted into HEAD.'
|
128
|
+
else
|
129
|
+
if @nokogiri.at('body')
|
130
|
+
@nokogiri.at('body') << new_element
|
131
|
+
Jekyll.logger.info'Converting style attribute to inline style, inserted into BODY.'
|
132
|
+
else
|
133
|
+
Jekyll.logger.warn'Unable to convert style attribute to inline style, no HEAD or BODY found.'
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
##
|
141
|
+
# Find all images
|
142
|
+
def find_images
|
143
|
+
@nokogiri.css('img').each do |find|
|
144
|
+
find_src = find.attr('src')
|
145
|
+
|
146
|
+
if find_src.start_with?('http', 'https')
|
147
|
+
@csp_image_src.push find_src.match(/(.*\/)+(.*$)/)[1]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
##
|
153
|
+
# Find all scripts
|
154
|
+
def find_scripts
|
155
|
+
@nokogiri.css('script').each do |find|
|
156
|
+
if find.attr('src')
|
157
|
+
find_src = find.attr('src')
|
158
|
+
|
159
|
+
if find_src.start_with?('http', 'https')
|
160
|
+
@csp_script_src.push find_src.match(/(.*\/)+(.*$)/)[1]
|
161
|
+
end
|
162
|
+
|
163
|
+
else
|
164
|
+
@csp_script_src.push self.generate_sha256_content_hash find.content
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
##
|
170
|
+
# Find all stylesheets
|
171
|
+
def find_styles
|
172
|
+
@nokogiri.css('style').each do |find|
|
173
|
+
if find.attr('src')
|
174
|
+
find_src = find.attr('src')
|
175
|
+
|
176
|
+
if find_src.start_with?('http', 'https')
|
177
|
+
@csp_style_src.push find_src.match(/(.*\/)+(.*$)/)[1]
|
178
|
+
end
|
179
|
+
|
180
|
+
else
|
181
|
+
@csp_style_src.push self.generate_sha256_content_hash find.content
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
##
|
187
|
+
# Find all iframes
|
188
|
+
def find_iframes
|
189
|
+
@nokogiri.css('iframe').each do |find|
|
190
|
+
find_src = find.attr('src')
|
191
|
+
|
192
|
+
if find_src.start_with?('http', 'https')
|
193
|
+
@csp_frame_src.push find_src.match(/(.*\/)+(.*$)/)[1]
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
##
|
199
|
+
# Generate a content hash
|
200
|
+
def generate_sha256_content_hash(content)
|
201
|
+
hash = Digest::SHA2.base64digest content
|
202
|
+
"'sha256-#{hash}'"
|
203
|
+
end
|
204
|
+
|
205
|
+
##
|
206
|
+
# Builds an HTML meta tag based on the found inline scripts and style hashes
|
207
|
+
def run
|
208
|
+
self.parse_existing_meta_element
|
209
|
+
|
210
|
+
self.convert_all_inline_styles_attributes
|
211
|
+
|
212
|
+
# Find elements in document
|
213
|
+
self.find_images
|
214
|
+
self.find_styles
|
215
|
+
self.find_scripts
|
216
|
+
self.find_iframes
|
217
|
+
|
218
|
+
self.generate_convert_security_policy_meta_tag
|
219
|
+
|
220
|
+
@nokogiri.to_html
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
##
|
225
|
+
# Write the file contents back.
|
226
|
+
def write_file_contents(dest, content)
|
227
|
+
FileUtils.mkdir_p(File.dirname(dest))
|
228
|
+
File.open(dest, 'w') do |f|
|
229
|
+
f.write(content)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
##
|
234
|
+
# Write document contents
|
235
|
+
def write(dest)
|
236
|
+
dest_path = destination(dest)
|
237
|
+
if File.extname(dest_path) == ".html"
|
238
|
+
content_security_policy_generator = ContentSecurityPolicyGenerator.new output
|
239
|
+
output = content_security_policy_generator.run
|
240
|
+
end
|
241
|
+
|
242
|
+
write_file_contents(dest_path, output)
|
243
|
+
end
|
244
|
+
|
245
|
+
end
|
246
|
+
|
247
|
+
class Document
|
248
|
+
include JekyllContentSecurityPolicyGenerator
|
249
|
+
|
250
|
+
##
|
251
|
+
# Write document contents
|
252
|
+
def write(dest)
|
253
|
+
super dest
|
254
|
+
trigger_hooks(:post_write)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
class Page
|
259
|
+
include JekyllContentSecurityPolicyGenerator
|
260
|
+
|
261
|
+
##
|
262
|
+
# Write page contents
|
263
|
+
def write(dest)
|
264
|
+
super dest
|
265
|
+
Jekyll::Hooks.trigger hook_owner, :post_write, self
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll-content-security-policy-generator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- strongscot
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-04-
|
11
|
+
date: 2021-04-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jekyll
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: nokogiri
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,51 +56,60 @@ dependencies:
|
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: rubocop
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '0
|
89
|
+
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '0
|
97
|
-
description: Helps generate a content security policy
|
96
|
+
version: '0'
|
97
|
+
description: Helps generate a content security policy. Locates inline scripts, images,
|
98
|
+
frames etc.
|
98
99
|
email:
|
99
100
|
- mail@strongscot.com
|
100
101
|
executables: []
|
101
102
|
extensions: []
|
102
103
|
extra_rdoc_files: []
|
103
|
-
files:
|
104
|
+
files:
|
105
|
+
- ".gitignore"
|
106
|
+
- LICENSE
|
107
|
+
- Makefile
|
108
|
+
- README.md
|
109
|
+
- jekyll-content-security-policy-generator.gemspec
|
110
|
+
- lib/jekyll-content-security-policy-generator.rb
|
111
|
+
- lib/jekyll-content-security-policy-generator/hook.rb
|
112
|
+
- lib/jekyll-content-security-policy-generator/version.rb
|
104
113
|
homepage: https://github.com/strongscot/jekyll-content-security-policy-generator
|
105
114
|
licenses:
|
106
115
|
- MIT
|
@@ -123,5 +132,5 @@ requirements: []
|
|
123
132
|
rubygems_version: 3.0.3
|
124
133
|
signing_key:
|
125
134
|
specification_version: 4
|
126
|
-
summary: Helps generate a content security policy
|
135
|
+
summary: Helps generate a content security policy.
|
127
136
|
test_files: []
|