platformos-check 0.4.5 → 0.4.7
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/CHANGELOG.md +11 -1
- data/config/default.yml +8 -0
- data/docs/checks/form_action.md +1 -1
- data/docs/checks/form_authenticity_token.md +55 -0
- data/docs/checks/unreachable_code.md +66 -0
- data/lib/platformos_check/checks/form_authenticity_token.rb +21 -0
- data/lib/platformos_check/checks/unreachable_code.rb +114 -0
- data/lib/platformos_check/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aebbd738b1045c874460b7f1de2cf2774297f36136fce816521dda29ce371652
|
4
|
+
data.tar.gz: c348e3afc68f2a664fe1ad313d41497ad7c977f8de72f3b82df9dda297926c38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 368d39315a05ab34eff3797012af56775ca9a5ff4d8209ed0c44aa2916f97fe5740afa859bbfbbdf34409aa40967efe4236b2394eafcdecfc313c97f62a4dba7
|
7
|
+
data.tar.gz: f912bda1de7e0be84e887ab2f19cde9072e03468ea52265f910e20ff5a7317b7f7f4e6fe83aef690350f21543ffbd495e01c72eddca5c393acfc5500055d6939
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,14 @@
|
|
1
|
-
v0.4.
|
1
|
+
v0.4.7 / 2023-12-22
|
2
|
+
==================
|
3
|
+
|
4
|
+
* Add UnreachableCode check
|
5
|
+
|
6
|
+
v0.4.6 / 2023-12-19
|
7
|
+
==================
|
8
|
+
|
9
|
+
* Add FormAuthenticityToken check
|
10
|
+
|
11
|
+
v0.4.5 / 2023-12-19
|
2
12
|
==================
|
3
13
|
|
4
14
|
* Add FormAction check
|
data/config/default.yml
CHANGED
@@ -50,6 +50,10 @@ UnknownFilter:
|
|
50
50
|
enabled: true
|
51
51
|
ignore: []
|
52
52
|
|
53
|
+
UnreachableCode:
|
54
|
+
enabled: true
|
55
|
+
ignore: []
|
56
|
+
|
53
57
|
UnusedAssign:
|
54
58
|
enabled: true
|
55
59
|
ignore: []
|
@@ -91,6 +95,10 @@ FormAction:
|
|
91
95
|
enabled: true
|
92
96
|
ignore: []
|
93
97
|
|
98
|
+
FormAuthenticityToken:
|
99
|
+
enabled: true
|
100
|
+
ignore: []
|
101
|
+
|
94
102
|
HtmlParsingError:
|
95
103
|
enabled: true
|
96
104
|
ignore: []
|
data/docs/checks/form_action.md
CHANGED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Form authenticity token (`FormAuthenticityToken`)
|
2
|
+
|
3
|
+
In platformOS all POST/PATCH/PUT/DELETE requests are protected from [CSRF Attacks][csrf-attack] through [authenticity_token][page-csrf]
|
4
|
+
Form action defines the endpoint to which browser will make a request after submitting it.
|
5
|
+
|
6
|
+
As a general rule you should include hidden input `<input type="hidden" name="authenticity_token" value="{{ context.authenticity_token }}">` in every form. Missing it will result in session invalidation and any logged in user will be automatically logged out.
|
7
|
+
|
8
|
+
## Check Details
|
9
|
+
|
10
|
+
This check is aimed at ensuring you have not forgotten to include authenticity_token in a form.
|
11
|
+
|
12
|
+
:-1: Examples of **incorrect** code for this check:
|
13
|
+
|
14
|
+
```liquid
|
15
|
+
<form action="dummy/create">
|
16
|
+
</form>
|
17
|
+
```
|
18
|
+
|
19
|
+
:+1: Examples of **correct** code for this check:
|
20
|
+
|
21
|
+
```liquid
|
22
|
+
<form action="/dummy/create">
|
23
|
+
<input type="hidden" name="authenticity_token" value="{{ context.authenticity_token }}">
|
24
|
+
</form>
|
25
|
+
```
|
26
|
+
|
27
|
+
## Check Options
|
28
|
+
|
29
|
+
The default configuration for this check is the following:
|
30
|
+
|
31
|
+
```yaml
|
32
|
+
FormAuthenticityToken:
|
33
|
+
enabled: true
|
34
|
+
```
|
35
|
+
|
36
|
+
## When Not To Use It
|
37
|
+
|
38
|
+
There should be no cases where disabling this rule is needed.
|
39
|
+
|
40
|
+
## Version
|
41
|
+
|
42
|
+
This check has been introduced in PlatformOS Check 0.4.6.
|
43
|
+
|
44
|
+
## Resources
|
45
|
+
|
46
|
+
- [Rule Source][codesource]
|
47
|
+
- [Documentation Source][docsource]
|
48
|
+
- [platformOS Page documentation][page-csrf]
|
49
|
+
- [OWASP Cross Site Request Forgery][csrf-attack]
|
50
|
+
|
51
|
+
[codesource]: /lib/platformos_check/checks/form_authenticity_token.rb
|
52
|
+
[docsource]: /docs/checks/form_authenticity_token.md
|
53
|
+
[page-csrf]: https://documentation.platformos.com/developer-guide/pages/pages#post-put-patch-delete-methods-and-cross-site-request-forgery-attacks
|
54
|
+
[csrf-attack]: https://owasp.org/www-community/attacks/csrf
|
55
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# Unreachable code (`UnreachableCode`)
|
2
|
+
|
3
|
+
Unreachable code reports code that will never be reached, no matter what.
|
4
|
+
|
5
|
+
## Check Details
|
6
|
+
|
7
|
+
This check is aimed at ensuring you will not accidentally write code that will never be reached.
|
8
|
+
|
9
|
+
:-1: Examples of **incorrect** code for this check:
|
10
|
+
|
11
|
+
```liquid
|
12
|
+
assign x = "hello"
|
13
|
+
break
|
14
|
+
log x
|
15
|
+
```
|
16
|
+
|
17
|
+
```liquid
|
18
|
+
if x
|
19
|
+
log x
|
20
|
+
else
|
21
|
+
break
|
22
|
+
log "Stop"
|
23
|
+
endif
|
24
|
+
```
|
25
|
+
|
26
|
+
:+1: Examples of **correct** code for this check:
|
27
|
+
|
28
|
+
```liquid
|
29
|
+
assign x = "hello"
|
30
|
+
log x
|
31
|
+
break
|
32
|
+
```
|
33
|
+
|
34
|
+
```liquid
|
35
|
+
if x
|
36
|
+
log x
|
37
|
+
else
|
38
|
+
log "Stop"
|
39
|
+
break
|
40
|
+
endif
|
41
|
+
```
|
42
|
+
|
43
|
+
## Check Options
|
44
|
+
|
45
|
+
The default configuration for this check is the following:
|
46
|
+
|
47
|
+
```yaml
|
48
|
+
UnreachableCode:
|
49
|
+
enabled: true
|
50
|
+
```
|
51
|
+
|
52
|
+
## When Not To Use It
|
53
|
+
|
54
|
+
There should be no cases where disabling this rule is needed.
|
55
|
+
|
56
|
+
## Version
|
57
|
+
|
58
|
+
This check has been introduced in PlatformOS Check 0.4.7.
|
59
|
+
|
60
|
+
## Resources
|
61
|
+
|
62
|
+
- [Rule Source][codesource]
|
63
|
+
- [Documentation Source][docsource]
|
64
|
+
|
65
|
+
[codesource]: /lib/platformos_check/checks/unreachable_code.rb
|
66
|
+
[docsource]: /docs/checks/unreachable_code.md
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PlatformosCheck
|
4
|
+
class FormAuthenticityToken < HtmlCheck
|
5
|
+
severity :error
|
6
|
+
categories :html
|
7
|
+
doc docs_url(__FILE__)
|
8
|
+
|
9
|
+
AUTHENTICITY_TOKEN_VALUE = /\A\s*{{\s*context\.authenticity_token\s*}}\s*\z/
|
10
|
+
|
11
|
+
def on_form(node)
|
12
|
+
authenticity_toke_inputs = node.children.select { |c| c.name == 'input' && c.attributes['name'] == 'authenticity_token' && c.attributes['value']&.match?(AUTHENTICITY_TOKEN_VALUE) }
|
13
|
+
return if authenticity_toke_inputs.size == 1
|
14
|
+
return add_offense('Duplicated authenticity_token inputs', node:) if authenticity_toke_inputs.size > 1
|
15
|
+
|
16
|
+
add_offense('Missing authenticity_token input <input type="hidden" name="authenticity_token" value="{{ context.authenticity_token }}">', node:) do |corrector|
|
17
|
+
corrector.insert_after(node, "\n<input type=\"hidden\" name=\"authenticity_token\" value=\"{{ context.authenticity_token }}\">")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PlatformosCheck
|
4
|
+
# Recommends using {% liquid ... %} if 5 or more consecutive {% ... %} are found.
|
5
|
+
class UnreachableCode < LiquidCheck
|
6
|
+
severity :error
|
7
|
+
category :liquid
|
8
|
+
doc docs_url(__FILE__)
|
9
|
+
|
10
|
+
FLOW_COMMAND = %i[break continue return]
|
11
|
+
CONDITION_TYPES = Set.new(%i[condition else_condition])
|
12
|
+
INCLUDE_FLOW_COMMAND = %w[break]
|
13
|
+
|
14
|
+
def on_document(node)
|
15
|
+
@processed_files = {}
|
16
|
+
check_unreachable_code(node.children)
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def check_unreachable_code(nodes)
|
22
|
+
nodes = sanitize_children(nodes)
|
23
|
+
nodes.each_cons(2) do |node1, _node2|
|
24
|
+
next unless flow_expression?(node1)
|
25
|
+
|
26
|
+
add_offense("Unreachable code after `#{node1.type_name}`", node: node1)
|
27
|
+
end
|
28
|
+
flow_expression?(nodes.last)
|
29
|
+
end
|
30
|
+
|
31
|
+
def sanitize_children(children)
|
32
|
+
children.reject { |c| c.value.is_a?(String) && c.value.strip == '' }
|
33
|
+
end
|
34
|
+
|
35
|
+
def flow_expression?(node)
|
36
|
+
return false if node.nil?
|
37
|
+
return true if flow_command?(node)
|
38
|
+
|
39
|
+
case node.type_name
|
40
|
+
when :if, :unless
|
41
|
+
check_if(node)
|
42
|
+
false
|
43
|
+
when :for
|
44
|
+
check_for(node)
|
45
|
+
false
|
46
|
+
when :case
|
47
|
+
check_case(node)
|
48
|
+
false
|
49
|
+
when :try_rc, :try
|
50
|
+
check_try(node)
|
51
|
+
false
|
52
|
+
when :block_body
|
53
|
+
node.children.any? { |c| flow_expression?(c) }
|
54
|
+
else
|
55
|
+
false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def check_if(node)
|
60
|
+
node.children.each do |condition|
|
61
|
+
check_unreachable_code(condition.children.detect(&:block_body?).children)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def check_for(node)
|
66
|
+
check_unreachable_code(node.children.detect(&:block_body?).children)
|
67
|
+
end
|
68
|
+
|
69
|
+
def check_case(node)
|
70
|
+
node.children.each do |condition|
|
71
|
+
next unless CONDITION_TYPES.include?(condition.type_name)
|
72
|
+
|
73
|
+
check_unreachable_code(condition.children.detect(&:block_body?).children)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def check_try(node)
|
78
|
+
node.children.each do |block_body|
|
79
|
+
check_unreachable_code(block_body.children)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def flow_command?(node)
|
84
|
+
return true if FLOW_COMMAND.include?(node.type_name)
|
85
|
+
|
86
|
+
return evaluate_include(node.value.template_name_expr) if node.type_name == :include && node.value.template_name_expr.is_a?(String)
|
87
|
+
|
88
|
+
false
|
89
|
+
end
|
90
|
+
|
91
|
+
def evaluate_include(path)
|
92
|
+
return false unless path.is_a?(String)
|
93
|
+
|
94
|
+
@processed_files[path] ||= include_node_contains_flow_command?(@platformos_app.grouped_files[PlatformosCheck::PartialFile][path]&.parse&.root)
|
95
|
+
@processed_files[path]
|
96
|
+
end
|
97
|
+
|
98
|
+
def include_node_contains_flow_command?(root)
|
99
|
+
return false if root.nil?
|
100
|
+
|
101
|
+
root.nodelist.any? do |node|
|
102
|
+
if INCLUDE_FLOW_COMMAND.include?(node.respond_to?(:tag_name) && node.tag_name)
|
103
|
+
true
|
104
|
+
elsif node.respond_to?(:nodelist) && node.nodelist
|
105
|
+
include_node_contains_flow_command?(node)
|
106
|
+
elsif node.respond_to?(:tag_name) && node.tag_name == 'include' && node.template_name_expr.is_a?(String)
|
107
|
+
evaluate_include(node.template_name_expr)
|
108
|
+
else
|
109
|
+
false
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: platformos-check
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Bliszczyk
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2023-12-
|
13
|
+
date: 2023-12-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: graphql
|
@@ -118,6 +118,7 @@ files:
|
|
118
118
|
- docs/checks/convert_include_to_render.md
|
119
119
|
- docs/checks/deprecated_filter.md
|
120
120
|
- docs/checks/form_action.md
|
121
|
+
- docs/checks/form_authenticity_token.md
|
121
122
|
- docs/checks/html_parsing_error.md
|
122
123
|
- docs/checks/img_lazy_loading.md
|
123
124
|
- docs/checks/img_width_and_height.md
|
@@ -133,6 +134,7 @@ files:
|
|
133
134
|
- docs/checks/template_length.md
|
134
135
|
- docs/checks/undefined_object.md
|
135
136
|
- docs/checks/unknown_filter.md
|
137
|
+
- docs/checks/unreachable_code.md
|
136
138
|
- docs/checks/unused_assign.md
|
137
139
|
- docs/checks/unused_partial.md
|
138
140
|
- docs/checks/valid_yaml.md
|
@@ -161,6 +163,7 @@ files:
|
|
161
163
|
- lib/platformos_check/checks/convert_include_to_render.rb
|
162
164
|
- lib/platformos_check/checks/deprecated_filter.rb
|
163
165
|
- lib/platformos_check/checks/form_action.rb
|
166
|
+
- lib/platformos_check/checks/form_authenticity_token.rb
|
164
167
|
- lib/platformos_check/checks/html_parsing_error.rb
|
165
168
|
- lib/platformos_check/checks/img_lazy_loading.rb
|
166
169
|
- lib/platformos_check/checks/img_width_and_height.rb
|
@@ -176,6 +179,7 @@ files:
|
|
176
179
|
- lib/platformos_check/checks/template_length.rb
|
177
180
|
- lib/platformos_check/checks/undefined_object.rb
|
178
181
|
- lib/platformos_check/checks/unknown_filter.rb
|
182
|
+
- lib/platformos_check/checks/unreachable_code.rb
|
179
183
|
- lib/platformos_check/checks/unused_assign.rb
|
180
184
|
- lib/platformos_check/checks/unused_partial.rb
|
181
185
|
- lib/platformos_check/checks/valid_yaml.rb
|