oauthlint-rules 0.3.1 → 0.5.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 (49) hide show
  1. package/dist/loader.d.ts +1 -1
  2. package/dist/schema.d.ts +19 -19
  3. package/dist/schema.d.ts.map +1 -1
  4. package/dist/schema.js +1 -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 +1 -1
  9. package/rules/cors/null-origin.yml +1 -1
  10. package/rules/cors/reflect-origin.yml +1 -1
  11. package/rules/express/cookie-insecure.yml +44 -0
  12. package/rules/flow/basic-auth-in-log.yml +99 -0
  13. package/rules/flow/open-redirect.yml +42 -21
  14. package/rules/flow/ssrf.yml +43 -22
  15. package/rules/flow/timing-unsafe-compare.yml +1 -1
  16. package/rules/go/cookie/insecure.yml +1 -1
  17. package/rules/go/cors/allow-all.yml +1 -1
  18. package/rules/go/flow/open-redirect.yml +16 -6
  19. package/rules/go/flow/ssrf.yml +16 -7
  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/crypto/noop-password-encoder.yml +38 -0
  24. package/rules/java/flow/ssrf.yml +113 -0
  25. package/rules/java/session/fixation-disabled.yml +1 -1
  26. package/rules/java/tls/trust-all-certs.yml +18 -7
  27. package/rules/java/web/security-ignoring-all.yml +38 -0
  28. package/rules/java/web/wildcard-permit-all.yml +37 -0
  29. package/rules/nextauth/hardcoded-secret.yml +62 -0
  30. package/rules/oauth/no-state.yml +9 -8
  31. package/rules/oauth/open-redirect-callback.yml +18 -3
  32. package/rules/oauth/static-state.yml +8 -7
  33. package/rules/passport/jwt-ignore-expiration.yml +58 -0
  34. package/rules/py/cookie/insecure-flags.yml +1 -1
  35. package/rules/py/cors/allow-all.yml +1 -1
  36. package/rules/py/cors/fastapi-wildcard-credentials.yml +49 -0
  37. package/rules/py/crypto/passlib-weak-scheme.yml +40 -0
  38. package/rules/py/django/cors-allow-all.yml +34 -0
  39. package/rules/py/drf/default-authentication-empty.yml +32 -0
  40. package/rules/py/drf/default-permission-allowany.yml +35 -0
  41. package/rules/py/drf/view-authentication-disabled.yml +34 -0
  42. package/rules/py/flask/session-cookie-insecure.yml +42 -0
  43. package/rules/py/flow/requests-verify-disabled.yml +30 -18
  44. package/rules/py/jwt/verify-claims-disabled.yml +45 -0
  45. package/rules/py/oauth/token-request-verify-disabled.yml +14 -4
  46. package/rules/rust/cookie/insecure.yml +1 -1
  47. package/rules/rust/cors/permissive.yml +1 -1
  48. package/rules/rust/flow/ssrf.yml +90 -0
  49. package/rules/tls/reject-unauthorized.yml +1 -1
