codelaw-rules-security-html 0.3.0__py3-none-any.whl
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.
- codelaw_rules_security_html/LICENSE +23 -0
- codelaw_rules_security_html/NOTICE +9 -0
- codelaw_rules_security_html/README.md +98 -0
- codelaw_rules_security_html/codelaw-pack.toml +6 -0
- codelaw_rules_security_html/corpus.toml +23 -0
- codelaw_rules_security_html/presets/sec-html/recommended.toml +18 -0
- codelaw_rules_security_html/presets/sec-html/strict.toml +9 -0
- codelaw_rules_security_html/rules/sec-html/angularjs-url-expression.cases.md +26 -0
- codelaw_rules_security_html/rules/sec-html/angularjs-url-expression.md +34 -0
- codelaw_rules_security_html/rules/sec-html/csp-meta-unsafe.cases.md +51 -0
- codelaw_rules_security_html/rules/sec-html/csp-meta-unsafe.md +40 -0
- codelaw_rules_security_html/rules/sec-html/form-csrf-token.cases.md +51 -0
- codelaw_rules_security_html/rules/sec-html/form-csrf-token.md +41 -0
- codelaw_rules_security_html/rules/sec-html/iframe-allow-powerful.cases.md +31 -0
- codelaw_rules_security_html/rules/sec-html/iframe-allow-powerful.md +39 -0
- codelaw_rules_security_html/rules/sec-html/iframe-sandbox.cases.md +63 -0
- codelaw_rules_security_html/rules/sec-html/iframe-sandbox.md +34 -0
- codelaw_rules_security_html/rules/sec-html/no-credentials-in-url.cases.md +21 -0
- codelaw_rules_security_html/rules/sec-html/no-credentials-in-url.md +39 -0
- codelaw_rules_security_html/rules/sec-html/no-external-base.cases.md +21 -0
- codelaw_rules_security_html/rules/sec-html/no-external-base.md +39 -0
- codelaw_rules_security_html/rules/sec-html/no-inline-event-handler.cases.md +32 -0
- codelaw_rules_security_html/rules/sec-html/no-inline-event-handler.md +40 -0
- codelaw_rules_security_html/rules/sec-html/no-javascript-url.cases.md +61 -0
- codelaw_rules_security_html/rules/sec-html/no-javascript-url.md +39 -0
- codelaw_rules_security_html/rules/sec-html/no-mixed-content.cases.md +79 -0
- codelaw_rules_security_html/rules/sec-html/no-mixed-content.md +34 -0
- codelaw_rules_security_html/rules/sec-html/no-plugin-embed.cases.md +25 -0
- codelaw_rules_security_html/rules/sec-html/no-plugin-embed.md +40 -0
- codelaw_rules_security_html/rules/sec-html/no-secret-in-hidden-input.cases.md +31 -0
- codelaw_rules_security_html/rules/sec-html/no-secret-in-hidden-input.md +39 -0
- codelaw_rules_security_html/rules/sec-html/no-sensitive-comments.cases.md +64 -0
- codelaw_rules_security_html/rules/sec-html/no-sensitive-comments.md +34 -0
- codelaw_rules_security_html/rules/sec-html/no-srcdoc-script.cases.md +21 -0
- codelaw_rules_security_html/rules/sec-html/no-srcdoc-script.md +39 -0
- codelaw_rules_security_html/rules/sec-html/no-template-html-sink.cases.md +23 -0
- codelaw_rules_security_html/rules/sec-html/no-template-html-sink.md +39 -0
- codelaw_rules_security_html/rules/sec-html/no-unsafe-template-interpolation.cases.md +45 -0
- codelaw_rules_security_html/rules/sec-html/no-unsafe-template-interpolation.md +39 -0
- codelaw_rules_security_html/rules/sec-html/password-form-post.cases.md +63 -0
- codelaw_rules_security_html/rules/sec-html/password-form-post.md +34 -0
- codelaw_rules_security_html/rules/sec-html/referrer-policy.cases.md +39 -0
- codelaw_rules_security_html/rules/sec-html/referrer-policy.md +34 -0
- codelaw_rules_security_html/rules/sec-html/sri-crossorigin.cases.md +35 -0
- codelaw_rules_security_html/rules/sec-html/sri-crossorigin.md +34 -0
- codelaw_rules_security_html-0.3.0.dist-info/METADATA +108 -0
- codelaw_rules_security_html-0.3.0.dist-info/RECORD +49 -0
- codelaw_rules_security_html-0.3.0.dist-info/WHEEL +4 -0
- codelaw_rules_security_html-0.3.0.dist-info/licenses/LICENSE +23 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# sec-html/no-external-base — cases
|
|
2
|
+
|
|
3
|
+
### case: a protocol-relative base
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<base href="//cdn.example.com/">
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```expect
|
|
10
|
+
1:7 sec-html/no-external-base
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### case: a path
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<base href="/app/" target="_self">
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```expect
|
|
20
|
+
(none)
|
|
21
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sec-html/no-external-base
|
|
3
|
+
title: "<base> stays on this origin"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "which origin the page may use is a decision for its owner"
|
|
7
|
+
stability: preview
|
|
8
|
+
security: { owasp: ["A05:2025"], severity: medium }
|
|
9
|
+
since: 0.2.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A `<base href>` is a path, not a URL on another origin.
|
|
13
|
+
|
|
14
|
+
**Why:** Every relative URL, form action and script on the page resolves against `<base>`, so one that points elsewhere hands them all to that site.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: sec-html/no-external-base
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Delete the `<base>` and write the URLs you need in full.
|
|
23
|
+
2. Or make its `href` a path on this origin, such as `/app/`.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### HTML
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<base href="https://cdn.example.com/app/">
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<base href="/app/">
|
|
39
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# sec-html/no-inline-event-handler — cases
|
|
2
|
+
|
|
3
|
+
### case: two handlers on one element
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<button onclick="a()" onfocus="b()">x</button>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```expect
|
|
10
|
+
1:9 sec-html/no-inline-event-handler
|
|
11
|
+
1:23 sec-html/no-inline-event-handler
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### case: framework bindings and data attributes are not handlers
|
|
15
|
+
|
|
16
|
+
```html
|
|
17
|
+
<button data-onclick="a" (click)="b" @click="c" onboarding="d">x</button>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```expect
|
|
21
|
+
(none)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### case: an image error handler
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<img src="a.png" alt="" onerror="fallback(this)">
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```expect
|
|
31
|
+
1:25 sec-html/no-inline-event-handler
|
|
32
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sec-html/no-inline-event-handler
|
|
3
|
+
title: "No inline event handlers"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the handler's code has to move into a script that attaches it"
|
|
7
|
+
stability: preview
|
|
8
|
+
security: { cwe: [79], owasp: ["A05:2025"], severity: medium }
|
|
9
|
+
since: 0.2.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
No element has an inline event handler (`onclick`, `onerror`, `onload`, …).
|
|
13
|
+
|
|
14
|
+
**Why:** An inline handler runs script from an attribute, so a strict Content Security Policy that blocks inline script blocks it too, and a value interpolated into it becomes cross-site scripting.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: sec-html/no-inline-event-handler
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Give the element an id or a class.
|
|
23
|
+
2. Attach the listener with `addEventListener` in a script file.
|
|
24
|
+
3. Delete the `on…` attribute.
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
### HTML
|
|
29
|
+
|
|
30
|
+
#### Don't
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<button type="button" onclick="save()">Save</button>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
#### Do
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<button type="button" id="save">Save</button>
|
|
40
|
+
```
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# sec-html/no-javascript-url — cases
|
|
2
|
+
|
|
3
|
+
### case: case and leading space do not hide it
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<a href=" JavaScript:alert(1)">a</a>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```expect
|
|
10
|
+
1:4 sec-html/no-javascript-url
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### case: a tab inside the scheme is still javascript:
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<a href="java script:alert(1)">a</a>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```expect
|
|
20
|
+
1:4 sec-html/no-javascript-url
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### case: formaction
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<button formaction="javascript:go()">a</button>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```expect
|
|
30
|
+
1:9 sec-html/no-javascript-url
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### case: object data
|
|
34
|
+
|
|
35
|
+
```html
|
|
36
|
+
<object data="javascript:go()"></object>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```expect
|
|
40
|
+
1:9 sec-html/no-javascript-url
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### case: data on another element is not a URL
|
|
44
|
+
|
|
45
|
+
```html
|
|
46
|
+
<div data="javascript:go()">a</div>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```expect
|
|
50
|
+
(none)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### case: an ordinary link
|
|
54
|
+
|
|
55
|
+
```html
|
|
56
|
+
<a href="/javascript:">a</a>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```expect
|
|
60
|
+
(none)
|
|
61
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sec-html/no-javascript-url
|
|
3
|
+
title: "No javascript: URLs"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the script has to move out of the URL into a listener or a real link"
|
|
7
|
+
stability: preview
|
|
8
|
+
security: { cwe: [79], owasp: ["A05:2025"], severity: high }
|
|
9
|
+
since: 0.2.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
An `href`, `src`, `action`, `formaction`, `xlink:href` or `<object data>` is never a `javascript:` URL.
|
|
13
|
+
|
|
14
|
+
**Why:** A `javascript:` URL runs script from an attribute, so it is cross-site scripting waiting for one interpolated value, and a strict Content Security Policy blocks it.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: sec-html/no-javascript-url
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Replace a `javascript:` link with a `<button type="button">` and attach the listener with `addEventListener`.
|
|
23
|
+
2. Point `href`, `src`, `action` or `formaction` at a real URL.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### HTML
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<a href="javascript:void(0)">Menu</a>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<button type="button" id="menu">Menu</button>
|
|
39
|
+
```
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# sec-html/no-mixed-content — cases
|
|
2
|
+
|
|
3
|
+
### case: loopback is trusted
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<img src="http://localhost:3000/a.png" alt="">
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```expect
|
|
10
|
+
(none)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### case: a stylesheet link is fixed
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<link rel="stylesheet" href="http://a.example/s.css">
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```expect
|
|
20
|
+
1:24 sec-html/no-mixed-content
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```fixed
|
|
24
|
+
<link rel="stylesheet" href="https://a.example/s.css">
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### case: a canonical link is only a pointer
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<link rel="canonical" href="http://a.example/">
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```expect
|
|
34
|
+
(none)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### case: a plain link is navigation, a download is not
|
|
38
|
+
|
|
39
|
+
```html
|
|
40
|
+
<a href="http://a.example/x">a</a>
|
|
41
|
+
<a href="http://a.example/x.pdf" download>b</a>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```expect
|
|
45
|
+
2:4 sec-html/no-mixed-content
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
```fixed
|
|
49
|
+
<a href="http://a.example/x">a</a>
|
|
50
|
+
<a href="https://a.example/x.pdf" download>b</a>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### case: a form action
|
|
54
|
+
|
|
55
|
+
```html
|
|
56
|
+
<form action="http://a.example/p"></form>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```expect
|
|
60
|
+
1:7 sec-html/no-mixed-content
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```fixed
|
|
64
|
+
<form action="https://a.example/p"></form>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### case: the scheme is read in any case
|
|
68
|
+
|
|
69
|
+
```html
|
|
70
|
+
<img src="HTTP://a.example/p.png" alt="">
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```expect
|
|
74
|
+
1:6 sec-html/no-mixed-content
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```fixed
|
|
78
|
+
<img src="https://a.example/p.png" alt="">
|
|
79
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sec-html/no-mixed-content
|
|
3
|
+
title: "Subresources and forms load over HTTPS"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: suggest
|
|
6
|
+
fix_reason: "the host may not serve HTTPS; check that it does before switching"
|
|
7
|
+
stability: preview
|
|
8
|
+
security: { cwe: [319], owasp: ["A04:2025"], severity: medium }
|
|
9
|
+
since: 0.2.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A `src`, a form `action`, a stylesheet or script `href` and a download link never use `http://`.
|
|
13
|
+
|
|
14
|
+
**Why:** A resource fetched over plain HTTP can be read and changed by anyone on the network, and a browser blocks or warns about it on an HTTPS page.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: sec-html/no-mixed-content
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
### HTML
|
|
23
|
+
|
|
24
|
+
#### Don't
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<script src="http://cdn.example.com/lib.js"></script>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
#### Do
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<script src="https://cdn.example.com/lib.js"></script>
|
|
34
|
+
```
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# sec-html/no-plugin-embed — cases
|
|
2
|
+
|
|
3
|
+
### case: object, embed and applet
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<object data="a.swf"></object>
|
|
7
|
+
<embed src="a.swf">
|
|
8
|
+
<applet code="A"></applet>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```expect
|
|
12
|
+
1:1 sec-html/no-plugin-embed
|
|
13
|
+
2:1 sec-html/no-plugin-embed
|
|
14
|
+
3:1 sec-html/no-plugin-embed
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### case: an object that holds an image
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<object type="image/svg+xml" data="a.svg"></object>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```expect
|
|
24
|
+
(none)
|
|
25
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sec-html/no-plugin-embed
|
|
3
|
+
title: "No <object>, <embed> or <applet>"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "what replaces the plugin depends on what it showed"
|
|
7
|
+
stability: preview
|
|
8
|
+
security: { owasp: ["A02:2025"], severity: low }
|
|
9
|
+
since: 0.2.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
The page does not use `<object>`, `<embed>` or `<applet>` (an `<object>` that holds an image is fine).
|
|
13
|
+
|
|
14
|
+
**Why:** They load a plugin or another document with the page's trust, and the plugins that needed them are gone from browsers.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: sec-html/no-plugin-embed
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Use `<img>`, `<video>` or `<audio>` for media.
|
|
23
|
+
2. Use a sandboxed `<iframe>` for another document.
|
|
24
|
+
3. Use `<a download>` for a file to fetch.
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
### HTML
|
|
29
|
+
|
|
30
|
+
#### Don't
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<embed src="movie.swf">
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
#### Do
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<video src="movie.mp4" controls></video>
|
|
40
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# sec-html/no-secret-in-hidden-input — cases
|
|
2
|
+
|
|
3
|
+
### case: a literal key
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<input type="hidden" name="api_key" value="sk_live_1">
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```expect
|
|
10
|
+
1:37 sec-html/no-secret-in-hidden-input
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### case: csrf tokens are fine
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<input type="hidden" name="csrf_token" value="abc"><input type="hidden" name="_token" value="abc">
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```expect
|
|
20
|
+
(none)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### case: a value filled in at render time or empty
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<input type="hidden" name="api_key" value="{{ key }}"><input type="hidden" name="api_key" value="">
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```expect
|
|
30
|
+
(none)
|
|
31
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sec-html/no-secret-in-hidden-input
|
|
3
|
+
title: "No secret in a hidden input"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "where the secret should live is a design decision"
|
|
7
|
+
stability: preview
|
|
8
|
+
security: { cwe: [798, 200], owasp: ["A07:2025"], severity: high }
|
|
9
|
+
since: 0.2.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A hidden input named like a password, token, secret or API key does not hold a literal value (CSRF tokens are excluded).
|
|
13
|
+
|
|
14
|
+
**Why:** A hidden field is part of the page everyone receives, so a secret written into it is disclosed to every visitor.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: sec-html/no-secret-in-hidden-input
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Keep the secret on the server and send a session or a reference instead.
|
|
23
|
+
2. If the field is an anti-forgery token, name it `csrf_token`, `_csrf` or the framework's own name.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### HTML
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<input type="hidden" name="api_key" value="sk_live_51Habc">
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
|
39
|
+
```
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# sec-html/no-sensitive-comments — cases
|
|
2
|
+
|
|
3
|
+
### case: a comment on its own line goes with the line
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<p>a</p>
|
|
7
|
+
<!-- password: hunter2 -->
|
|
8
|
+
<p>b</p>
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
```expect
|
|
13
|
+
2:3 sec-html/no-sensitive-comments
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
```fixed
|
|
17
|
+
<p>a</p>
|
|
18
|
+
<p>b</p>
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### case: a comment after other markup
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<p>a</p><!-- TODO remove this -->
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```expect
|
|
29
|
+
1:9 sec-html/no-sensitive-comments
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```fixed
|
|
33
|
+
<p>a</p>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### case: a private address
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<!-- the API is at 10.0.3.7 -->
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```expect
|
|
43
|
+
1:1 sec-html/no-sensitive-comments
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### case: an ordinary comment
|
|
47
|
+
|
|
48
|
+
```html
|
|
49
|
+
<!-- navigation -->
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
```expect
|
|
53
|
+
(none)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### case: a conditional comment is not a note
|
|
57
|
+
|
|
58
|
+
```html
|
|
59
|
+
<!--[if IE]><p>password: x</p><![endif]-->
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```expect
|
|
63
|
+
(none)
|
|
64
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sec-html/no-sensitive-comments
|
|
3
|
+
title: "No comment that exposes a secret or an internal host"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: auto
|
|
6
|
+
stability: preview
|
|
7
|
+
security: { cwe: [615], owasp: ["A02:2025"], severity: low }
|
|
8
|
+
since: 0.2.0
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
An HTML comment does not hold a password, key, token, private IP address, internal host name, or a note to remove it before release.
|
|
12
|
+
|
|
13
|
+
**Why:** Comments are sent to every visitor, so a developer's note becomes a disclosure.
|
|
14
|
+
|
|
15
|
+
```codelaw
|
|
16
|
+
native: sec-html/no-sensitive-comments
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Examples
|
|
20
|
+
|
|
21
|
+
### HTML
|
|
22
|
+
|
|
23
|
+
#### Don't
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<!-- password: hunter2 -->
|
|
27
|
+
<p>Welcome</p>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
#### Do
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<p>Welcome</p>
|
|
34
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# sec-html/no-srcdoc-script — cases
|
|
2
|
+
|
|
3
|
+
### case: an event handler inside srcdoc
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<iframe srcdoc="<p onclick=x()>a</p>"></iframe>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```expect
|
|
10
|
+
1:9 sec-html/no-srcdoc-script
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### case: plain markup
|
|
14
|
+
|
|
15
|
+
```html
|
|
16
|
+
<iframe srcdoc="<p>hello</p>"></iframe>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```expect
|
|
20
|
+
(none)
|
|
21
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sec-html/no-srcdoc-script
|
|
3
|
+
title: "An iframe's srcdoc holds no script"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "the framed document has to become a file or be sandboxed"
|
|
7
|
+
stability: preview
|
|
8
|
+
security: { cwe: [79], owasp: ["A05:2025"], severity: high }
|
|
9
|
+
since: 0.2.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
An `<iframe srcdoc>` does not contain a `<script>`, an event handler or a `javascript:` URL.
|
|
13
|
+
|
|
14
|
+
**Why:** `srcdoc` content runs with the origin of the page that holds it unless the iframe is sandboxed, so script in it is script in the page.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: sec-html/no-srcdoc-script
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Move the document to its own file and load it with `src`.
|
|
23
|
+
2. Add `sandbox` without `allow-same-origin`.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### HTML
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<iframe srcdoc="<script>track()</script>"></iframe>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<iframe sandbox src="/track.html"></iframe>
|
|
39
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# sec-html/no-template-html-sink — cases
|
|
2
|
+
|
|
3
|
+
### case: Vue and Angular
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<p v-html="a"></p>
|
|
7
|
+
<div [innerHTML]="b"></div>
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```expect
|
|
11
|
+
1:4 sec-html/no-template-html-sink
|
|
12
|
+
2:6 sec-html/no-template-html-sink
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### case: a text binding
|
|
16
|
+
|
|
17
|
+
```html
|
|
18
|
+
<i [textContent]="c"></i>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```expect
|
|
22
|
+
(none)
|
|
23
|
+
```
|