codelaw-rules-security-js 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_js/LICENSE +23 -0
- codelaw_rules_security_js/NOTICE +22 -0
- codelaw_rules_security_js/README.md +183 -0
- codelaw_rules_security_js/codelaw-pack.toml +6 -0
- codelaw_rules_security_js/corpus.toml +70 -0
- codelaw_rules_security_js/data/sources/browser.json +24 -0
- codelaw_rules_security_js/data/sources/express.json +28 -0
- codelaw_rules_security_js/data/sources/koa.json +18 -0
- codelaw_rules_security_js/data/sources/llm.json +14 -0
- codelaw_rules_security_js/data/sources/nextjs.json +13 -0
- codelaw_rules_security_js/presets/sec-js/recommended.toml +58 -0
- codelaw_rules_security_js/presets/sec-js/strict.toml +15 -0
- codelaw_rules_security_js/rules/sec-js/angularjs-sce-disabled.cases.md +129 -0
- codelaw_rules_security_js/rules/sec-js/angularjs-sce-disabled.md +132 -0
- codelaw_rules_security_js/rules/sec-js/cookie-flags.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/cookie-flags.md +117 -0
- codelaw_rules_security_js/rules/sec-js/express-hardening.cases.md +12 -0
- codelaw_rules_security_js/rules/sec-js/express-hardening.md +135 -0
- codelaw_rules_security_js/rules/sec-js/express-session-secret.cases.md +21 -0
- codelaw_rules_security_js/rules/sec-js/express-session-secret.md +101 -0
- codelaw_rules_security_js/rules/sec-js/graphql-hardening.cases.md +21 -0
- codelaw_rules_security_js/rules/sec-js/graphql-hardening.md +116 -0
- codelaw_rules_security_js/rules/sec-js/helmet-config.cases.md +21 -0
- codelaw_rules_security_js/rules/sec-js/helmet-config.md +88 -0
- codelaw_rules_security_js/rules/sec-js/jwt-verify.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/jwt-verify.md +107 -0
- codelaw_rules_security_js/rules/sec-js/missing-rate-limit.cases.md +22 -0
- codelaw_rules_security_js/rules/sec-js/missing-rate-limit.md +119 -0
- codelaw_rules_security_js/rules/sec-js/no-archive-slip.cases.md +11 -0
- codelaw_rules_security_js/rules/sec-js/no-archive-slip.md +119 -0
- codelaw_rules_security_js/rules/sec-js/no-bad-tag-filter.cases.md +11 -0
- codelaw_rules_security_js/rules/sec-js/no-bad-tag-filter.md +85 -0
- codelaw_rules_security_js/rules/sec-js/no-biased-random.cases.md +21 -0
- codelaw_rules_security_js/rules/sec-js/no-biased-random.md +115 -0
- codelaw_rules_security_js/rules/sec-js/no-bidi-characters.cases.md +21 -0
- codelaw_rules_security_js/rules/sec-js/no-bidi-characters.md +123 -0
- codelaw_rules_security_js/rules/sec-js/no-child-process-shell.cases.md +71 -0
- codelaw_rules_security_js/rules/sec-js/no-child-process-shell.md +141 -0
- codelaw_rules_security_js/rules/sec-js/no-cleartext-http.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/no-cleartext-http.md +147 -0
- codelaw_rules_security_js/rules/sec-js/no-cors-wildcard-credentials.cases.md +21 -0
- codelaw_rules_security_js/rules/sec-js/no-cors-wildcard-credentials.md +92 -0
- codelaw_rules_security_js/rules/sec-js/no-csrf-before-method-override.cases.md +12 -0
- codelaw_rules_security_js/rules/sec-js/no-csrf-before-method-override.md +128 -0
- codelaw_rules_security_js/rules/sec-js/no-dangerously-set-inner-html.cases.md +141 -0
- codelaw_rules_security_js/rules/sec-js/no-dangerously-set-inner-html.md +107 -0
- codelaw_rules_security_js/rules/sec-js/no-document-cookie-token.cases.md +21 -0
- codelaw_rules_security_js/rules/sec-js/no-document-cookie-token.md +89 -0
- codelaw_rules_security_js/rules/sec-js/no-dynamic-script-src.cases.md +31 -0
- codelaw_rules_security_js/rules/sec-js/no-dynamic-script-src.md +100 -0
- codelaw_rules_security_js/rules/sec-js/no-electron-insecure.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/no-electron-insecure.md +134 -0
- codelaw_rules_security_js/rules/sec-js/no-eval.cases.md +52 -0
- codelaw_rules_security_js/rules/sec-js/no-eval.md +102 -0
- codelaw_rules_security_js/rules/sec-js/no-format-string.cases.md +11 -0
- codelaw_rules_security_js/rules/sec-js/no-format-string.md +115 -0
- codelaw_rules_security_js/rules/sec-js/no-hardcoded-crypto-key.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/no-hardcoded-crypto-key.md +96 -0
- codelaw_rules_security_js/rules/sec-js/no-hardcoded-secret.cases.md +61 -0
- codelaw_rules_security_js/rules/sec-js/no-hardcoded-secret.md +112 -0
- codelaw_rules_security_js/rules/sec-js/no-header-injection.cases.md +21 -0
- codelaw_rules_security_js/rules/sec-js/no-header-injection.md +95 -0
- codelaw_rules_security_js/rules/sec-js/no-incomplete-sanitization.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/no-incomplete-sanitization.md +113 -0
- codelaw_rules_security_js/rules/sec-js/no-incomplete-url-check.cases.md +61 -0
- codelaw_rules_security_js/rules/sec-js/no-incomplete-url-check.md +118 -0
- codelaw_rules_security_js/rules/sec-js/no-insecure-random.cases.md +51 -0
- codelaw_rules_security_js/rules/sec-js/no-insecure-random.md +127 -0
- codelaw_rules_security_js/rules/sec-js/no-javascript-url.cases.md +61 -0
- codelaw_rules_security_js/rules/sec-js/no-javascript-url.md +102 -0
- codelaw_rules_security_js/rules/sec-js/no-jquery-html-sink.cases.md +139 -0
- codelaw_rules_security_js/rules/sec-js/no-jquery-html-sink.md +131 -0
- codelaw_rules_security_js/rules/sec-js/no-ldap-injection.cases.md +21 -0
- codelaw_rules_security_js/rules/sec-js/no-ldap-injection.md +87 -0
- codelaw_rules_security_js/rules/sec-js/no-llm-output-to-sink.cases.md +34 -0
- codelaw_rules_security_js/rules/sec-js/no-llm-output-to-sink.md +105 -0
- codelaw_rules_security_js/rules/sec-js/no-log-injection.cases.md +11 -0
- codelaw_rules_security_js/rules/sec-js/no-log-injection.md +113 -0
- codelaw_rules_security_js/rules/sec-js/no-mass-assignment.cases.md +51 -0
- codelaw_rules_security_js/rules/sec-js/no-mass-assignment.md +100 -0
- codelaw_rules_security_js/rules/sec-js/no-new-buffer.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/no-new-buffer.md +120 -0
- codelaw_rules_security_js/rules/sec-js/no-non-literal-fs-filename.cases.md +31 -0
- codelaw_rules_security_js/rules/sec-js/no-non-literal-fs-filename.md +151 -0
- codelaw_rules_security_js/rules/sec-js/no-non-literal-require.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/no-non-literal-require.md +88 -0
- codelaw_rules_security_js/rules/sec-js/no-nosql-injection.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/no-nosql-injection.md +114 -0
- codelaw_rules_security_js/rules/sec-js/no-open-redirect.cases.md +21 -0
- codelaw_rules_security_js/rules/sec-js/no-open-redirect.md +106 -0
- codelaw_rules_security_js/rules/sec-js/no-path-traversal.cases.md +54 -0
- codelaw_rules_security_js/rules/sec-js/no-path-traversal.md +187 -0
- codelaw_rules_security_js/rules/sec-js/no-prompt-injection.cases.md +31 -0
- codelaw_rules_security_js/rules/sec-js/no-prompt-injection.md +118 -0
- codelaw_rules_security_js/rules/sec-js/no-prototype-pollution.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/no-prototype-pollution.md +135 -0
- codelaw_rules_security_js/rules/sec-js/no-secret-in-log.cases.md +31 -0
- codelaw_rules_security_js/rules/sec-js/no-secret-in-log.md +86 -0
- codelaw_rules_security_js/rules/sec-js/no-sensitive-get-query.cases.md +21 -0
- codelaw_rules_security_js/rules/sec-js/no-sensitive-get-query.md +89 -0
- codelaw_rules_security_js/rules/sec-js/no-server-env-in-client.cases.md +42 -0
- codelaw_rules_security_js/rules/sec-js/no-server-env-in-client.md +107 -0
- codelaw_rules_security_js/rules/sec-js/no-sql-template.cases.md +51 -0
- codelaw_rules_security_js/rules/sec-js/no-sql-template.md +112 -0
- codelaw_rules_security_js/rules/sec-js/no-ssrf.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/no-ssrf.md +165 -0
- codelaw_rules_security_js/rules/sec-js/no-ssti.cases.md +54 -0
- codelaw_rules_security_js/rules/sec-js/no-ssti.md +128 -0
- codelaw_rules_security_js/rules/sec-js/no-stack-trace-response.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/no-stack-trace-response.md +102 -0
- codelaw_rules_security_js/rules/sec-js/no-tls-bypass.cases.md +31 -0
- codelaw_rules_security_js/rules/sec-js/no-tls-bypass.md +117 -0
- codelaw_rules_security_js/rules/sec-js/no-token-in-web-storage.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/no-token-in-web-storage.md +92 -0
- codelaw_rules_security_js/rules/sec-js/no-unsafe-deserialize.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/no-unsafe-deserialize.md +115 -0
- codelaw_rules_security_js/rules/sec-js/no-unsafe-regex.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/no-unsafe-regex.md +93 -0
- codelaw_rules_security_js/rules/sec-js/no-unsanitized-html.cases.md +199 -0
- codelaw_rules_security_js/rules/sec-js/no-unsanitized-html.md +143 -0
- codelaw_rules_security_js/rules/sec-js/no-unvalidated-dynamic-method.cases.md +34 -0
- codelaw_rules_security_js/rules/sec-js/no-unvalidated-dynamic-method.md +94 -0
- codelaw_rules_security_js/rules/sec-js/no-user-controlled-auth-bypass.cases.md +11 -0
- codelaw_rules_security_js/rules/sec-js/no-user-controlled-auth-bypass.md +102 -0
- codelaw_rules_security_js/rules/sec-js/no-weak-cipher.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/no-weak-cipher.md +95 -0
- codelaw_rules_security_js/rules/sec-js/no-weak-hash.cases.md +31 -0
- codelaw_rules_security_js/rules/sec-js/no-weak-hash.md +97 -0
- codelaw_rules_security_js/rules/sec-js/no-weak-key-size.cases.md +31 -0
- codelaw_rules_security_js/rules/sec-js/no-weak-key-size.md +117 -0
- codelaw_rules_security_js/rules/sec-js/no-window-open-opener.cases.md +31 -0
- codelaw_rules_security_js/rules/sec-js/no-window-open-opener.md +115 -0
- codelaw_rules_security_js/rules/sec-js/no-xpath-injection.cases.md +21 -0
- codelaw_rules_security_js/rules/sec-js/no-xpath-injection.md +95 -0
- codelaw_rules_security_js/rules/sec-js/no-xxe.cases.md +21 -0
- codelaw_rules_security_js/rules/sec-js/no-xxe.md +124 -0
- codelaw_rules_security_js/rules/sec-js/password-hash-effort.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/password-hash-effort.md +97 -0
- codelaw_rules_security_js/rules/sec-js/postmessage-origin.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/postmessage-origin.md +125 -0
- codelaw_rules_security_js/rules/sec-js/timing-safe-compare.cases.md +41 -0
- codelaw_rules_security_js/rules/sec-js/timing-safe-compare.md +142 -0
- codelaw_rules_security_js/rules/sec-js/upload-limits.cases.md +21 -0
- codelaw_rules_security_js/rules/sec-js/upload-limits.md +115 -0
- codelaw_rules_security_js-0.3.0.dist-info/METADATA +193 -0
- codelaw_rules_security_js-0.3.0.dist-info/RECORD +148 -0
- codelaw_rules_security_js-0.3.0.dist-info/WHEEL +4 -0
- codelaw_rules_security_js-0.3.0.dist-info/licenses/LICENSE +23 -0
|
@@ -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
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
@codelaw/rules-security-js · codelaw-rules-security-js
|
|
2
|
+
|
|
3
|
+
Every rule in this pack is written for codelaw. Rules whose `ported_from:` names a
|
|
4
|
+
source reimplement the documented behaviour of that rule; no source code, pattern or
|
|
5
|
+
documentation text is copied:
|
|
6
|
+
|
|
7
|
+
- eslint-plugin-security (Apache-2.0): detect-buffer-noassert, detect-child-process,
|
|
8
|
+
detect-eval-with-expression, detect-new-buffer, detect-non-literal-fs-filename,
|
|
9
|
+
detect-non-literal-regexp, detect-non-literal-require, detect-object-injection,
|
|
10
|
+
detect-possible-timing-attacks, detect-pseudoRandomBytes, detect-unsafe-regex,
|
|
11
|
+
detect-bidi-characters.
|
|
12
|
+
- Bandit (Apache-2.0): B105, B202, B304, B307, B310, B311, B324, B501, B505, B506, B602, B608.
|
|
13
|
+
- Ruff's `S` rules (MIT): S105, S202, S304, S307, S310, S311, S324, S501, S505, S506, S602, S608.
|
|
14
|
+
- ESLint (MIT): no-script-url.
|
|
15
|
+
|
|
16
|
+
data/sources/*.json are request-source lists (`req.query`, `location.hash`, …) written for this
|
|
17
|
+
pack from the frameworks' public documentation (Express, Koa, Next.js, the DOM).
|
|
18
|
+
|
|
19
|
+
Rule sets under a copyleft or source-available licence — eslint-plugin-no-unsanitized
|
|
20
|
+
(MPL-2.0), njsscan (LGPL-3.0), Semgrep's rules (the Semgrep Rules License) — are
|
|
21
|
+
read for ideas only; no text, pattern or code is taken from them (L2). CodeQL's JavaScript
|
|
22
|
+
queries (MIT) and the OWASP cheat sheets were read for ideas; nothing is copied.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# `@codelaw/rules-security-js` · `codelaw-rules-security-js`
|
|
2
|
+
|
|
3
|
+
codelaw's JavaScript (Node, the browser, Express) security rules: 66 of them, each mapped to a CWE and an OWASP Top 10:2025 category, each with
|
|
4
|
+
a fix class and examples in all four languages. One of codelaw's first-party rule packs
|
|
5
|
+
([SR-RULE-PACKS](../../records/0101_rule-packs.md)). The same files ship on npm as `@codelaw/rules-security-js` and on PyPI as
|
|
6
|
+
`codelaw-rules-security-js`: a Python repository with JavaScript in it gets them too.
|
|
7
|
+
|
|
8
|
+
```toml
|
|
9
|
+
# codelaw.toml
|
|
10
|
+
extends = ["codelaw:js/recommended", "codelaw:sec-js/recommended"]
|
|
11
|
+
preview = true # every rule is `preview` until a corpus run promotes it
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`codelaw init` does not add it: a security pack is chosen, not detected. The rules run on JS, JSX, TS and TSX
|
|
15
|
+
files; the TypeScript-only rules (Angular, NestJS, Prisma, typed casts) are in
|
|
16
|
+
[`security-ts`](../security-ts/README.md), which extends this pack.
|
|
17
|
+
|
|
18
|
+
## Presets
|
|
19
|
+
|
|
20
|
+
<!-- docs-sync:presets -->
|
|
21
|
+
|
|
22
|
+
| preset | rules | ported from |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| `sec-js/recommended` | 55 | high-confidence rules, at `error` |
|
|
25
|
+
| `sec-js/strict` | 66 | `sec-js/recommended` and the heuristic rules, at `warn` |
|
|
26
|
+
|
|
27
|
+
<!-- /docs-sync:presets -->
|
|
28
|
+
|
|
29
|
+
`recommended` holds the 55 high-confidence rules, at `error`; `strict` adds the 11 heuristic ones, at `warn`, so a team can
|
|
30
|
+
start without noise. 17 rules offer a mechanical fix (`auto` 0, `suggest` 17); the other
|
|
31
|
+
49 are `manual`, and each names the safe API in its `How to fix` steps, which the `codelaw-fix` skill walks through.
|
|
32
|
+
|
|
33
|
+
## Rules
|
|
34
|
+
|
|
35
|
+
Every rule carries `security: { cwe, owasp, severity }` ([SR-RULE-FORMAT](../../records/0112_rule-format.md) decision 2a), so
|
|
36
|
+
|
|
37
|
+
- its finding names the CWE (`sec-js/<rule> (CWE-79) …`);
|
|
38
|
+
- `codelaw rules --tag cwe:79` and `--tag owasp:A05` find it, and `codelaw rules --security-coverage` puts it in the OWASP Top 10:2025 matrix;
|
|
39
|
+
- SARIF carries its `security` and `external/cwe/cwe-<n>` tags and a `security-severity` that GitHub code scanning ranks by
|
|
40
|
+
([SR-CLI-MCP](../../records/0115_cli-and-mcp.md) decision 4).
|
|
41
|
+
|
|
42
|
+
### Injection and code execution
|
|
43
|
+
|
|
44
|
+
| rule | rule says | CWE | OWASP 2025 | fix | preset |
|
|
45
|
+
|---|---|---|---|---|---|
|
|
46
|
+
| [`sec-js/no-eval`](rules/sec-js/no-eval.md) | No eval, new Function or string timers | 94 | A05 | manual | recommended |
|
|
47
|
+
| [`sec-js/no-child-process-shell`](rules/sec-js/no-child-process-shell.md) | No shell command built from a value | 78 | A05 | manual | recommended |
|
|
48
|
+
| [`sec-js/no-sql-template`](rules/sec-js/no-sql-template.md) | No SQL built from a template or concatenation | 89 | A05 | manual | recommended |
|
|
49
|
+
| [`sec-js/no-nosql-injection`](rules/sec-js/no-nosql-injection.md) | No request object passed straight to a query, no $where | 943 | A05 | manual | recommended |
|
|
50
|
+
| [`sec-js/no-xpath-injection`](rules/sec-js/no-xpath-injection.md) | No XPath built from a template or concatenation | 643 | A05 | manual | recommended |
|
|
51
|
+
| [`sec-js/no-ldap-injection`](rules/sec-js/no-ldap-injection.md) | No LDAP filter built from a template or concatenation | 90 | A05 | manual | recommended |
|
|
52
|
+
| [`sec-js/no-ssti`](rules/sec-js/no-ssti.md) | No template compiled from a request, no template data taken whole from a request | 1336, 73 | A05 | manual | recommended |
|
|
53
|
+
| [`sec-js/no-header-injection`](rules/sec-js/no-header-injection.md) | No response header value taken from a request | 113 | A05 | manual | recommended |
|
|
54
|
+
| [`sec-js/no-log-injection`](rules/sec-js/no-log-injection.md) | No request data written to a log unchanged | 117 | A09 | manual | strict |
|
|
55
|
+
| [`sec-js/no-format-string`](rules/sec-js/no-format-string.md) | No request data as a format string | 134 | A05 | suggest | strict |
|
|
56
|
+
| [`sec-js/no-non-literal-require`](rules/sec-js/no-non-literal-require.md) | No require or import of a computed module name | 829, 95 | A08 | manual | recommended |
|
|
57
|
+
| [`sec-js/no-unvalidated-dynamic-method`](rules/sec-js/no-unvalidated-dynamic-method.md) | No method chosen by a request value | 470 | A05 | manual | recommended |
|
|
58
|
+
| [`sec-js/no-xxe`](rules/sec-js/no-xxe.md) | No XML entity expansion | 611, 776 | A05 | suggest | recommended |
|
|
59
|
+
| [`sec-js/no-unsafe-deserialize`](rules/sec-js/no-unsafe-deserialize.md) | No deserializer that builds objects or runs code | 502 | A08 | suggest | recommended |
|
|
60
|
+
| [`sec-js/no-new-buffer`](rules/sec-js/no-new-buffer.md) | No new Buffer, no noAssert | 119 | A06 | suggest | recommended |
|
|
61
|
+
| [`sec-js/no-unsafe-regex`](rules/sec-js/no-unsafe-regex.md) | No regular expression that can run for ever, no regular expression built from a request | 1333 | A06 | manual | strict |
|
|
62
|
+
| [`sec-js/no-prototype-pollution`](rules/sec-js/no-prototype-pollution.md) | No request value used as a key to write or merge | 1321 | A08 | manual | recommended |
|
|
63
|
+
|
|
64
|
+
### Cross-site scripting and the browser
|
|
65
|
+
|
|
66
|
+
| rule | rule says | CWE | OWASP 2025 | fix | preset |
|
|
67
|
+
|---|---|---|---|---|---|
|
|
68
|
+
| [`sec-js/no-unsanitized-html`](rules/sec-js/no-unsanitized-html.md) | No HTML written from a value that is not a literal | 79 | A05 | suggest | recommended |
|
|
69
|
+
| [`sec-js/no-dangerously-set-inner-html`](rules/sec-js/no-dangerously-set-inner-html.md) | No dangerouslySetInnerHTML from a value that is not sanitized | 79 | A05 | manual | recommended |
|
|
70
|
+
| [`sec-js/no-javascript-url`](rules/sec-js/no-javascript-url.md) | No javascript: URL, no navigation to a URL taken from the address | 79 | A05 | manual | recommended |
|
|
71
|
+
| [`sec-js/postmessage-origin`](rules/sec-js/postmessage-origin.md) | postMessage names its target, a message handler checks the sender | 346 | A01 | manual | recommended |
|
|
72
|
+
| [`sec-js/no-jquery-html-sink`](rules/sec-js/no-jquery-html-sink.md) | No jQuery call that parses a built string as HTML | 79 | A05 | manual | recommended |
|
|
73
|
+
| [`sec-js/no-window-open-opener`](rules/sec-js/no-window-open-opener.md) | No window.open without noopener | 1022 | A05 | suggest | recommended |
|
|
74
|
+
| [`sec-js/no-dynamic-script-src`](rules/sec-js/no-dynamic-script-src.md) | No script or frame source taken from a value that is not a literal | 829 | A08 | manual | recommended |
|
|
75
|
+
| [`sec-js/no-incomplete-url-check`](rules/sec-js/no-incomplete-url-check.md) | No URL checked with a substring test | 20 | A01 | manual | recommended |
|
|
76
|
+
| [`sec-js/no-incomplete-sanitization`](rules/sec-js/no-incomplete-sanitization.md) | No escaping that stops at the first match, no one-pass stripping | 116 | A05 | suggest | recommended |
|
|
77
|
+
| [`sec-js/no-bad-tag-filter`](rules/sec-js/no-bad-tag-filter.md) | No regular expression that filters HTML tags | 116, 185 | A05 | manual | recommended |
|
|
78
|
+
| [`sec-js/angularjs-sce-disabled`](rules/sec-js/angularjs-sce-disabled.md) | No AngularJS strict contextual escaping switched off | 79 | A05 | manual | strict |
|
|
79
|
+
| [`sec-js/no-bidi-characters`](rules/sec-js/no-bidi-characters.md) | No hidden bidirectional control characters in code | — | A08 | suggest | recommended |
|
|
80
|
+
| [`sec-js/no-document-cookie-token`](rules/sec-js/no-document-cookie-token.md) | No token or session written to document.cookie | 1004 | A07 | manual | recommended |
|
|
81
|
+
| [`sec-js/no-token-in-web-storage`](rules/sec-js/no-token-in-web-storage.md) | No token kept in localStorage or sessionStorage | 922 | A07 | manual | recommended |
|
|
82
|
+
| [`sec-js/no-server-env-in-client`](rules/sec-js/no-server-env-in-client.md) | No server environment variable in a client component, no secret in a public one | 200 | A02 | manual | recommended |
|
|
83
|
+
| [`sec-js/no-electron-insecure`](rules/sec-js/no-electron-insecure.md) | No insecure Electron window setting | 79, 829 | A02 | suggest | recommended |
|
|
84
|
+
|
|
85
|
+
### Access, requests and the server
|
|
86
|
+
|
|
87
|
+
| rule | rule says | CWE | OWASP 2025 | fix | preset |
|
|
88
|
+
|---|---|---|---|---|---|
|
|
89
|
+
| [`sec-js/no-path-traversal`](rules/sec-js/no-path-traversal.md) | No file path taken from a request | 22 | A01 | manual | recommended |
|
|
90
|
+
| [`sec-js/no-archive-slip`](rules/sec-js/no-archive-slip.md) | No archive entry name written to disk unchecked | 22 | A01 | manual | recommended |
|
|
91
|
+
| [`sec-js/no-open-redirect`](rules/sec-js/no-open-redirect.md) | No redirect to an address taken from a request | 601 | A01 | manual | recommended |
|
|
92
|
+
| [`sec-js/no-ssrf`](rules/sec-js/no-ssrf.md) | No request made to an address taken from a request | 918 | A01 | manual | recommended |
|
|
93
|
+
| [`sec-js/no-tls-bypass`](rules/sec-js/no-tls-bypass.md) | No switching off of certificate checks | 295 | A04 | suggest | recommended |
|
|
94
|
+
| [`sec-js/no-cleartext-http`](rules/sec-js/no-cleartext-http.md) | No request made over http:// | 319 | A04 | manual | recommended |
|
|
95
|
+
| [`sec-js/no-cors-wildcard-credentials`](rules/sec-js/no-cors-wildcard-credentials.md) | No CORS that allows every origin together with credentials | 942 | A02 | manual | recommended |
|
|
96
|
+
| [`sec-js/express-hardening`](rules/sec-js/express-hardening.md) | An Express app turns off x-powered-by or uses helmet | 200 | A02 | suggest | strict |
|
|
97
|
+
| [`sec-js/helmet-config`](rules/sec-js/helmet-config.md) | helmet is not given false for a header it sets | 693 | A02 | manual | recommended |
|
|
98
|
+
| [`sec-js/cookie-flags`](rules/sec-js/cookie-flags.md) | A cookie sets httpOnly, secure and sameSite | 614, 1004 | A02 | suggest | recommended |
|
|
99
|
+
| [`sec-js/express-session-secret`](rules/sec-js/express-session-secret.md) | express-session has a secret from the environment and a secure cookie | 798, 614 | A07 | manual | recommended |
|
|
100
|
+
| [`sec-js/no-csrf-before-method-override`](rules/sec-js/no-csrf-before-method-override.md) | No method-override before the CSRF check | 352 | A01 | suggest | recommended |
|
|
101
|
+
| [`sec-js/missing-rate-limit`](rules/sec-js/missing-rate-limit.md) | A login or reset route has a rate limit | 770, 307 | A07 | manual | strict |
|
|
102
|
+
| [`sec-js/no-sensitive-get-query`](rules/sec-js/no-sensitive-get-query.md) | No password, token or secret read from the query string | 598 | A04 | manual | recommended |
|
|
103
|
+
| [`sec-js/no-mass-assignment`](rules/sec-js/no-mass-assignment.md) | No request body written straight into a model | 915 | A01 | manual | recommended |
|
|
104
|
+
| [`sec-js/no-user-controlled-auth-bypass`](rules/sec-js/no-user-controlled-auth-bypass.md) | No privileged branch decided by a request value | 807 | A01 | manual | strict |
|
|
105
|
+
| [`sec-js/upload-limits`](rules/sec-js/upload-limits.md) | multer has size limits and a file filter | 434, 770 | A06 | manual | recommended |
|
|
106
|
+
| [`sec-js/graphql-hardening`](rules/sec-js/graphql-hardening.md) | A GraphQL server limits query depth and cost, and hides introspection | 200, 770 | A02 | manual | strict |
|
|
107
|
+
| [`sec-js/no-non-literal-fs-filename`](rules/sec-js/no-non-literal-fs-filename.md) | No file path that is not a literal | 22 | A01 | manual | strict |
|
|
108
|
+
| [`sec-js/no-stack-trace-response`](rules/sec-js/no-stack-trace-response.md) | No error object or stack trace in a response | 209 | A10 | manual | recommended |
|
|
109
|
+
|
|
110
|
+
### Cryptography, secrets and models
|
|
111
|
+
|
|
112
|
+
| rule | rule says | CWE | OWASP 2025 | fix | preset |
|
|
113
|
+
|---|---|---|---|---|---|
|
|
114
|
+
| [`sec-js/no-weak-hash`](rules/sec-js/no-weak-hash.md) | No MD5 or SHA-1 | 327 | A04 | manual | recommended |
|
|
115
|
+
| [`sec-js/no-weak-cipher`](rules/sec-js/no-weak-cipher.md) | No createCipher, no DES, RC4, Blowfish or ECB | 327 | A04 | manual | recommended |
|
|
116
|
+
| [`sec-js/no-weak-key-size`](rules/sec-js/no-weak-key-size.md) | No short RSA key, no weak elliptic curve | 326 | A04 | suggest | recommended |
|
|
117
|
+
| [`sec-js/no-hardcoded-crypto-key`](rules/sec-js/no-hardcoded-crypto-key.md) | No key or IV written into the source | 321, 329 | A04 | manual | recommended |
|
|
118
|
+
| [`sec-js/no-biased-random`](rules/sec-js/no-biased-random.md) | No byte taken modulo a number that does not divide 256 | 327 | A04 | suggest | recommended |
|
|
119
|
+
| [`sec-js/no-insecure-random`](rules/sec-js/no-insecure-random.md) | No Math.random for a token, a secret or a password | 338 | A04 | suggest | recommended |
|
|
120
|
+
| [`sec-js/password-hash-effort`](rules/sec-js/password-hash-effort.md) | A password is stored with a slow, salted hash | 916 | A04 | manual | recommended |
|
|
121
|
+
| [`sec-js/no-hardcoded-secret`](rules/sec-js/no-hardcoded-secret.md) | No secret written into the source | 798 | A07 | manual | recommended |
|
|
122
|
+
| [`sec-js/timing-safe-compare`](rules/sec-js/timing-safe-compare.md) | A token, hash or signature is compared in constant time | 208 | A07 | suggest | strict |
|
|
123
|
+
| [`sec-js/jwt-verify`](rules/sec-js/jwt-verify.md) | A JWT is verified with a named algorithm, never `none` | 347 | A07 | manual | recommended |
|
|
124
|
+
| [`sec-js/no-secret-in-log`](rules/sec-js/no-secret-in-log.md) | No password, token or secret written to a log | 532 | A09 | manual | strict |
|
|
125
|
+
| [`sec-js/no-llm-output-to-sink`](rules/sec-js/no-llm-output-to-sink.md) | No model output run, written as HTML or used as SQL | 94, 79 | A05 | manual | recommended |
|
|
126
|
+
| [`sec-js/no-prompt-injection`](rules/sec-js/no-prompt-injection.md) | No request data in a model's system prompt | 1427 | A05 | manual | recommended |
|
|
127
|
+
|
|
128
|
+
## How the rules know a value comes from a request
|
|
129
|
+
|
|
130
|
+
Several rules ask whether a sink's argument comes from a request (`sec-js/no-path-traversal`, `no-ssrf`, `no-open-redirect`, `no-ssti`,
|
|
131
|
+
`no-header-injection`, `no-log-injection`, `no-format-string`, `no-unvalidated-dynamic-method`, `no-prototype-pollution`, `no-llm-output-to-sink`,
|
|
132
|
+
`no-prompt-injection`). They use the `from_source:` predicate ([SR-RULE-FORMAT](../../records/0112_rule-format.md) decision 3a). It holds when the
|
|
133
|
+
argument **is** a listed request source (or a method called on one), is built from one by concatenation, interpolation or `?:`, or is a local name
|
|
134
|
+
bound to one **in the same function**, one or more assignments or destructurings away. The sources are in this pack's `data/sources/`:
|
|
135
|
+
|
|
136
|
+
| table | sources |
|
|
137
|
+
|---|---|
|
|
138
|
+
| `sources/express` | `req.body`, `req.query`, `req.params`, `req.headers`, `req.cookies`, `req.url`, … and the same on `request` (Fastify, Hapi) |
|
|
139
|
+
| `sources/koa` | `ctx.request.body`, `ctx.query`, `ctx.params`, `ctx.headers`, `ctx.cookies.get`, … |
|
|
140
|
+
| `sources/nextjs` | `searchParams`, `request.nextUrl.searchParams`, `request.json`, `request.formData`, … |
|
|
141
|
+
| `sources/browser` | `location.hash`, `location.search`, `document.referrer`, `window.name`, `document.cookie`, `event.data`, … |
|
|
142
|
+
| `sources/llm` | `completion.choices`, `response.content`, `message.content`, `result.text`, … (a model SDK's answer) |
|
|
143
|
+
|
|
144
|
+
**`from_source:` is not taint analysis.** It never follows a call (a value passed through any function, a sanitizer or not, stops being a
|
|
145
|
+
source), a return value, a parameter, a closure's outer variable or another file. A rule page that uses it says so. Rules that need to see more
|
|
146
|
+
than one argument position (`path.join(a, b)`) look for a request path in the whole call instead.
|
|
147
|
+
Every other rule fires on a dangerous sink with a value that is not a literal, or on a setting that is unsafe in itself.
|
|
148
|
+
|
|
149
|
+
## What the rules are not
|
|
150
|
+
|
|
151
|
+
- **Not a scanner for the whole program.** They read one file at a time and one function at a time; a value that crosses a function boundary is not seen.
|
|
152
|
+
- **Not a proof of safety.** A clean run means no known-bad shape was found, not that the code is safe. `strict` rules are heuristics and warn.
|
|
153
|
+
- **Not for generated code or tests without care.** Turn rules off for a folder with an `[[overrides]]` entry in `codelaw.toml`; `sec-js/no-hardcoded-secret` and
|
|
154
|
+
`sec-js/no-insecure-random` fire in test helpers too.
|
|
155
|
+
- **Deviations from the first catalogue (W-54).** `sec-js/no-cleartext-http` is `manual`: an edit primitive cannot rewrite the text inside a URL. `sec-js/no-bidi-characters`
|
|
156
|
+
is `suggest`, not `auto`: only a comment is removed whole, and a string or regular expression with a hidden character is left for you.
|
|
157
|
+
`sec-js/no-prototype-pollution` does not flag a literal `.__proto__` write, only a request value used as a key or merged; `sec-js/no-javascript-url` reads the
|
|
158
|
+
address by its text (`location.hash`, `document.referrer`, …), not through a local name.
|
|
159
|
+
|
|
160
|
+
## Not ported, and why
|
|
161
|
+
|
|
162
|
+
[eslint-plugin-security](https://github.com/eslint-community/eslint-plugin-security) (Apache-2.0) is the source of the rules whose `ported_from:` names it; this
|
|
163
|
+
table covers each of its rules. Bandit (Apache-2.0) and Ruff's `S` rules (MIT) are named in `ported_from:` the same way.
|
|
164
|
+
|
|
165
|
+
| eslint-plugin-security rule | here | why |
|
|
166
|
+
|---|---|---|
|
|
167
|
+
| `detect-buffer-noassert` | `sec-js/no-new-buffer` | the `noAssert` argument is flagged there |
|
|
168
|
+
| `detect-child-process` | `sec-js/no-child-process-shell` | narrowed: a literal command is fine; `shell: true` is flagged |
|
|
169
|
+
| `detect-disable-mustache-escape` | not ported | the `escapeMarkup = false` switch is of one old template engine; the XSS it allows is flagged where the output is written (`no-unsanitized-html`, `no-ssti`) |
|
|
170
|
+
| `detect-eval-with-expression` | `sec-js/no-eval` | widened to `new Function` and string timers |
|
|
171
|
+
| `detect-new-buffer` | `sec-js/no-new-buffer` | with a suggested fix |
|
|
172
|
+
| `detect-no-csrf-before-method-override` | `sec-js/no-csrf-before-method-override` | with a suggested reorder |
|
|
173
|
+
| `detect-non-literal-fs-filename` | `sec-js/no-path-traversal` (a request value), `sec-js/no-non-literal-fs-filename` (`strict`) | split: the first is precise, the second is the original's breadth |
|
|
174
|
+
| `detect-non-literal-regexp` | `sec-js/no-unsafe-regex` | only a pattern built from a request is flagged |
|
|
175
|
+
| `detect-non-literal-require` | `sec-js/no-non-literal-require` | |
|
|
176
|
+
| `detect-object-injection` | `sec-js/no-unvalidated-dynamic-method`, `sec-js/no-prototype-pollution` | not ported as written: it flags every `obj[key]`, which is most code; only a key a request supplies is flagged |
|
|
177
|
+
| `detect-possible-timing-attacks` | `sec-js/timing-safe-compare` (`strict`) | limited to names that hold a secret, with a suggested fix |
|
|
178
|
+
| `detect-pseudoRandomBytes` | `sec-js/no-insecure-random` | folded in |
|
|
179
|
+
| `detect-unsafe-regex` | `sec-js/no-unsafe-regex` | nested quantifiers in a regular expression literal |
|
|
180
|
+
| `detect-bidi-characters` | `sec-js/no-bidi-characters` | |
|
|
181
|
+
|
|
182
|
+
Read for ideas only, never copied (L2): CodeQL's JavaScript queries (MIT), the OWASP cheat sheets, and — under licences that forbid copying —
|
|
183
|
+
eslint-plugin-no-unsanitized (MPL-2.0), njsscan (LGPL-3.0) and Semgrep's rules (the Semgrep Rules License).
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
name = "@codelaw/rules-security-js"
|
|
2
|
+
version = "0.3.0"
|
|
3
|
+
min_codelaw = "0.2.0"
|
|
4
|
+
languages = ["javascript", "jsx", "typescript", "tsx"]
|
|
5
|
+
presets = ["sec-js/recommended", "sec-js/strict"]
|
|
6
|
+
description = "codelaw's security rules for JavaScript and JSX, and the TypeScript that runs them: CWE and OWASP Top 10:2025 mapped (SR-RULE-PACKS)"
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# `codelaw test --corpus` finding counts (SR-RULE-AUTHORING decision 4).
|
|
2
|
+
# Rewrite with --update-snapshot, and review the change.
|
|
3
|
+
|
|
4
|
+
[findings]
|
|
5
|
+
"sec-js/angularjs-sce-disabled" = 0
|
|
6
|
+
"sec-js/cookie-flags" = 0
|
|
7
|
+
"sec-js/express-hardening" = 3
|
|
8
|
+
"sec-js/express-session-secret" = 0
|
|
9
|
+
"sec-js/graphql-hardening" = 0
|
|
10
|
+
"sec-js/helmet-config" = 0
|
|
11
|
+
"sec-js/jwt-verify" = 0
|
|
12
|
+
"sec-js/missing-rate-limit" = 0
|
|
13
|
+
"sec-js/no-archive-slip" = 0
|
|
14
|
+
"sec-js/no-bad-tag-filter" = 0
|
|
15
|
+
"sec-js/no-biased-random" = 0
|
|
16
|
+
"sec-js/no-bidi-characters" = 0
|
|
17
|
+
"sec-js/no-child-process-shell" = 0
|
|
18
|
+
"sec-js/no-cleartext-http" = 0
|
|
19
|
+
"sec-js/no-cors-wildcard-credentials" = 0
|
|
20
|
+
"sec-js/no-csrf-before-method-override" = 0
|
|
21
|
+
"sec-js/no-dangerously-set-inner-html" = 0
|
|
22
|
+
"sec-js/no-document-cookie-token" = 0
|
|
23
|
+
"sec-js/no-dynamic-script-src" = 0
|
|
24
|
+
"sec-js/no-electron-insecure" = 0
|
|
25
|
+
"sec-js/no-eval" = 0
|
|
26
|
+
"sec-js/no-format-string" = 0
|
|
27
|
+
"sec-js/no-hardcoded-crypto-key" = 0
|
|
28
|
+
"sec-js/no-hardcoded-secret" = 0
|
|
29
|
+
"sec-js/no-header-injection" = 0
|
|
30
|
+
"sec-js/no-incomplete-sanitization" = 0
|
|
31
|
+
"sec-js/no-incomplete-url-check" = 0
|
|
32
|
+
"sec-js/no-insecure-random" = 1
|
|
33
|
+
"sec-js/no-javascript-url" = 0
|
|
34
|
+
"sec-js/no-jquery-html-sink" = 0
|
|
35
|
+
"sec-js/no-ldap-injection" = 0
|
|
36
|
+
"sec-js/no-llm-output-to-sink" = 0
|
|
37
|
+
"sec-js/no-log-injection" = 0
|
|
38
|
+
"sec-js/no-mass-assignment" = 0
|
|
39
|
+
"sec-js/no-new-buffer" = 0
|
|
40
|
+
"sec-js/no-non-literal-fs-filename" = 9
|
|
41
|
+
"sec-js/no-non-literal-require" = 0
|
|
42
|
+
"sec-js/no-nosql-injection" = 0
|
|
43
|
+
"sec-js/no-open-redirect" = 0
|
|
44
|
+
"sec-js/no-path-traversal" = 0
|
|
45
|
+
"sec-js/no-prompt-injection" = 0
|
|
46
|
+
"sec-js/no-prototype-pollution" = 0
|
|
47
|
+
"sec-js/no-secret-in-log" = 0
|
|
48
|
+
"sec-js/no-sensitive-get-query" = 0
|
|
49
|
+
"sec-js/no-server-env-in-client" = 1
|
|
50
|
+
"sec-js/no-sql-template" = 0
|
|
51
|
+
"sec-js/no-ssrf" = 0
|
|
52
|
+
"sec-js/no-ssti" = 0
|
|
53
|
+
"sec-js/no-stack-trace-response" = 0
|
|
54
|
+
"sec-js/no-tls-bypass" = 0
|
|
55
|
+
"sec-js/no-token-in-web-storage" = 2
|
|
56
|
+
"sec-js/no-unsafe-deserialize" = 0
|
|
57
|
+
"sec-js/no-unsafe-regex" = 0
|
|
58
|
+
"sec-js/no-unsanitized-html" = 0
|
|
59
|
+
"sec-js/no-unvalidated-dynamic-method" = 0
|
|
60
|
+
"sec-js/no-user-controlled-auth-bypass" = 0
|
|
61
|
+
"sec-js/no-weak-cipher" = 0
|
|
62
|
+
"sec-js/no-weak-hash" = 0
|
|
63
|
+
"sec-js/no-weak-key-size" = 0
|
|
64
|
+
"sec-js/no-window-open-opener" = 0
|
|
65
|
+
"sec-js/no-xpath-injection" = 0
|
|
66
|
+
"sec-js/no-xxe" = 0
|
|
67
|
+
"sec-js/password-hash-effort" = 0
|
|
68
|
+
"sec-js/postmessage-origin" = 3
|
|
69
|
+
"sec-js/timing-safe-compare" = 3
|
|
70
|
+
"sec-js/upload-limits" = 0
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[
|
|
2
|
+
"location.hash",
|
|
3
|
+
"location.search",
|
|
4
|
+
"location.href",
|
|
5
|
+
"location.pathname",
|
|
6
|
+
"document.location.hash",
|
|
7
|
+
"document.location.search",
|
|
8
|
+
"document.location.href",
|
|
9
|
+
"window.location.hash",
|
|
10
|
+
"window.location.search",
|
|
11
|
+
"window.location.href",
|
|
12
|
+
"window.location.pathname",
|
|
13
|
+
"document.URL",
|
|
14
|
+
"document.documentURI",
|
|
15
|
+
"document.baseURI",
|
|
16
|
+
"document.referrer",
|
|
17
|
+
"document.cookie",
|
|
18
|
+
"window.name",
|
|
19
|
+
"event.data",
|
|
20
|
+
"e.data",
|
|
21
|
+
"evt.data",
|
|
22
|
+
"message.data",
|
|
23
|
+
"event.newValue"
|
|
24
|
+
]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
[
|
|
2
|
+
"req.body",
|
|
3
|
+
"req.query",
|
|
4
|
+
"req.params",
|
|
5
|
+
"req.headers",
|
|
6
|
+
"req.header",
|
|
7
|
+
"req.get",
|
|
8
|
+
"req.cookies",
|
|
9
|
+
"req.signedCookies",
|
|
10
|
+
"req.url",
|
|
11
|
+
"req.originalUrl",
|
|
12
|
+
"req.path",
|
|
13
|
+
"req.hostname",
|
|
14
|
+
"req.host",
|
|
15
|
+
"req.files",
|
|
16
|
+
"req.file",
|
|
17
|
+
"request.body",
|
|
18
|
+
"request.query",
|
|
19
|
+
"request.params",
|
|
20
|
+
"request.headers",
|
|
21
|
+
"request.header",
|
|
22
|
+
"request.cookies",
|
|
23
|
+
"request.url",
|
|
24
|
+
"request.originalUrl",
|
|
25
|
+
"request.hostname",
|
|
26
|
+
"request.raw.url",
|
|
27
|
+
"request.files"
|
|
28
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[
|
|
2
|
+
"ctx.request.body",
|
|
3
|
+
"ctx.request.query",
|
|
4
|
+
"ctx.request.querystring",
|
|
5
|
+
"ctx.request.headers",
|
|
6
|
+
"ctx.request.url",
|
|
7
|
+
"ctx.request.href",
|
|
8
|
+
"ctx.query",
|
|
9
|
+
"ctx.querystring",
|
|
10
|
+
"ctx.params",
|
|
11
|
+
"ctx.headers",
|
|
12
|
+
"ctx.url",
|
|
13
|
+
"ctx.originalUrl",
|
|
14
|
+
"ctx.path",
|
|
15
|
+
"ctx.hostname",
|
|
16
|
+
"ctx.cookies.get",
|
|
17
|
+
"ctx.get"
|
|
18
|
+
]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
[
|
|
2
|
+
"completion.choices",
|
|
3
|
+
"chatCompletion.choices",
|
|
4
|
+
"response.choices",
|
|
5
|
+
"completion.content",
|
|
6
|
+
"response.content",
|
|
7
|
+
"message.content",
|
|
8
|
+
"msg.content",
|
|
9
|
+
"completion.text",
|
|
10
|
+
"response.output_text",
|
|
11
|
+
"result.output_text",
|
|
12
|
+
"result.text",
|
|
13
|
+
"result.content"
|
|
14
|
+
]
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
description = "high-confidence security rules for JavaScript, at error"
|
|
2
|
+
|
|
3
|
+
[rules]
|
|
4
|
+
"sec-js/cookie-flags" = "error"
|
|
5
|
+
"sec-js/express-session-secret" = "error"
|
|
6
|
+
"sec-js/helmet-config" = "error"
|
|
7
|
+
"sec-js/jwt-verify" = "error"
|
|
8
|
+
"sec-js/no-archive-slip" = "error"
|
|
9
|
+
"sec-js/no-bad-tag-filter" = "error"
|
|
10
|
+
"sec-js/no-biased-random" = "error"
|
|
11
|
+
"sec-js/no-bidi-characters" = "error"
|
|
12
|
+
"sec-js/no-child-process-shell" = "error"
|
|
13
|
+
"sec-js/no-cleartext-http" = "error"
|
|
14
|
+
"sec-js/no-cors-wildcard-credentials" = "error"
|
|
15
|
+
"sec-js/no-csrf-before-method-override" = "error"
|
|
16
|
+
"sec-js/no-dangerously-set-inner-html" = "error"
|
|
17
|
+
"sec-js/no-document-cookie-token" = "error"
|
|
18
|
+
"sec-js/no-dynamic-script-src" = "error"
|
|
19
|
+
"sec-js/no-electron-insecure" = "error"
|
|
20
|
+
"sec-js/no-eval" = "error"
|
|
21
|
+
"sec-js/no-hardcoded-crypto-key" = "error"
|
|
22
|
+
"sec-js/no-hardcoded-secret" = "error"
|
|
23
|
+
"sec-js/no-header-injection" = "error"
|
|
24
|
+
"sec-js/no-incomplete-sanitization" = "error"
|
|
25
|
+
"sec-js/no-incomplete-url-check" = "error"
|
|
26
|
+
"sec-js/no-insecure-random" = "error"
|
|
27
|
+
"sec-js/no-javascript-url" = "error"
|
|
28
|
+
"sec-js/no-jquery-html-sink" = "error"
|
|
29
|
+
"sec-js/no-ldap-injection" = "error"
|
|
30
|
+
"sec-js/no-llm-output-to-sink" = "error"
|
|
31
|
+
"sec-js/no-mass-assignment" = "error"
|
|
32
|
+
"sec-js/no-new-buffer" = "error"
|
|
33
|
+
"sec-js/no-non-literal-require" = "error"
|
|
34
|
+
"sec-js/no-nosql-injection" = "error"
|
|
35
|
+
"sec-js/no-open-redirect" = "error"
|
|
36
|
+
"sec-js/no-path-traversal" = "error"
|
|
37
|
+
"sec-js/no-prompt-injection" = "error"
|
|
38
|
+
"sec-js/no-prototype-pollution" = "error"
|
|
39
|
+
"sec-js/no-sensitive-get-query" = "error"
|
|
40
|
+
"sec-js/no-server-env-in-client" = "error"
|
|
41
|
+
"sec-js/no-sql-template" = "error"
|
|
42
|
+
"sec-js/no-ssrf" = "error"
|
|
43
|
+
"sec-js/no-ssti" = "error"
|
|
44
|
+
"sec-js/no-stack-trace-response" = "error"
|
|
45
|
+
"sec-js/no-tls-bypass" = "error"
|
|
46
|
+
"sec-js/no-token-in-web-storage" = "error"
|
|
47
|
+
"sec-js/no-unsafe-deserialize" = "error"
|
|
48
|
+
"sec-js/no-unsanitized-html" = "error"
|
|
49
|
+
"sec-js/no-unvalidated-dynamic-method" = "error"
|
|
50
|
+
"sec-js/no-weak-cipher" = "error"
|
|
51
|
+
"sec-js/no-weak-hash" = "error"
|
|
52
|
+
"sec-js/no-weak-key-size" = "error"
|
|
53
|
+
"sec-js/no-window-open-opener" = "error"
|
|
54
|
+
"sec-js/no-xpath-injection" = "error"
|
|
55
|
+
"sec-js/no-xxe" = "error"
|
|
56
|
+
"sec-js/password-hash-effort" = "error"
|
|
57
|
+
"sec-js/postmessage-origin" = "error"
|
|
58
|
+
"sec-js/upload-limits" = "error"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
description = "sec-js/recommended and the heuristic security rules, at warn"
|
|
2
|
+
extends = ["codelaw:sec-js/recommended"]
|
|
3
|
+
|
|
4
|
+
[rules]
|
|
5
|
+
"sec-js/angularjs-sce-disabled" = "warn"
|
|
6
|
+
"sec-js/express-hardening" = "warn"
|
|
7
|
+
"sec-js/graphql-hardening" = "warn"
|
|
8
|
+
"sec-js/missing-rate-limit" = "warn"
|
|
9
|
+
"sec-js/no-format-string" = "warn"
|
|
10
|
+
"sec-js/no-log-injection" = "warn"
|
|
11
|
+
"sec-js/no-non-literal-fs-filename" = "warn"
|
|
12
|
+
"sec-js/no-secret-in-log" = "warn"
|
|
13
|
+
"sec-js/no-unsafe-regex" = "warn"
|
|
14
|
+
"sec-js/no-user-controlled-auth-bypass" = "warn"
|
|
15
|
+
"sec-js/timing-safe-compare" = "warn"
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# sec-js/angularjs-sce-disabled — cases
|
|
2
|
+
|
|
3
|
+
### case: resource whitelist
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
$sceDelegateProvider.resourceUrlWhitelist(["**"]);
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```expect
|
|
10
|
+
1:1 sec-js/angularjs-sce-disabled
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### case: trustAsHtml
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
$sce.trustAsHtml(html);
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```expect
|
|
20
|
+
1:1 sec-js/angularjs-sce-disabled
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### case: href whitelist
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
$compileProvider.aHrefSanitizationWhitelist(/./);
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```expect
|
|
30
|
+
1:1 sec-js/angularjs-sce-disabled
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### case: extend: the project function passes
|
|
34
|
+
|
|
35
|
+
```js options={"sanitizers":[{"name":"cleanHtml","module":"@acme/security"}]}
|
|
36
|
+
import { cleanHtml } from "@acme/security";
|
|
37
|
+
$sce.trustAsHtml(cleanHtml(x));
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
```expect
|
|
41
|
+
(none)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### case: extend: the built-in DOMPurify still passes
|
|
45
|
+
|
|
46
|
+
```js options={"sanitizers":[{"name":"cleanHtml","module":"@acme/security"}]}
|
|
47
|
+
import DOMPurify from "dompurify";
|
|
48
|
+
$sce.trustAsHtml(DOMPurify.sanitize(x));
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```expect
|
|
52
|
+
(none)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### case: replace: the project function passes
|
|
56
|
+
|
|
57
|
+
```js options={"sanitizers":[{"name":"cleanHtml","module":"@acme/security"}],"sanitizers_mode":"replace"}
|
|
58
|
+
import { cleanHtml } from "@acme/security";
|
|
59
|
+
$sce.trustAsHtml(cleanHtml(x));
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```expect
|
|
63
|
+
(none)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### case: replace: DOMPurify is reported
|
|
67
|
+
|
|
68
|
+
```js options={"sanitizers":[{"name":"cleanHtml","module":"@acme/security"}],"sanitizers_mode":"replace"}
|
|
69
|
+
import DOMPurify from "dompurify";
|
|
70
|
+
$sce.trustAsHtml(DOMPurify.sanitize(x));
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```expect
|
|
74
|
+
2:1 sec-js/angularjs-sce-disabled
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### case: an aliased import passes
|
|
78
|
+
|
|
79
|
+
```js options={"sanitizers":[{"name":"cleanHtml","module":"@acme/security"}]}
|
|
80
|
+
import { cleanHtml as clean } from "@acme/security";
|
|
81
|
+
$sce.trustAsHtml(clean(x));
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
```expect
|
|
85
|
+
(none)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### case: a same-named local function is reported
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
function sanitizeHtml(x) { return x; }
|
|
92
|
+
$sce.trustAsHtml(sanitizeHtml(x));
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
```expect
|
|
96
|
+
2:1 sec-js/angularjs-sce-disabled
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### case: a function of the same name from another module is reported
|
|
100
|
+
|
|
101
|
+
```js options={"sanitizers":[{"name":"cleanHtml","module":"@acme/security"}]}
|
|
102
|
+
import { cleanHtml } from "left-pad";
|
|
103
|
+
$sce.trustAsHtml(cleanHtml(x));
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
```expect
|
|
107
|
+
2:1 sec-js/angularjs-sce-disabled
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### case: the global DOMPurify passes
|
|
111
|
+
|
|
112
|
+
```js
|
|
113
|
+
$sce.trustAsHtml(DOMPurify.sanitize(x));
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```expect
|
|
117
|
+
(none)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### case: the built-in sanitize-html import passes
|
|
121
|
+
|
|
122
|
+
```js
|
|
123
|
+
import sanitizeHtml from "sanitize-html";
|
|
124
|
+
$sce.trustAsHtml(sanitizeHtml(x));
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
```expect
|
|
128
|
+
(none)
|
|
129
|
+
```
|