@@ -0,0 +1,34 @@
1
+ rules:
2
+ - id: auth.py.django.cors-allow-all
3
+ languages:
4
+ - python
5
+ severity: WARNING
6
+ message: |
7
+ django-cors-headers is configured to allow every origin, disabling
8
+ cross-origin access control.
9
+
10
+ `CORS_ALLOW_ALL_ORIGINS = True` (or the legacy `CORS_ORIGIN_ALLOW_ALL =
11
+ True`) reflects any site's `Origin`, so ANY website can make cross-origin
12
+ requests to your API; combined with credentialed sessions this leaks
13
+ cookies, tokens and CSRF protections cross-origin (CWE-942, OWASP
14
+ A05:2021). Set it to `False` and list trusted origins explicitly, e.g.
15
+ `CORS_ALLOWED_ORIGINS = ["https://app.example.com"]`.
16
+ # Matches ONLY the literal `True` on the django-cors-headers settings keys.
17
+ # `= False` and an explicit `CORS_ALLOWED_ORIGINS = [...]` allow-list are
18
+ # never flagged. Distinct from `auth.py.cors.allow-all`, which targets the
19
+ # Flask-CORS `CORS(...)` / `@cross_origin(...)` call forms.
20
+ pattern-either:
21
+ - pattern: CORS_ALLOW_ALL_ORIGINS = True
22
+ - pattern: CORS_ORIGIN_ALLOW_ALL = True
23
+ metadata:
24
+ oauthlint-rule-id: AUTH-PY-DJANGO-001
25
+ oauthlint-doc-url: https://oauthlint.dev/rules/py-django-cors-allow-all
26
+ category: security
27
+ cwe: CWE-942
28
+ owasp: A05:2021
29
+ llm-prevalence: MEDIUM
30
+ technology:
31
+ - django-cors-headers
32
+ references:
33
+ - https://github.com/adamchainz/django-cors-headers#cors_allow_all_origins-bool
34
+ - https://cwe.mitre.org/data/definitions/942.html
@@ -0,0 +1,32 @@
1
+ rules:
2
+ - id: auth.py.drf.default-authentication-empty
3
+ languages:
4
+ - python
5
+ severity: ERROR
6
+ message: |
7
+ DRF disables authentication globally with an empty
8
+ `DEFAULT_AUTHENTICATION_CLASSES` list.
9
+
10
+ An empty list means no authentication scheme runs, so `request.user` is
11
+ never populated from a credential and every view falls back to anonymous
12
+ access (CWE-306, OWASP A01:2021). Permission checks that rely on
13
+ `request.user` being authenticated then have nothing to enforce against.
14
+
15
+ Populate the list with the schemes you use, for example
16
+ `rest_framework.authentication.SessionAuthentication` and
17
+ `rest_framework.authentication.TokenAuthentication`.
18
+ # Scoped to the `REST_FRAMEWORK` settings dict; matches ONLY the empty list.
19
+ # A populated list such as `[SessionAuthentication]` is not matched.
20
+ pattern: 'REST_FRAMEWORK = {..., "DEFAULT_AUTHENTICATION_CLASSES": [], ...}'
21
+ metadata:
22
+ oauthlint-rule-id: AUTH-PY-DRF-002
23
+ oauthlint-doc-url: https://oauthlint.dev/rules/py-drf-default-authentication-empty
24
+ category: security
25
+ cwe: CWE-306
26
+ owasp: A01:2021
27
+ llm-prevalence: MEDIUM
28
+ technology:
29
+ - djangorestframework
30
+ references:
31
+ - https://www.django-rest-framework.org/api-guide/authentication/#setting-the-authentication-scheme
32
+ - https://cwe.mitre.org/data/definitions/306.html
@@ -0,0 +1,35 @@
1
+ rules:
2
+ - id: auth.py.drf.default-permission-allowany
3
+ languages:
4
+ - python
5
+ severity: ERROR
6
+ message: |
7
+ DRF makes every endpoint public because `DEFAULT_PERMISSION_CLASSES` is set
8
+ to `AllowAny`.
9
+
10
+ With `AllowAny` as the project-wide default, every view that does not
11
+ override `permission_classes` skips authorization entirely, so any
12
+ unauthenticated caller can reach it (CWE-862, OWASP A01:2021). This is easy
13
+ to ship by accident because it silently exposes future endpoints too.
14
+
15
+ Set the global default to a real permission such as
16
+ `rest_framework.permissions.IsAuthenticated` and opt specific views out to
17
+ public only when you mean to.
18
+ # Scoped to the `REST_FRAMEWORK` settings dict. Matches `AllowAny` both as the
19
+ # imported symbol and as the `'rest_framework.permissions.AllowAny'` string.
20
+ # `IsAuthenticated` (or any other class), or the key being absent, is not matched.
21
+ pattern-either:
22
+ - pattern: 'REST_FRAMEWORK = {..., "DEFAULT_PERMISSION_CLASSES": [..., AllowAny, ...], ...}'
23
+ - pattern: 'REST_FRAMEWORK = {..., "DEFAULT_PERMISSION_CLASSES": [..., "rest_framework.permissions.AllowAny", ...], ...}'
24
+ metadata:
25
+ oauthlint-rule-id: AUTH-PY-DRF-001
26
+ oauthlint-doc-url: https://oauthlint.dev/rules/py-drf-default-permission-allowany
27
+ category: security
28
+ cwe: CWE-862
29
+ owasp: A01:2021
30
+ llm-prevalence: HIGH
31
+ technology:
32
+ - djangorestframework
33
+ references:
34
+ - https://www.django-rest-framework.org/api-guide/permissions/#setting-the-permission-policy
35
+ - https://cwe.mitre.org/data/definitions/862.html
@@ -0,0 +1,34 @@
1
+ rules:
2
+ - id: auth.py.drf.view-authentication-disabled
3
+ languages:
4
+ - python
5
+ severity: ERROR
6
+ message: |
7
+ A DRF view disables authentication with an empty `authentication_classes`
8
+ list.
9
+
10
+ Setting `authentication_classes = []` on a view (or the
11
+ `@authentication_classes([])` decorator on a function view) turns off every
12
+ authentication scheme for that endpoint, so `request.user` is always
13
+ anonymous and any permission tied to an authenticated user cannot hold
14
+ (CWE-306, OWASP A01:2021).
15
+
16
+ List the schemes the view should accept, for example
17
+ `authentication_classes = [TokenAuthentication]`, instead of emptying it.
18
+ # Matches ONLY an explicitly emptied `authentication_classes`, as a class
19
+ # attribute or via the decorator. A populated list is not matched.
20
+ pattern-either:
21
+ - pattern: authentication_classes = []
22
+ - pattern: "@authentication_classes([])"
23
+ metadata:
24
+ oauthlint-rule-id: AUTH-PY-DRF-003
25
+ oauthlint-doc-url: https://oauthlint.dev/rules/py-drf-view-authentication-disabled
26
+ category: security
27
+ cwe: CWE-306
28
+ owasp: A01:2021
29
+ llm-prevalence: MEDIUM
30
+ technology:
31
+ - djangorestframework
32
+ references:
33
+ - https://www.django-rest-framework.org/api-guide/views/#api_view
34
+ - https://cwe.mitre.org/data/definitions/306.html
@@ -0,0 +1,42 @@
1
+ rules:
2
+ - id: auth.py.flask.session-cookie-insecure
3
+ languages:
4
+ - python
5
+ severity: ERROR
6
+ message: |
7
+ A Flask cookie security flag is disabled through `app.config`, weakening
8
+ session and remember-me cookie protection.
9
+
10
+ `SESSION_COOKIE_SECURE = False` lets the session cookie travel over plain
11
+ HTTP where it can be sniffed on the wire, and `SESSION_COOKIE_HTTPONLY =
12
+ False` exposes it to JavaScript so an XSS payload can read and exfiltrate
13
+ it; the `REMEMBER_COOKIE_*` flags do the same for Flask-Login's long-lived
14
+ remember-me token (CWE-614, OWASP A05:2021). Keep these `True` (or drive
15
+ them from an environment check), e.g. `app.config["SESSION_COOKIE_SECURE"]
16
+ = True` and `app.config["SESSION_COOKIE_HTTPONLY"] = True`.
17
+ # Matches ONLY the literal `False` set via `app.config[...] = False` (the
18
+ # subscript form) or `app.config.update(...=False)` (the keyword form) — the
19
+ # `app.config` variants that the bare module-level assignment rule
20
+ # `auth.py.cookie.insecure-flags` does NOT see. `= True` and env-driven
21
+ # values are never flagged. `$APP` matches any Flask app variable name.
22
+ pattern-either:
23
+ - pattern: $APP.config['SESSION_COOKIE_SECURE'] = False
24
+ - pattern: $APP.config['SESSION_COOKIE_HTTPONLY'] = False
25
+ - pattern: $APP.config['REMEMBER_COOKIE_SECURE'] = False
26
+ - pattern: $APP.config['REMEMBER_COOKIE_HTTPONLY'] = False
27
+ - pattern: $APP.config.update(..., SESSION_COOKIE_SECURE=False, ...)
28
+ - pattern: $APP.config.update(..., REMEMBER_COOKIE_SECURE=False, ...)
29
+ metadata:
30
+ oauthlint-rule-id: AUTH-PY-FLASK-001
31
+ oauthlint-doc-url: https://oauthlint.dev/rules/py-flask-session-cookie-insecure
32
+ category: security
33
+ cwe: CWE-614
34
+ owasp: A05:2021
35
+ llm-prevalence: MEDIUM
36
+ technology:
37
+ - flask
38
+ - flask-login
39
+ references:
40
+ - https://flask.palletsprojects.com/en/stable/config/#SESSION_COOKIE_SECURE
41
+ - https://flask-login.readthedocs.io/en/latest/#cookie-settings
42
+ - https://cwe.mitre.org/data/definitions/614.html
@@ -19,29 +19,41 @@ rules:
19
19
  # Scoped to `requests.<method>(...)`, `requests.request(...)` and Session
