oauthlint-rules 0.2.3 → 0.2.4
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.
package/package.json
CHANGED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
- id: auth.java.crypto.weak-hash
|
|
3
|
+
languages:
|
|
4
|
+
- java
|
|
5
|
+
severity: WARNING
|
|
6
|
+
message: |
|
|
7
|
+
A broken hash algorithm (MD5 or SHA-1) is being instantiated via JCA
|
|
8
|
+
`MessageDigest.getInstance(...)`. MD5 and SHA-1 are cryptographically
|
|
9
|
+
broken: practical collision attacks exist, so they must NOT be used for
|
|
10
|
+
any security purpose — integrity checks, content/token fingerprints,
|
|
11
|
+
digital signatures, HMAC keys, or deduplication that a trust decision
|
|
12
|
+
depends on (CWE-328 / CWE-327).
|
|
13
|
+
|
|
14
|
+
Use SHA-256 or stronger (SHA-384, SHA-512, SHA-3):
|
|
15
|
+
`MessageDigest.getInstance("SHA-256")`. Note: this rule covers the general
|
|
16
|
+
weak-digest case; storing *passwords* needs a dedicated slow hasher
|
|
17
|
+
(BCrypt/Argon2/PBKDF2), which is enforced separately.
|
|
18
|
+
# Match only the algorithm string passed to MessageDigest.getInstance(...).
|
|
19
|
+
# The metavariable-regex flags the broken digests MD5, SHA-1 and the SHA1
|
|
20
|
+
# alias (case-insensitive, optional hyphen). It is scoped to the
|
|
21
|
+
# getInstance(...) instantiation site on purpose so it is low-FP and does
|
|
22
|
+
# NOT overlap auth.java.crypto.weak-password-hash, which instead anchors on
|
|
23
|
+
# a password-named digest()/update() call (and also flags SHA-256/SHA-512 in
|
|
24
|
+
# that password context). "SHA-256"/"SHA-512" are silent here.
|
|
25
|
+
patterns:
|
|
26
|
+
- pattern: java.security.MessageDigest.getInstance($ALG, ...)
|
|
27
|
+
- metavariable-regex:
|
|
28
|
+
metavariable: $ALG
|
|
29
|
+
regex: (?i)^"(md5|sha-?1)"$
|
|
30
|
+
metadata:
|
|
31
|
+
oauthlint-rule-id: AUTH-JAVA-CRYPTO-004
|
|
32
|
+
oauthlint-doc-url: https://oauthlint.dev/rules/java-crypto-weak-hash
|
|
33
|
+
category: security
|
|
34
|
+
cwe: CWE-328
|
|
35
|
+
owasp: A02:2021
|
|
36
|
+
llm-prevalence: MEDIUM
|
|
37
|
+
technology:
|
|
38
|
+
- java
|
|
39
|
+
references:
|
|
40
|
+
- https://cwe.mitre.org/data/definitions/328.html
|
|
41
|
+
- https://csrc.nist.gov/news/2022/nist-transitioning-away-from-sha-1-for-all-apps
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
- id: auth.oauth.access-token-in-url
|
|
3
|
+
languages:
|
|
4
|
+
- javascript
|
|
5
|
+
- typescript
|
|
6
|
+
severity: WARNING
|
|
7
|
+
message: |
|
|
8
|
+
An OAuth `access_token` (or `refresh_token` / `id_token`) is placed in a
|
|
9
|
+
URL query string. URLs leak: the full URL — token included — is recorded
|
|
10
|
+
in server and reverse-proxy access logs, saved in browser history, and
|
|
11
|
+
sent in the `Referer` header to every third-party CDN, analytics, and ad
|
|
12
|
+
script loaded by the destination page. A token in a URL is a leaked token.
|
|
13
|
+
|
|
14
|
+
Send the token in the `Authorization: Bearer …` header, or in a POST
|
|
15
|
+
request body. Never in the URL query string.
|
|
16
|
+
|
|
17
|
+
CWE-598: Use of GET Request Method With Sensitive Query Strings.
|
|
18
|
+
# Anchored to the query-param shape `?<name>=` / `&<name>=` (the `[?&]…=`
|
|
19
|
+
# form) so we fire on token-carrying URLs built as string or template
|
|
20
|
+
# literals, while staying silent on: a token in an `Authorization` header,
|
|
21
|
+
# a POST body / object property `{ access_token: t }` (no leading `?`/`&`
|
|
22
|
+
# and no trailing `=`), `params.set('access_token', …)` builders, and the
|
|
23
|
+
# bare word `access_token` in a comment or non-URL string. Case-insensitive
|
|
24
|
+
# on the param name. This is deliberately distinct from
|
|
25
|
+
# auth.flow.credentials-in-url (which excludes `access_token`) and
|
|
26
|
+
# auth.jwt.in-url (which only matches JWT-shaped `eyJ…` values).
|
|
27
|
+
pattern-regex: '[?&](?i:access_token|refresh_token|id_token)='
|
|
28
|
+
metadata:
|
|
29
|
+
oauthlint-rule-id: AUTH-OAUTH-013
|
|
30
|
+
oauthlint-doc-url: https://oauthlint.dev/rules/oauth-access-token-in-url
|
|
31
|
+
category: security
|
|
32
|
+
cwe: CWE-598
|
|
33
|
+
owasp: A05:2021
|
|
34
|
+
llm-prevalence: MEDIUM
|
|
35
|
+
technology:
|
|
36
|
+
- oauth
|
|
37
|
+
references:
|
|
38
|
+
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration/
|
|
39
|
+
- https://cwe.mitre.org/data/definitions/598.html
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
- id: auth.rust.jwt.no-issuer-validation
|
|
3
|
+
languages:
|
|
4
|
+
- rust
|
|
5
|
+
severity: WARNING
|
|
6
|
+
message: |
|
|
7
|
+
A JWT is decoded with a `jsonwebtoken` `Validation` that never sets the
|
|
8
|
+
expected issuer, so `decode` accepts a token minted by ANY issuer. The
|
|
9
|
+
`jsonwebtoken` crate does not validate the `iss` claim unless you opt in,
|
|
10
|
+
so a token signed by an attacker-controlled or otherwise untrusted issuer
|
|
11
|
+
passes validation as long as the signature checks out. For OAuth/OIDC this
|
|
12
|
+
lets a token from the wrong authorization server be replayed against this
|
|
13
|
+
API.
|
|
14
|
+
|
|
15
|
+
Pin the issuer before decoding, e.g.
|
|
16
|
+
`validation.set_issuer(&["https://issuer.example.com"])` (or set
|
|
17
|
+
`validation.iss`), so only tokens whose `iss` claim matches your trusted
|
|
18
|
+
authorization server are accepted.
|
|
19
|
+
# Modeled on auth.rust.jwt.no-aud-validation: detect a `Validation`
|
|
20
|
+
# (`Validation::new(...)` or `Validation::default()`) that flows into
|
|
21
|
+
# `decode(...)` but never has its issuer pinned. Unlike `aud`/`exp` (default
|
|
22
|
+
# `true`, disabled via `validate_* = false`), the issuer check is OFF by
|
|
23
|
+
# default and must be opted into via `set_issuer(...)` / `validation.iss`,
|
|
24
|
+
# so the vulnerable shape is the ABSENCE of that call. We bind the validator
|
|
25
|
+
# to `$V` at construction, require a `decode` that uses it, and suppress the
|
|
26
|
+
# finding with `pattern-not-inside` when `set_issuer` / `validation.iss` is
|
|
27
|
+
# set on the same `$V`. Matching on the construction (not the `decode` call)
|
|
28
|
+
# mirrors the sibling rule's low-FP, AST-only profile.
|
|
29
|
+
patterns:
|
|
30
|
+
- pattern-either:
|
|
31
|
+
- pattern: let mut $V = Validation::new(...);
|
|
32
|
+
- pattern: let mut $V = Validation::default();
|
|
33
|
+
- pattern-not-inside: |
|
|
34
|
+
let mut $V = ...;
|
|
35
|
+
...
|
|
36
|
+
$V.set_issuer(...);
|
|
37
|
+
...
|
|
38
|
+
- pattern-not-inside: |
|
|
39
|
+
let mut $V = ...;
|
|
40
|
+
...
|
|
41
|
+
$V.iss = $X;
|
|
42
|
+
...
|
|
43
|
+
- pattern-inside: |
|
|
44
|
+
let mut $V = ...;
|
|
45
|
+
...
|
|
46
|
+
decode($TOKEN, $KEY, &$V)
|
|
47
|
+
metadata:
|
|
48
|
+
oauthlint-rule-id: AUTH-RUST-JWT-005
|
|
49
|
+
oauthlint-doc-url: https://oauthlint.dev/rules/rust-jwt-no-issuer-validation
|
|
50
|
+
category: security
|
|
51
|
+
cwe: CWE-345
|
|
52
|
+
owasp: API2:2023
|
|
53
|
+
llm-prevalence: MEDIUM
|
|
54
|
+
technology:
|
|
55
|
+
- jsonwebtoken
|
|
56
|
+
references:
|
|
57
|
+
- https://docs.rs/jsonwebtoken/latest/jsonwebtoken/struct.Validation.html#method.set_issuer
|
|
58
|
+
- https://cwe.mitre.org/data/definitions/345.html
|
|
59
|
+
- https://cwe.mitre.org/data/definitions/287.html
|
|
@@ -16,6 +16,11 @@ rules:
|
|
|
16
16
|
# Matches only the literal `true`. `danger_accept_invalid_certs(false)` and
|
|
17
17
|
# the method's absence are not flagged. `$B` is any builder expression.
|
|
18
18
|
pattern: $B.danger_accept_invalid_certs(true)
|
|
19
|
+
# Safe, deterministic autofix: flip the boolean literal to `false`, which is
|
|
20
|
+
# the secure default and fully resolves the finding. `$B` (the builder
|
|
21
|
+
# expression) is preserved verbatim, so the surrounding chain is untouched —
|
|
22
|
+
# only `true` -> `false` changes.
|
|
23
|
+
fix: $B.danger_accept_invalid_certs(false)
|
|
19
24
|
metadata:
|
|
20
25
|
oauthlint-rule-id: AUTH-RUST-TLS-001
|
|
21
26
|
oauthlint-doc-url: https://oauthlint.dev/rules/rust-tls-accept-invalid-certs
|
|
@@ -18,6 +18,11 @@ rules:
|
|
|
18
18
|
# Matches only the literal `true`. `danger_accept_invalid_hostnames(false)`
|
|
19
19
|
# and the method's absence are not flagged. `$B` is any builder expression.
|
|
20
20
|
pattern: $B.danger_accept_invalid_hostnames(true)
|
|
21
|
+
# Safe, deterministic autofix: flip the boolean literal to `false`, which is
|
|
22
|
+
# the secure default and fully resolves the finding. `$B` (the builder
|
|
23
|
+
# expression) is preserved verbatim, so the surrounding chain is untouched —
|
|
24
|
+
# only `true` -> `false` changes.
|
|
25
|
+
fix: $B.danger_accept_invalid_hostnames(false)
|
|
21
26
|
metadata:
|
|
22
27
|
oauthlint-rule-id: AUTH-RUST-TLS-002
|
|
23
28
|
oauthlint-doc-url: https://oauthlint.dev/rules/rust-tls-accept-invalid-hostnames
|