oauthlint-rules 0.3.0 → 0.4.0

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 (39) hide show
  1. package/dist/loader.d.ts +1 -1
  2. package/dist/schema.d.ts +79 -19
  3. package/dist/schema.d.ts.map +1 -1
  4. package/dist/schema.js +13 -4
  5. package/dist/schema.js.map +1 -1
  6. package/package.json +1 -1
  7. package/rules/cookie/no-samesite.yml +1 -1
  8. package/rules/cookie/samesite-none-insecure.yml +23 -1
  9. package/rules/cors/null-origin.yml +1 -1
  10. package/rules/cors/reflect-origin.yml +1 -1
  11. package/rules/flow/basic-auth-in-log.yml +99 -0
  12. package/rules/flow/open-redirect.yml +53 -21
  13. package/rules/flow/ssrf.yml +61 -21
  14. package/rules/flow/timing-unsafe-compare.yml +19 -0
  15. package/rules/go/cookie/insecure.yml +1 -1
  16. package/rules/go/cors/allow-all.yml +1 -1
  17. package/rules/go/flow/open-redirect.yml +16 -6
  18. package/rules/go/flow/ssrf.yml +16 -7
  19. package/rules/go/oauth/ropc-grant.yml +15 -0
  20. package/rules/java/cookie/insecure.yml +1 -1
  21. package/rules/java/cors/allow-all.yml +1 -1
  22. package/rules/java/cors/credentialed-wildcard.yml +1 -1
  23. package/rules/java/flow/ssrf.yml +113 -0
  24. package/rules/java/session/fixation-disabled.yml +1 -1
  25. package/rules/java/tls/trust-all-certs.yml +18 -7
  26. package/rules/oauth/no-state.yml +9 -8
  27. package/rules/oauth/open-redirect-callback.yml +18 -3
  28. package/rules/oauth/ropc-grant.yml +8 -3
  29. package/rules/oauth/static-state.yml +8 -7
  30. package/rules/py/cookie/insecure-flags.yml +1 -1
  31. package/rules/py/cors/allow-all.yml +1 -1
  32. package/rules/py/flow/requests-verify-disabled.yml +1 -1
  33. package/rules/py/oauth/ropc-grant.yml +12 -4
  34. package/rules/rust/cookie/insecure.yml +1 -1
  35. package/rules/rust/cors/permissive.yml +1 -1
  36. package/rules/rust/flow/ssrf.yml +90 -0
  37. package/rules/rust/oauth/ropc-grant.yml +17 -0
  38. package/rules/rust/oauth/static-state.yml +25 -5
  39. package/rules/tls/reject-unauthorized.yml +1 -1
@@ -0,0 +1,90 @@
1
+ rules:
2
+ - id: auth.rust.flow.ssrf
3
+ languages:
4
+ - rust
5
+ severity: ERROR
6
+ message: |
7
+ Untrusted request input flows into the URL of an outbound HTTP request.
8
+ Because the destination is attacker-controlled, this is a Server-Side
9
+ Request Forgery (CWE-918): an attacker can point the request at internal
10
+ services behind your firewall, or at the cloud metadata endpoint
11
+ (http://169.254.169.254/...) to steal IAM/instance credentials and pivot
12
+ deeper into your infrastructure.
13
+
14
+ Never pass a request-derived `String` (an axum/actix handler parameter, or
15
+ a value taken from request input) straight into `reqwest::get(...)` or a
16
+ `Client::get(...)` / `Client::post(...).send()`. Validate the destination
17
+ host against an explicit allow-list (parse the URL and check the resolved
18
+ host/scheme, rejecting private/loopback/link-local ranges) before issuing
19
+ the request.
20
+ # Taint mode so indirection (let u = params.url; reqwest::get(u)) is caught,
21
+ # not just the inline form. The source is narrowed to function PARAMETERS
22
+ # (the shape an axum/actix handler takes its request data in) so an
23
+ # arbitrary local `let url = "https://constant"` is not treated as untrusted
24
+ # — only data arriving as a handler/function parameter is. The taint is
25
+ # cleared by an allow-list / host-validation if-guard, mirroring the Python
26
+ # and Go SSRF rules.
27
+ mode: taint
28
+ pattern-sources:
29
+ # A function parameter carrying request data: a bare `String` (the typical
30
+ # axum `String` / extracted field), or an axum `Query`/`Path` extractor
31
+ # (both the type-position and the destructured forms). Focus the parameter
32
+ # so the taint tracks the value rather than the whole function.
33
+ - patterns:
34
+ - pattern-either:
35
+ - pattern: "fn $F(..., $P: String, ...) {...}"
36
+ - pattern: "fn $F(..., $P: Query<$T>, ...) {...}"
37
+ - pattern: "fn $F(..., $P: Path<$T>, ...) {...}"
38
+ - pattern: "fn $F(..., Query($P): Query<$T>, ...) {...}"
39
+ - pattern: "fn $F(..., Path($P): Path<$T>, ...) {...}"
40
+ - focus-metavariable: $P
41
+ pattern-sanitizers:
42
+ # A value used inside an allow-list / host-validation if-guard is treated
43
+ # as vetted, so the guarded request does not fire. A bare `Url::parse(...)`
44
+ # is deliberately NOT a sanitizer: the parsed URL is still
45
+ # attacker-controlled, so parse-then-use without a host check must fire.
46
+ - patterns:
47
+ - pattern: $V
48
+ - pattern-inside: |
49
+ if is_allowed_url(<... $V ...>) {
50
+ ...
51
+ }
52
+ - patterns:
53
+ - pattern: $V
54
+ - pattern-inside: |
55
+ if validate_host(<... $V ...>) {
56
+ ...
57
+ }
58
+ - patterns:
59
+ - pattern: $V
60
+ - pattern-inside: |
61
+ if $ALLOW.contains(<... $V ...>) {
62
+ ...
63
+ }
64
+ pattern-sinks:
65
+ # Focus the URL argument so the finding lands on the tainted destination.
66
+ - patterns:
67
+ - pattern-either:
68
+ - pattern: reqwest::get($URL)
69
+ - pattern: reqwest::blocking::get($URL)
70
+ - pattern: $C.get($URL).send()
71
+ - pattern: $C.post($URL).send()
72
+ - pattern: $C.put($URL).send()
73
+ - pattern: $C.delete($URL).send()
74
+ - pattern: $C.head($URL).send()
75
+ - pattern: $C.request($M, $URL).send()
76
+ - focus-metavariable: $URL
77
+ metadata:
78
+ oauthlint-rule-id: AUTH-RUST-FLOW-002
79
+ oauthlint-doc-url: https://oauthlint.dev/rules/rust-flow-ssrf
80
+ category: security
81
+ cwe: CWE-918
82
+ owasp: API7:2023
83
+ llm-prevalence: HIGH
84
+ technology:
85
+ - reqwest
86
+ - axum
87
+ - actix-web
88
+ references:
89
+ - https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html
90
+ - https://cwe.mitre.org/data/definitions/918.html
@@ -25,6 +25,23 @@ rules:
25
25
  # URL-encoded request body string: "grant_type=password&username=…".
26
26
  - pattern-regex: |-
27
27
  [?&"]grant_type=password(?:[&"\s\\]|$)