20
20
  # objects (`$SESSION.<method>(...)`). Fires only on the literal
21
21
  # `verify=False`; `verify=True` and `verify="/path/ca.pem"` are not flagged.
22
- pattern-either:
23
- - pattern: requests.get(..., verify=False, ...)
24
- - pattern: requests.post(..., verify=False, ...)
25
- - pattern: requests.put(..., verify=False, ...)
26
- - pattern: requests.delete(..., verify=False, ...)
27
- - pattern: requests.patch(..., verify=False, ...)
28
- - pattern: requests.head(..., verify=False, ...)
29
- - pattern: requests.options(..., verify=False, ...)
30
- - pattern: requests.request(..., verify=False, ...)
31
- - pattern: $SESSION.get(..., verify=False, ...)
32
- - pattern: $SESSION.post(..., verify=False, ...)
33
- - pattern: $SESSION.put(..., verify=False, ...)
34
- - pattern: $SESSION.delete(..., verify=False, ...)
35
- - pattern: $SESSION.patch(..., verify=False, ...)
36
- - pattern: $SESSION.head(..., verify=False, ...)
37
- - pattern: $SESSION.options(..., verify=False, ...)
38
- - pattern: $SESSION.request(..., verify=False, ...)
22
+ patterns:
23
+ - pattern-either:
24
+ - pattern: requests.get(..., verify=$V, ...)
25
+ - pattern: requests.post(..., verify=$V, ...)
26
+ - pattern: requests.put(..., verify=$V, ...)
27
+ - pattern: requests.delete(..., verify=$V, ...)
28
+ - pattern: requests.patch(..., verify=$V, ...)
29
+ - pattern: requests.head(..., verify=$V, ...)
30
+ - pattern: requests.options(..., verify=$V, ...)
31
+ - pattern: requests.request(..., verify=$V, ...)
32
+ - pattern: $SESSION.get(..., verify=$V, ...)
33
+ - pattern: $SESSION.post(..., verify=$V, ...)
34
+ - pattern: $SESSION.put(..., verify=$V, ...)
35
+ - pattern: $SESSION.delete(..., verify=$V, ...)
36
+ - pattern: $SESSION.patch(..., verify=$V, ...)
37
+ - pattern: $SESSION.head(..., verify=$V, ...)
38
+ - pattern: $SESSION.options(..., verify=$V, ...)
39
+ - pattern: $SESSION.request(..., verify=$V, ...)
40
+ # Fire only on the literal `False` (unchanged detection), and focus the
41
+ # match/fix on that value token so the autofix flips just it, leaving the
42
+ # rest of the call intact.
43
+ - metavariable-regex:
44
+ metavariable: $V
45
+ regex: ^False$
46
+ - focus-metavariable: $V
47
+ # Safe, deterministic autofix: `True` is the library default (verification
48
+ # on) and the exact value the rule treats as compliant, so it fully resolves
49
+ # the finding. Only the value token is rewritten (`verify=False` -> `verify=True`).
50
+ fix: "True"
39
51
  metadata:
