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,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sec-html/no-template-html-sink
|
|
3
|
+
title: "No template binding that writes HTML"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "whether the value is trusted, and how to sanitise it, is the author's call"
|
|
7
|
+
stability: preview
|
|
8
|
+
security: { cwe: [79], owasp: ["A05:2025"], severity: high }
|
|
9
|
+
since: 0.2.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A template does not bind a value as HTML: Angular `[innerHTML]` and `[outerHTML]`, Vue `v-html`, Alpine `x-html`.
|
|
13
|
+
|
|
14
|
+
**Why:** The value is written into the page as markup, so any part of it a user controls is cross-site scripting.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: sec-html/no-template-html-sink
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Bind text instead (`{{ value }}`, `v-text`, `x-text`, `[textContent]`).
|
|
23
|
+
2. If it must be HTML, sanitise it with a maintained library such as DOMPurify and bind the sanitised result.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### HTML
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<div [innerHTML]="comment"></div>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<div>{{ comment }}</div>
|
|
39
|
+
```
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# sec-html/no-unsafe-template-interpolation — cases
|
|
2
|
+
|
|
3
|
+
### case: each syntax
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<p>{{ x|safe }}</p>
|
|
7
|
+
{% autoescape off %}
|
|
8
|
+
<%- user %>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```expect
|
|
12
|
+
1:4 sec-html/no-unsafe-template-interpolation
|
|
13
|
+
2:1 sec-html/no-unsafe-template-interpolation
|
|
14
|
+
3:1 sec-html/no-unsafe-template-interpolation
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### case: a literal string marked safe
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<p>{{ "<b>"|safe }}</p>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```expect
|
|
24
|
+
(none)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### case: EJS include and ERB trim marks
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<%- include('a') %><%- if x -%>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```expect
|
|
34
|
+
(none)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### case: a raw block is not triple-stache
|
|
38
|
+
|
|
39
|
+
```html
|
|
40
|
+
{{{{raw}}}}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```expect
|
|
44
|
+
(none)
|
|
45
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sec-html/no-unsafe-template-interpolation
|
|
3
|
+
title: "No template syntax that turns escaping off"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: manual
|
|
6
|
+
fix_reason: "whether the value is trusted, and how to sanitise it, is the author's call"
|
|
7
|
+
stability: preview
|
|
8
|
+
security: { cwe: [79], owasp: ["A05:2025"], severity: high }
|
|
9
|
+
since: 0.2.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A template does not turn escaping off: Handlebars `{{{ }}}`, Jinja and Nunjucks `|safe`, Django `{% autoescape off %}`, EJS `<%-`.
|
|
13
|
+
|
|
14
|
+
**Why:** The value is written into the page as markup, so any part of it a user controls is cross-site scripting.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: sec-html/no-unsafe-template-interpolation
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## How to fix
|
|
21
|
+
|
|
22
|
+
1. Use the escaping form: `{{ value }}` (Handlebars, Jinja, Django), `<%= value %>` (EJS).
|
|
23
|
+
2. If the value must be markup, sanitise it with a maintained library first and mark only the sanitised result safe.
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
### HTML
|
|
28
|
+
|
|
29
|
+
#### Don't
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<p>{{{ comment }}}</p>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
#### Do
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<p>{{ comment }}</p>
|
|
39
|
+
```
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# sec-html/password-form-post — cases
|
|
2
|
+
|
|
3
|
+
### case: get is replaced
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<form method="GET"><input type="password"></form>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```expect
|
|
10
|
+
1:1 sec-html/password-form-post
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```fixed
|
|
14
|
+
<form method="post"><input type="password"></form>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### case: no method means get
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<form action="/x"><input type="password"></form>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```expect
|
|
24
|
+
1:1 sec-html/password-form-post
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```fixed
|
|
28
|
+
<form method="post" action="/x"><input type="password"></form>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### case: a framework handles the submit
|
|
32
|
+
|
|
33
|
+
```html
|
|
34
|
+
<form (ngSubmit)="go()"><input type="password"></form>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```expect
|
|
38
|
+
(none)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### case: an http action
|
|
42
|
+
|
|
43
|
+
```html
|
|
44
|
+
<form method="post" action="http://a.example/l"><input type="password"></form>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
```expect
|
|
48
|
+
1:21 sec-html/password-form-post
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```fixed
|
|
52
|
+
<form method="post" action="https://a.example/l"><input type="password"></form>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### case: no password, no finding
|
|
56
|
+
|
|
57
|
+
```html
|
|
58
|
+
<form method="get"><input type="search" name="q"></form>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```expect
|
|
62
|
+
(none)
|
|
63
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sec-html/password-form-post
|
|
3
|
+
title: "A form with a password sends it with POST over HTTPS"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: suggest
|
|
6
|
+
fix_reason: "a server that reads only the query string has to change with the form"
|
|
7
|
+
stability: preview
|
|
8
|
+
security: { cwe: [598], owasp: ["A04:2025"], severity: high }
|
|
9
|
+
since: 0.2.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A form holding a password field sets `method="post"` and does not post to an `http:` URL.
|
|
13
|
+
|
|
14
|
+
**Why:** A form with no `method` or with `method="get"` puts the password in the URL, where history, logs and referrers keep it; an `http:` action sends it in the clear.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: sec-html/password-form-post
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
### HTML
|
|
23
|
+
|
|
24
|
+
#### Don't
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<form action="/login" method="get"><input type="password" name="pw"></form>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
#### Do
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<form action="/login" method="post"><input type="password" name="pw"></form>
|
|
34
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# sec-html/referrer-policy — cases
|
|
2
|
+
|
|
3
|
+
### case: an attribute
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<a href="/a" referrerpolicy="unsafe-url">a</a>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```expect
|
|
10
|
+
1:14 sec-html/referrer-policy
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```fixed
|
|
14
|
+
<a href="/a" referrerpolicy="strict-origin-when-cross-origin">a</a>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### case: a meta tag
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<meta name="referrer" content="no-referrer-when-downgrade">
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```expect
|
|
24
|
+
1:23 sec-html/referrer-policy
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
```fixed
|
|
28
|
+
<meta name="referrer" content="strict-origin-when-cross-origin">
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### case: no-referrer is safe
|
|
32
|
+
|
|
33
|
+
```html
|
|
34
|
+
<meta name="referrer" content="no-referrer">
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
```expect
|
|
38
|
+
(none)
|
|
39
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sec-html/referrer-policy
|
|
3
|
+
title: "No referrer policy that leaks full URLs"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: suggest
|
|
6
|
+
fix_reason: "a partner may rely on the full referrer; the safer value is a suggestion"
|
|
7
|
+
stability: preview
|
|
8
|
+
security: { cwe: [200], owasp: ["A02:2025"], severity: low }
|
|
9
|
+
since: 0.2.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A `referrerpolicy` attribute or `<meta name="referrer">` is not `unsafe-url` or `no-referrer-when-downgrade`.
|
|
13
|
+
|
|
14
|
+
**Why:** Both send the full URL of the page, query string included, to other sites, and a URL often holds a token or an identifier.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: sec-html/referrer-policy
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
### HTML
|
|
23
|
+
|
|
24
|
+
#### Don't
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<a href="https://other.example/" referrerpolicy="unsafe-url">Other</a>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
#### Do
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<a href="https://other.example/" referrerpolicy="strict-origin-when-cross-origin">Other</a>
|
|
34
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# sec-html/sri-crossorigin — cases
|
|
2
|
+
|
|
3
|
+
### case: a stylesheet
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<link rel="stylesheet" href="https://cdn.example.com/a.css" integrity="sha384-abc">
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```expect
|
|
10
|
+
1:61 sec-html/sri-crossorigin
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```fixed
|
|
14
|
+
<link rel="stylesheet" href="https://cdn.example.com/a.css" integrity="sha384-abc" crossorigin="anonymous">
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### case: a file on this origin
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<script src="/a.js" integrity="sha384-abc"></script>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```expect
|
|
24
|
+
(none)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### case: crossorigin already there
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<script src="https://cdn.example.com/a.js" integrity="sha384-abc" crossorigin></script>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```expect
|
|
34
|
+
(none)
|
|
35
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sec-html/sri-crossorigin
|
|
3
|
+
title: "A script or stylesheet with an integrity hash has crossorigin"
|
|
4
|
+
languages: [html]
|
|
5
|
+
fix: suggest
|
|
6
|
+
fix_reason: "`anonymous` is right unless the file needs credentials; the suggestion assumes it does not"
|
|
7
|
+
stability: preview
|
|
8
|
+
security: { cwe: [353], owasp: ["A08:2025"], severity: low }
|
|
9
|
+
since: 0.2.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
A `<script>` or `<link>` from another origin that has `integrity` also has `crossorigin`.
|
|
13
|
+
|
|
14
|
+
**Why:** Without `crossorigin` the browser fetches the file without CORS and cannot read it to check the hash, so the `integrity` protects nothing.
|
|
15
|
+
|
|
16
|
+
```codelaw
|
|
17
|
+
native: sec-html/sri-crossorigin
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
### HTML
|
|
23
|
+
|
|
24
|
+
#### Don't
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<script src="https://cdn.example.com/lib.js" integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"></script>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
#### Do
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<script src="https://cdn.example.com/lib.js" integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC" crossorigin="anonymous"></script>
|
|
34
|
+
```
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codelaw-rules-security-html
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: codelaw's security rules for HTML; its presets also turn on the html pack's security rules (SR-RULE-PACKS)
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Project-URL: Repository, https://github.com/arpitarya/codelaw
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# `@codelaw/rules-security-html` · `codelaw-rules-security-html`
|
|
12
|
+
|
|
13
|
+
codelaw's HTML security rules (CSP, mixed content, iframes, forms, template sinks) — one of codelaw's first-party rule packs
|
|
14
|
+
([SR-RULE-PACKS](../../records/0101_rule-packs.md)). The same files ship on npm as `@codelaw/rules-security-html` and on PyPI as
|
|
15
|
+
`codelaw-rules-security-html`. Its presets **extend** `codelaw:html/security`,
|
|
16
|
+
so the html pack's five security rules (`html/require-sri`,
|
|
17
|
+
`html/target-blank-rel`, `html/no-inline-script`, `html/autocomplete-password`,
|
|
18
|
+
`html/meta-refresh`) run without being copied here; it needs the html pack
|
|
19
|
+
(`@codelaw/rules-html` or `codelaw-rules-html`) installed beside it.
|
|
20
|
+
|
|
21
|
+
```toml
|
|
22
|
+
# codelaw.toml
|
|
23
|
+
extends = ["codelaw:html/recommended", "codelaw:sec-html/recommended"]
|
|
24
|
+
preview = true # every rule is `preview` until a corpus run promotes it
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`codelaw init` does not add it: a security pack is chosen, not detected.
|
|
28
|
+
|
|
29
|
+
## Presets
|
|
30
|
+
|
|
31
|
+
<!-- docs-sync:presets -->
|
|
32
|
+
|
|
33
|
+
| preset | rules | ported from |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| `sec-html/recommended` | 19 | extends `html/security` (the html pack's five security rules); high-confidence rules, at `error` |
|
|
36
|
+
| `sec-html/strict` | 24 | `sec-html/recommended` and the heuristic rules, at `warn` |
|
|
37
|
+
|
|
38
|
+
<!-- /docs-sync:presets -->
|
|
39
|
+
|
|
40
|
+
`recommended` holds only high-confidence rules, at `error`; `strict` adds the
|
|
41
|
+
heuristic ones, at `warn`, so a team can start without noise.
|
|
42
|
+
|
|
43
|
+
## Rules
|
|
44
|
+
|
|
45
|
+
| rule | flags | CWE | OWASP 2025 | fix | preset |
|
|
46
|
+
|---|---|---|---|---|---|
|
|
47
|
+
| `sec-html/no-inline-event-handler` | `onclick=`, `onerror=` … attributes (they block a strict CSP) | 79 | A05 | manual | `recommended` |
|
|
48
|
+
| `sec-html/no-javascript-url` | `javascript:` in `href`, `src`, `action`, `formaction`, `xlink:href`, `<object data>` | 79 | A05 | manual | `recommended` |
|
|
49
|
+
| `sec-html/no-mixed-content` | `http://` in `src`, `action`, a stylesheet/script `href`, a download link | 319 | A04 | suggest | `recommended` |
|
|
50
|
+
| `sec-html/password-form-post` | a password form with `method=get`, no `method`, or an `http:` action | 598 | A04 | suggest | `recommended` |
|
|
51
|
+
| `sec-html/iframe-sandbox` | `<iframe>` without `sandbox`, or `allow-scripts` with `allow-same-origin` | 1021 | A02 | suggest | `recommended` |
|
|
52
|
+
| `sec-html/csp-meta-unsafe` | a meta CSP with `'unsafe-inline'`, `'unsafe-eval'`, `*` or `data:` in script sources | 693 | A02 | manual | `recommended` |
|
|
53
|
+
| `sec-html/no-credentials-in-url` | `user:pass@host` in a URL attribute | 522 | A07 | manual | `recommended` |
|
|
54
|
+
| `sec-html/no-template-html-sink` | Angular `[innerHTML]`, Vue `v-html`, Alpine `x-html` | 79 | A05 | manual | `recommended` |
|
|
55
|
+
| `sec-html/referrer-policy` | `referrerpolicy` or `<meta name=referrer>` set to `unsafe-url` or `no-referrer-when-downgrade` | 200 | A02 | suggest | `recommended` |
|
|
56
|
+
| `sec-html/no-srcdoc-script` | `<iframe srcdoc>` holding a script, handler or `javascript:` | 79 | A05 | manual | `recommended` |
|
|
57
|
+
| `sec-html/sri-crossorigin` | `integrity` on a cross-origin file without `crossorigin` | 353 | A08 | suggest | `recommended` |
|
|
58
|
+
| `sec-html/no-secret-in-hidden-input` | a hidden `password`/`token`/`secret`/`api-key` input with a literal value (CSRF tokens excluded) | 798, 200 | A07 | manual | `recommended` |
|
|
59
|
+
| `sec-html/angularjs-url-expression` | `href="{{…}}"` / `src="{{…}}"` in an AngularJS page | 79 | A05 | suggest | `recommended` |
|
|
60
|
+
| `sec-html/no-unsafe-template-interpolation` | Handlebars `{{{ }}}`, `|safe`, `{% autoescape off %}`, EJS `<%-` | 79 | A05 | manual | `recommended` |
|
|
61
|
+
| `sec-html/no-external-base` | `<base href>` on another origin | — | A05 | manual | `strict` |
|
|
62
|
+
| `sec-html/no-plugin-embed` | `<object>`, `<embed>`, `<applet>` | — | A02 | manual | `strict` |
|
|
63
|
+
| `sec-html/no-sensitive-comments` | an HTML comment with a password, key, internal host or a note to remove | 615 | A02 | auto | `strict` |
|
|
64
|
+
| `sec-html/form-csrf-token` | a `method=post` form with no CSRF field (extra names: `names` option) | 352 | A01 | manual | `strict` |
|
|
65
|
+
| `sec-html/iframe-allow-powerful` | a cross-origin `<iframe allow="camera; microphone; …">` | 250 | A02 | manual | `strict` |
|
|
66
|
+
|
|
67
|
+
Each rule is native (a Rust implementation in the engine, read with the same
|
|
68
|
+
document model as the `html/*` rules) and is pattern-level: one start tag,
|
|
69
|
+
one attribute, one comment or one run of template syntax. A value that is
|
|
70
|
+
template code (`{{ }}`, `<% %>`) is judged by its literal prefix only, and
|
|
71
|
+
the AngularJS rule runs only on a page that shows AngularJS. The catalogue
|
|
72
|
+
and its sources are [W-56](../../archive/open/W-56-security-html-pack.md) and the
|
|
73
|
+
OWASP HTML5, CSP and Cross-Site Request Forgery cheat sheets.
|
|
74
|
+
|
|
75
|
+
`sec-html/no-inline-event-handler` and `sec-html/no-javascript-url` overlap
|
|
76
|
+
`html/no-inline-script`, which the preset also turns on: a handler is
|
|
77
|
+
reported twice, once with its CWE. Turn either off in `[rules]` if one report
|
|
78
|
+
is enough.
|
|
79
|
+
|
|
80
|
+
`suggest` fixes (`https://`, `method="post"`, `sandbox`, `crossorigin`,
|
|
81
|
+
`referrerpolicy`) apply with `codelaw fix --unsafe`. A fix is not applied when
|
|
82
|
+
it would add a finding the file did not have: under `strict`, turning a form
|
|
83
|
+
to POST is refused while `sec-html/form-csrf-token` has nothing to see.
|
|
84
|
+
|
|
85
|
+
Every rule here carries `security: { cwe, owasp, severity }`
|
|
86
|
+
([SR-RULE-FORMAT](../../records/0112_rule-format.md) decision 2a), so
|
|
87
|
+
|
|
88
|
+
- its finding names the CWE (`sec-html/<rule> (CWE-79) …`);
|
|
89
|
+
- `codelaw rules --tag cwe:79` and `--tag owasp:A05` find it, and
|
|
90
|
+
`codelaw rules --security-coverage` puts it in the OWASP Top 10:2025 matrix;
|
|
91
|
+
- SARIF carries its `security` and `external/cwe/cwe-<n>` tags and a
|
|
92
|
+
`security-severity` that GitHub code scanning ranks by
|
|
93
|
+
([SR-CLI-MCP](../../records/0115_cli-and-mcp.md) decision 4).
|
|
94
|
+
|
|
95
|
+
## `from_source:` is not taint analysis
|
|
96
|
+
|
|
97
|
+
A rule here that asks whether a sink's argument comes from a request
|
|
98
|
+
uses the `from_source:` predicate ([SR-RULE-FORMAT](../../records/0112_rule-format.md)
|
|
99
|
+
decision 3a). It holds when the argument **is** a listed request source
|
|
100
|
+
(or a method called on one), is built from one by concatenation,
|
|
101
|
+
interpolation or `?:`, or is a local name bound to one **in the same
|
|
102
|
+
function** — one or more assignments or destructurings away. It never
|
|
103
|
+
follows a call, a return value, a parameter, a closure's outer variable or
|
|
104
|
+
another file, so a value that crosses a function boundary is not seen
|
|
105
|
+
(cross-function flow waits on a deeper analysis, as B-049's type-aware
|
|
106
|
+
rules do). Every rule
|
|
107
|
+
page that uses it says so. The sources are listed per framework in this
|
|
108
|
+
pack's `data/sources/<framework>.json`.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
codelaw_rules_security_html/LICENSE,sha256=_R8NFLyGiKUo7mPzbUGbqg3hdEKYhaTsIgBGXqtFfa8,1097
|
|
2
|
+
codelaw_rules_security_html/NOTICE,sha256=pz5xQ3-bTIX7I5AWsynK94tIXi5y-yeXccKjjzuGEoc,595
|
|
3
|
+
codelaw_rules_security_html/README.md,sha256=mYLx3udkKxOfMxS3CJI-l_BbEn8rtm7NSiwySybm4Kk,6533
|
|
4
|
+
codelaw_rules_security_html/codelaw-pack.toml,sha256=GR7Nodld6-voCGQwhhgwQmblAhqvZBz6pKEhjk-4TwY,276
|
|
5
|
+
codelaw_rules_security_html/corpus.toml,sha256=tHkkuidxwbVOLwKfAy8HF8slbkqxikrF35nBjEKyyQk,807
|
|
6
|
+
codelaw_rules_security_html/presets/sec-html/recommended.toml,sha256=Y5lgiv5UZObIIcLHS9bdQKNPtbmzWebEp29Z4Py4J-s,709
|
|
7
|
+
codelaw_rules_security_html/presets/sec-html/strict.toml,sha256=-Zai8FsvhVcdbTCj7MmOhw-DOLmKoqGTq2RO8IEBzfM,329
|
|
8
|
+
codelaw_rules_security_html/rules/sec-html/angularjs-url-expression.cases.md,sha256=7JVgqzxm0_lmUg9fKOly13R9YNWQi1OLGvVz7ELIbeY,443
|
|
9
|
+
codelaw_rules_security_html/rules/sec-html/angularjs-url-expression.md,sha256=vqqeSsFk-j8lb43R18uyzpMGSpBunGV_K0P05m7W2mY,855
|
|
10
|
+
codelaw_rules_security_html/rules/sec-html/csp-meta-unsafe.cases.md,sha256=AtVl27yVI319ZQ60brrubOg-_qDA3LJJIi2otjNcdq8,969
|
|
11
|
+
codelaw_rules_security_html/rules/sec-html/csp-meta-unsafe.md,sha256=NQXfP-UlRtxhWhas0lHLgc6tM42d4Gky23EefpuFH48,1094
|
|
12
|
+
codelaw_rules_security_html/rules/sec-html/form-csrf-token.cases.md,sha256=icHIIZoC96ag56fmw0e3PFF5-3U8J_pNhQW5gLdv2p4,702
|
|
13
|
+
codelaw_rules_security_html/rules/sec-html/form-csrf-token.md,sha256=8WJj33l1vO9kYgZv-PCgAMMJ9b6CiB9l1vytzcg_u-M,1307
|
|
14
|
+
codelaw_rules_security_html/rules/sec-html/iframe-allow-powerful.cases.md,sha256=HnfdfmqIHjR4GP0wh6nfqr4n9pAREiOQFS6CpGQPh4w,454
|
|
15
|
+
codelaw_rules_security_html/rules/sec-html/iframe-allow-powerful.md,sha256=wGrPZau1PPBFi577nboele_LK4QZ3BhiT9g_97AUi7o,1046
|
|
16
|
+
codelaw_rules_security_html/rules/sec-html/iframe-sandbox.cases.md,sha256=vgQvUYc7bPo4Z2dfvZhO4DcF5kDxllxoN-TuxbIqyN4,900
|
|
17
|
+
codelaw_rules_security_html/rules/sec-html/iframe-sandbox.md,sha256=jkfpo5kdjKeDlBM4aRD0OUVnAxg1rk5gfKIq8cRxZ8I,737
|
|
18
|
+
codelaw_rules_security_html/rules/sec-html/no-credentials-in-url.cases.md,sha256=PnPu9cavNhMBu9ztwnpanPepKPlWLkY7DosPY4cBVnI,310
|
|
19
|
+
codelaw_rules_security_html/rules/sec-html/no-credentials-in-url.md,sha256=0Vb-lnsvH8l-nleFCEL9MKheWQhMXoYtN0Az2KDQ3pE,857
|
|
20
|
+
codelaw_rules_security_html/rules/sec-html/no-external-base.cases.md,sha256=eKN4egbHaxF7xlnAcU6K0TFd-IggqKHotbwgK8NuMe0,253
|
|
21
|
+
codelaw_rules_security_html/rules/sec-html/no-external-base.md,sha256=r49try5rfsm8GJj6H05Pyf2M_q97xnaGQoFyp1RxHV8,789
|
|
22
|
+
codelaw_rules_security_html/rules/sec-html/no-inline-event-handler.cases.md,sha256=Wjlcip9wACUmneZe1r8qICP-BtwH8N7hbVzsJqMx8sw,560
|
|
23
|
+
codelaw_rules_security_html/rules/sec-html/no-inline-event-handler.md,sha256=owCbaCFqdoKFFAuNwldEZ8xT5sFpRk6_wNqCn9Udr0g,936
|
|
24
|
+
codelaw_rules_security_html/rules/sec-html/no-javascript-url.cases.md,sha256=AE7UquBNfSM1mj6T789XMdh9LQLd8EMQS_Dhh-lttOw,799
|
|
25
|
+
codelaw_rules_security_html/rules/sec-html/no-javascript-url.md,sha256=O1P4blISboe6WTAZb7Lc_udc5gPonqN1h9NKpGDQNek,952
|
|
26
|
+
codelaw_rules_security_html/rules/sec-html/no-mixed-content.cases.md,sha256=7F-IbMhTB4nZ22Z0Bz9gYOyg5KNvxCZi-5xP2nUpXFc,1177
|
|
27
|
+
codelaw_rules_security_html/rules/sec-html/no-mixed-content.md,sha256=YHg6HfmXctrY8M3MhtlS2eBhZqvOU8rEuPV05CDCQKM,772
|
|
28
|
+
codelaw_rules_security_html/rules/sec-html/no-plugin-embed.cases.md,sha256=jrUm5Y5qITsw9xqqlRN4fbFLf-vmLy4qOeSOkxfdxnE,394
|
|
29
|
+
codelaw_rules_security_html/rules/sec-html/no-plugin-embed.md,sha256=nWyLpHjlSWtpWcOv40iBtG5pfkiUuYJVFHNFa_zPycE,833
|
|
30
|
+
codelaw_rules_security_html/rules/sec-html/no-secret-in-hidden-input.cases.md,sha256=3oxfhm3yjggoqNajdX2lxpzyWlB_Qxx9_4xxRbjim7U,549
|
|
31
|
+
codelaw_rules_security_html/rules/sec-html/no-secret-in-hidden-input.md,sha256=BuJiETRBq1np2pXRqwVtzTem3kxvifXCNYooE7cL6pk,969
|
|
32
|
+
codelaw_rules_security_html/rules/sec-html/no-sensitive-comments.cases.md,sha256=eX0h8As-N8rboXm-PVXiqMna24RiVk32uBTqgiM0H6Y,738
|
|
33
|
+
codelaw_rules_security_html/rules/sec-html/no-sensitive-comments.md,sha256=sBrXanUM1dUq68-tM8kP9Z8pGBnsMImNF7Rlap4lvxE,632
|
|
34
|
+
codelaw_rules_security_html/rules/sec-html/no-srcdoc-script.cases.md,sha256=Hb6aIcqHDTfkWko6PfashKlPw4NokXF5LH20EFrOiCU,309
|
|
35
|
+
codelaw_rules_security_html/rules/sec-html/no-srcdoc-script.md,sha256=FRzzUuL_uOTkj0gzuSOO7S7LrkqPz_0Cg0ngp7BOemA,866
|
|
36
|
+
codelaw_rules_security_html/rules/sec-html/no-template-html-sink.cases.md,sha256=AjJcFJpybPliUXkcyv6eA5BKrMUuvoNO3EqFft7hOxc,302
|
|
37
|
+
codelaw_rules_security_html/rules/sec-html/no-template-html-sink.md,sha256=UTYPLq45GZzaTGPXepIbGR2dU2ijTdCkJ2lAqyBHMjQ,916
|
|
38
|
+
codelaw_rules_security_html/rules/sec-html/no-unsafe-template-interpolation.cases.md,sha256=VwSXPpMD3zqQpAca4huPyBARw0ZIePhg8cf0YO1OqIo,595
|
|
39
|
+
codelaw_rules_security_html/rules/sec-html/no-unsafe-template-interpolation.md,sha256=fA6FYFSL5TDKwHXpF3O4UDYbg5QkgjzQ2wSUf11e7vg,969
|
|
40
|
+
codelaw_rules_security_html/rules/sec-html/password-form-post.cases.md,sha256=y3lcsegT2gEwI2hZH0blqpKr66QXQykaLkUjgnX67SE,978
|
|
41
|
+
codelaw_rules_security_html/rules/sec-html/password-form-post.md,sha256=TLTIM7NVxmIRCIZkSAcDoXG3lT7kCMdmEJpxLqjHV2c,848
|
|
42
|
+
codelaw_rules_security_html/rules/sec-html/referrer-policy.cases.md,sha256=QIbqZ3t53l-jzgA717uisoAdfNHrcstZTZXM7fWrgFo,578
|
|
43
|
+
codelaw_rules_security_html/rules/sec-html/referrer-policy.md,sha256=VXSR7AvibI3GNSbb_Oy6gQS5KNLIUPe_vvbK2JJhSsE,823
|
|
44
|
+
codelaw_rules_security_html/rules/sec-html/sri-crossorigin.cases.md,sha256=h3k6cjyZGrYo_VF_I3oAfvEWY9_F51nmdX0T1fH2o94,606
|
|
45
|
+
codelaw_rules_security_html/rules/sec-html/sri-crossorigin.md,sha256=RLoXHrVCWBouDvMtHFYjHhJWvzMwitasqPsmLVnWzWA,998
|
|
46
|
+
codelaw_rules_security_html-0.3.0.dist-info/METADATA,sha256=dLvfu-hKbVbEtfJUifadHROaDrABYEacRNPhsFNT8vE,6893
|
|
47
|
+
codelaw_rules_security_html-0.3.0.dist-info/WHEEL,sha256=iL940CG79gUG1gJG0fuOXtdNe75u1bVsFzkAeObStpM,97
|
|
48
|
+
codelaw_rules_security_html-0.3.0.dist-info/licenses/LICENSE,sha256=_R8NFLyGiKUo7mPzbUGbqg3hdEKYhaTsIgBGXqtFfa8,1097
|
|
49
|
+
codelaw_rules_security_html-0.3.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Arpit Arya
|
|
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 all
|
|
13
|
+
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 THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
SPDX-License-Identifier: MIT
|