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.
Files changed (49) hide show
  1. codelaw_rules_security_html/LICENSE +23 -0
  2. codelaw_rules_security_html/NOTICE +9 -0
  3. codelaw_rules_security_html/README.md +98 -0
  4. codelaw_rules_security_html/codelaw-pack.toml +6 -0
  5. codelaw_rules_security_html/corpus.toml +23 -0
  6. codelaw_rules_security_html/presets/sec-html/recommended.toml +18 -0
  7. codelaw_rules_security_html/presets/sec-html/strict.toml +9 -0
  8. codelaw_rules_security_html/rules/sec-html/angularjs-url-expression.cases.md +26 -0
  9. codelaw_rules_security_html/rules/sec-html/angularjs-url-expression.md +34 -0
  10. codelaw_rules_security_html/rules/sec-html/csp-meta-unsafe.cases.md +51 -0
  11. codelaw_rules_security_html/rules/sec-html/csp-meta-unsafe.md +40 -0
  12. codelaw_rules_security_html/rules/sec-html/form-csrf-token.cases.md +51 -0
  13. codelaw_rules_security_html/rules/sec-html/form-csrf-token.md +41 -0
  14. codelaw_rules_security_html/rules/sec-html/iframe-allow-powerful.cases.md +31 -0
  15. codelaw_rules_security_html/rules/sec-html/iframe-allow-powerful.md +39 -0
  16. codelaw_rules_security_html/rules/sec-html/iframe-sandbox.cases.md +63 -0
  17. codelaw_rules_security_html/rules/sec-html/iframe-sandbox.md +34 -0
  18. codelaw_rules_security_html/rules/sec-html/no-credentials-in-url.cases.md +21 -0
  19. codelaw_rules_security_html/rules/sec-html/no-credentials-in-url.md +39 -0
  20. codelaw_rules_security_html/rules/sec-html/no-external-base.cases.md +21 -0
  21. codelaw_rules_security_html/rules/sec-html/no-external-base.md +39 -0
  22. codelaw_rules_security_html/rules/sec-html/no-inline-event-handler.cases.md +32 -0
  23. codelaw_rules_security_html/rules/sec-html/no-inline-event-handler.md +40 -0
  24. codelaw_rules_security_html/rules/sec-html/no-javascript-url.cases.md +61 -0
  25. codelaw_rules_security_html/rules/sec-html/no-javascript-url.md +39 -0
  26. codelaw_rules_security_html/rules/sec-html/no-mixed-content.cases.md +79 -0
  27. codelaw_rules_security_html/rules/sec-html/no-mixed-content.md +34 -0
  28. codelaw_rules_security_html/rules/sec-html/no-plugin-embed.cases.md +25 -0
  29. codelaw_rules_security_html/rules/sec-html/no-plugin-embed.md +40 -0
  30. codelaw_rules_security_html/rules/sec-html/no-secret-in-hidden-input.cases.md +31 -0
  31. codelaw_rules_security_html/rules/sec-html/no-secret-in-hidden-input.md +39 -0
  32. codelaw_rules_security_html/rules/sec-html/no-sensitive-comments.cases.md +64 -0
  33. codelaw_rules_security_html/rules/sec-html/no-sensitive-comments.md +34 -0
  34. codelaw_rules_security_html/rules/sec-html/no-srcdoc-script.cases.md +21 -0
  35. codelaw_rules_security_html/rules/sec-html/no-srcdoc-script.md +39 -0
  36. codelaw_rules_security_html/rules/sec-html/no-template-html-sink.cases.md +23 -0
  37. codelaw_rules_security_html/rules/sec-html/no-template-html-sink.md +39 -0
  38. codelaw_rules_security_html/rules/sec-html/no-unsafe-template-interpolation.cases.md +45 -0
  39. codelaw_rules_security_html/rules/sec-html/no-unsafe-template-interpolation.md +39 -0
  40. codelaw_rules_security_html/rules/sec-html/password-form-post.cases.md +63 -0
  41. codelaw_rules_security_html/rules/sec-html/password-form-post.md +34 -0
  42. codelaw_rules_security_html/rules/sec-html/referrer-policy.cases.md +39 -0
  43. codelaw_rules_security_html/rules/sec-html/referrer-policy.md +34 -0
  44. codelaw_rules_security_html/rules/sec-html/sri-crossorigin.cases.md +35 -0
  45. codelaw_rules_security_html/rules/sec-html/sri-crossorigin.md +34 -0
  46. codelaw_rules_security_html-0.3.0.dist-info/METADATA +108 -0
  47. codelaw_rules_security_html-0.3.0.dist-info/RECORD +49 -0
  48. codelaw_rules_security_html-0.3.0.dist-info/WHEEL +4 -0
  49. 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="&lt;p onclick=x()&gt;a&lt;/p&gt;"></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="&lt;p&gt;hello&lt;/p&gt;"></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="&lt;script&gt;track()&lt;/script&gt;"></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
+ ```