40
52
  oauthlint-rule-id: AUTH-PY-FLOW-002
41
53
  oauthlint-doc-url: https://oauthlint.dev/rules/py-flow-requests-verify-disabled
42
54
  category: security
43
55
  cwe: CWE-295
44
- owasp: API8:2023
56
+ owasp: A02:2021
45
57
  llm-prevalence: HIGH
46
58
  technology:
47
59
  - requests
@@ -0,0 +1,45 @@
1
+ rules:
2
+ - id: auth.py.jwt.verify-claims-disabled
3
+ languages:
4
+ - python
5
+ severity: WARNING
6
+ message: |
7
+ PyJWT decode disables audience or issuer checks.
8
+
9
+ `jwt.decode(...)` is called with an `options` dict that turns off a claim
10
+ check: `"verify_aud": False`, `"verify_iss": False`, or
11
+ `"verify_nbf": False`. Skipping these lets a token minted for a different
12
+ audience or issuer (for example one from another tenant or a lower-trust
13
+ service) be accepted here, defeating the boundary those claims are meant
14
+ to enforce (CWE-347).
15
+
16
+ Remove the disabling option and validate the claim, e.g.
17
+ `jwt.decode(token, key, algorithms=["RS256"], audience="api",
18
+ issuer="https://issuer.example.com")`. PyJWT only checks `aud`/`iss` when
19
+ you pass the expected value, so supply it rather than disabling the check.
20
+ # Scoped to PyJWT's decode `options` dict. We match ONLY the aud/iss/nbf
21
+ # keys; `verify_signature` is reported by auth.py.jwt.no-verify and
22
+ # `verify_exp` by auth.py.jwt.no-expiration, so neither is matched here and
23
+ # we avoid duplicate findings.
24
+ patterns:
25
+ - pattern-either:
26
+ - pattern: jwt.decode(..., options=$OPTS, ...)
27
+ - pattern: decode(..., options=$OPTS, ...)
28
+ - metavariable-pattern:
29
+ metavariable: $OPTS
30
+ pattern-either:
31
+ - pattern: '{..., "verify_aud": False, ...}'
32
+ - pattern: '{..., "verify_iss": False, ...}'
33
+ - pattern: '{..., "verify_nbf": False, ...}'
34
+ metadata:
35
+ oauthlint-rule-id: AUTH-PY-JWT-008
36
+ oauthlint-doc-url: https://oauthlint.dev/rules/py-jwt-verify-claims-disabled
37
+ category: security
38
+ cwe: CWE-347
39
+ owasp: API2:2023
40
+ llm-prevalence: MEDIUM
41
+ technology:
42
+ - pyjwt
43
+ references:
44
+ - https://pyjwt.readthedocs.io/en/stable/api.html#jwt.decode
45
+ - https://cwe.mitre.org/data/definitions/347.html
@@ -21,10 +21,20 @@ rules:
21
21
  # `verify="/path/ca.pem"` are not flagged. This is distinct from