28
+ # We flag an application sending ROPC, not the example/test code or vendored
29
+ # client libraries that legitimately exercise the grant. Excluding these
30
+ # trees keeps the signal on first-party application code. (`tests.rs` is the
31
+ # Rust convention for a sibling test module file, e.g. oauth2-rs'
32
+ # `src/token/tests.rs`.)
33
+ paths:
34
+ exclude:
35
+ - "**/test/**"
36
+ - "**/tests.rs"
37
+ - "**/*_test.*"
38
+ - "**/*.test.*"
39
+ - "**/example/**"
40
+ - "**/examples/**"
41
+ - "**/mock*/**"
42
+ - "**/vendor/**"
43
+ - "**/node_modules/**"
44
+ - "**/target/**"
28
45
  metadata:
29
46
  oauthlint-rule-id: AUTH-RUST-OAUTH-001
30
47
  oauthlint-doc-url: https://oauthlint.dev/rules/rust-oauth-ropc-grant
@@ -19,11 +19,31 @@ rules:
19
19
  # direct argument, so `CsrfToken::new(generate())` or a variable is never
20
20
  # flagged. `CsrfToken::new_random()` is a different method and is not
21
21
  # matched.
22
- pattern-either:
23
- - pattern: CsrfToken::new("...".to_string())
24
- - pattern: CsrfToken::new("...".to_owned())
25
- - pattern: CsrfToken::new("...".into())
26
- - pattern: CsrfToken::new(String::from("..."))
22
+ patterns:
23
+ - pattern-either:
24
+ - pattern: CsrfToken::new("...".to_string())
25
+ - pattern: CsrfToken::new("...".to_owned())
26
+ - pattern: CsrfToken::new("...".into())
27
+ - pattern: CsrfToken::new(String::from("..."))
28
+ # Unit tests routinely pass a fixed `state` to assert on the URL — that is
29
+ # the test asserting determinism, not an app shipping a constant CSRF
30
+ # token. The `#[cfg(test)] mod tests { ... }` block is the canonical Rust
31
+ # idiom (e.g. oauth2-rs' own crate tests), so suppress matches inside it.
32
+ - pattern-not-inside: mod tests {...}
33
+ # Belt-and-suspenders: never fire on test/example/vendored/generated trees.
34
+ # `tests.rs` is Rust's sibling test-module file convention.
35
+ paths:
36
+ exclude:
37
+ - "**/test/**"
38
+ - "**/tests.rs"
39
+ - "**/*_test.*"
40
+ - "**/*.test.*"
41
+ - "**/example/**"
42
+ - "**/examples/**"
43
+ - "**/mock*/**"
44
+ - "**/vendor/**"
45
+ - "**/node_modules/**"
46
+ - "**/target/**"
27
47
  metadata:
28
48
  oauthlint-rule-id: AUTH-RUST-OAUTH-003
29
49
  oauthlint-doc-url: https://oauthlint.dev/rules/rust-oauth-static-state
@@ -31,7 +31,7 @@ rules:
31
31
  oauthlint-doc-url: https://oauthlint.dev/rules/tls-reject-unauthorized
32
32
  category: security
33
33
  cwe: CWE-295
34
- owasp: A05:2021
34
+ owasp: A02:2021
35
35
  llm-prevalence: HIGH
36
36
  technology:
37
37
  - node