22
22
  # auth.py.flow.requests-verify-disabled, which covers the `requests` HTTP
23
23
  # verbs (`get`/`post`/…); here the sink is the OAuth token-exchange call.
24
- pattern-either:
25
- - pattern: $C.fetch_token(..., verify=False, ...)
26
- - pattern: $C.refresh_token(..., verify=False, ...)
27
- - pattern: $C.fetch_access_token(..., verify=False, ...)
24
+ patterns:
25
+ - pattern-either:
26
+ - pattern: $C.fetch_token(..., verify=$V, ...)
27
+ - pattern: $C.refresh_token(..., verify=$V, ...)
28
+ - pattern: $C.fetch_access_token(..., verify=$V, ...)
29
+ # Fire only on the literal `False` (unchanged detection), and focus the
30
+ # match/fix on that value token so the autofix flips just it.
31
+ - metavariable-regex:
32
+ metavariable: $V
33
+ regex: ^False$
34
+ - focus-metavariable: $V
35
+ # Safe, deterministic autofix: `True` is the default (verification on) and the
36
+ # exact value the rule treats as compliant, so it resolves the finding.
37
+ fix: "True"
28
38
  metadata:
29
39
  oauthlint-rule-id: AUTH-PY-OAUTH-005
30
40
  oauthlint-doc-url: https://oauthlint.dev/rules/py-oauth-token-request-verify-disabled
@@ -26,7 +26,7 @@ rules:
26
26
  oauthlint-doc-url: https://oauthlint.dev/rules/rust-cookie-insecure
27
27
  category: security
28
28
  cwe: CWE-614
29
- owasp: A05:2021
29
+ owasp: API8:2023
30
30
  llm-prevalence: HIGH
31
31
  technology:
32
32
  - cookie
@@ -27,7 +27,7 @@ rules:
27
27
  oauthlint-doc-url: https://oauthlint.dev/rules/rust-cors-permissive
28
28
  category: security
29
29
  cwe: CWE-942
30
- owasp: A05:2021
30
+ owasp: API8:2023
31
31
  llm-prevalence: MEDIUM
32
32
  technology:
33
33
  - actix-web
@@ -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
@@ -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