oauthlint-rules 0.1.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/LICENSE +21 -0
  2. package/README.md +96 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +3 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/loader.d.ts +35 -0
  8. package/dist/loader.d.ts.map +1 -0
  9. package/dist/loader.js +72 -0
  10. package/dist/loader.js.map +1 -0
  11. package/dist/manifest.d.ts +10 -0
  12. package/dist/manifest.d.ts.map +1 -0
  13. package/dist/manifest.js +10 -0
  14. package/dist/manifest.js.map +1 -0
  15. package/dist/schema.d.ts +425 -0
  16. package/dist/schema.d.ts.map +1 -0
  17. package/dist/schema.js +71 -0
  18. package/dist/schema.js.map +1 -0
  19. package/package.json +61 -0
  20. package/rules/cookie/long-lived.yml +42 -0
  21. package/rules/cookie/no-httponly.yml +54 -0
  22. package/rules/cookie/no-samesite.yml +56 -0
  23. package/rules/cookie/no-secure.yml +58 -0
  24. package/rules/cors/wildcard-with-credentials.yml +56 -0
  25. package/rules/flow/insecure-random.yml +56 -0
  26. package/rules/flow/no-rate-limit.yml +39 -0
  27. package/rules/flow/password-min-length.yml +44 -0
  28. package/rules/flow/password-plaintext.yml +82 -0
  29. package/rules/flow/timing-unsafe-compare.yml +103 -0
  30. package/rules/jwt/alg-none.yml +46 -0
  31. package/rules/jwt/algorithm-confusion.yml +67 -0
  32. package/rules/jwt/in-url.yml +33 -0
  33. package/rules/jwt/localstorage.yml +39 -0
  34. package/rules/jwt/no-audience.yml +49 -0
  35. package/rules/jwt/no-expiration.yml +45 -0
  36. package/rules/jwt/no-issuer.yml +40 -0
  37. package/rules/jwt/weak-secret.yml +56 -0
  38. package/rules/oauth/broad-scope.yml +39 -0
  39. package/rules/oauth/hardcoded-secret.yml +41 -0
  40. package/rules/oauth/implicit-flow.yml +36 -0
  41. package/rules/oauth/long-token-lifetime.yml +57 -0
  42. package/rules/oauth/no-pkce.yml +50 -0
  43. package/rules/oauth/no-state-validation.yml +42 -0
  44. package/rules/oauth/no-state.yml +41 -0
  45. package/rules/oauth/open-redirect-callback.yml +47 -0
  46. package/rules/oauth/wildcard-redirect.yml +45 -0
  47. package/rules/secret/provider-key.yml +44 -0
  48. package/rules/session/id-in-url.yml +30 -0
  49. package/rules/session/no-regeneration.yml +53 -0
@@ -0,0 +1,44 @@
1
+ rules:
2
+ - id: auth.secret.provider-key
3
+ languages:
4
+ - javascript
5
+ - typescript
6
+ severity: ERROR
7
+ message: |
8
+ A hard-coded credential matching a well-known provider's key format
9
+ was found in the source. These keys are designed to be revocable —
10
+ once one ships to git, the only safe action is to rotate it, even
11
+ if the repo is private.
12
+
13
+ Move the value to an environment variable, a secret manager (AWS
14
+ Secrets Manager, GCP Secret Manager, Doppler, 1Password CLI),
15
+ or a `.env` file that's `.gitignore`d.
16
+
17
+ Detected formats:
18
+ - Stripe live / test: sk_live_… / sk_test_… / pk_live_…
19
+ - OpenAI: sk-… / sk-proj-…
20
+ - Anthropic: sk-ant-…
21
+ - GitHub: ghp_… / gho_… / ghu_… / ghs_… / ghr_… / github_pat_…
22
+ - Google Workspace: GOCSPX-…
23
+ - Google API key: AIza…
24
+ - AWS Access Key: AKIA[0-9A-Z]{16}
25
+ - Slack Bot / User: xoxb-… / xoxp-…
26
+ pattern-either:
27
+ - pattern-regex: \b(?:sk|pk|rk)_(?:live|test)_[0-9a-zA-Z]{16,}
28
+ - pattern-regex: \bsk-(?:ant-|proj-)?[A-Za-z0-9_-]{20,}
29
+ - pattern-regex: \bgh[opusr]_[A-Za-z0-9]{36,}
30
+ - pattern-regex: \bgithub_pat_[A-Za-z0-9_]{40,}
31
+ - pattern-regex: \bGOCSPX-[A-Za-z0-9_-]{20,}
32
+ - pattern-regex: \bAKIA[0-9A-Z]{16}\b
33
+ - pattern-regex: \bAIza[0-9A-Za-z_-]{35}\b
34
+ - pattern-regex: \bxox[bp]-[0-9]{10,}-[0-9]{10,}-[A-Za-z0-9]{20,}
35
+ metadata:
36
+ oauthlint-rule-id: AUTH-SECRET-001
37
+ oauthlint-doc-url: https://oauthlint.dev/rules/secret-provider-key
38
+ category: security
39
+ cwe: CWE-798
40
+ owasp: API8:2023
41
+ llm-prevalence: HIGH
42
+ references:
43
+ - https://blog.gitguardian.com/the-state-of-secrets-sprawl-2026/
44
+ - https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/
@@ -0,0 +1,30 @@
1
+ rules:
2
+ - id: auth.session.id-in-url
3
+ languages:
4
+ - javascript
5
+ - typescript
6
+ severity: ERROR
7
+ message: |
8
+ A session token / id appears in a URL query string. URLs are
9
+ logged everywhere (web server logs, reverse proxies, browser
10
+ history, referrer headers leaking to third-party CDNs and ad
11
+ networks), so this leaks the credential.
12
+
13
+ Pass session ids/tokens in the `Authorization` header or in a
14
+ `Secure; HttpOnly` cookie. Never in the URL.
15
+
16
+ OWASP ASVS V3.2 explicitly bans this pattern.
17
+ pattern-either:
18
+ - pattern-regex: |-
19
+ [?&](?:session|sid|sess|auth_token|access_token|refresh_token|token|api[_-]?key|jwt|bearer)=
20
+ - pattern-regex: |-
21
+ \?\s*['"]?(?:session|sid|sess|auth_token|access_token|refresh_token|token|api[_-]?key|jwt|bearer)['"]?\s*:
22
+ metadata:
23
+ oauthlint-rule-id: AUTH-SESSION-001
24
+ oauthlint-doc-url: https://oauthlint.dev/rules/session-id-in-url
25
+ category: security
26
+ cwe: CWE-598
27
+ owasp: API1:2023
28
+ llm-prevalence: MEDIUM
29
+ references:
30
+ - https://owasp.org/www-project-application-security-verification-standard/
@@ -0,0 +1,53 @@
1
+ rules:
2
+ - id: auth.session.no-regeneration
3
+ languages:
4
+ - javascript
5
+ - typescript
6
+ severity: WARNING
7
+ message: |
8
+ The user is being marked as logged in (`req.session.user = ...`,
9
+ `req.session.userId = ...`, etc.) WITHOUT first regenerating the
10
+ session id. This opens the door to session-fixation attacks: an
11
+ attacker who plants a known session id in the victim's browser
12
+ before login retains access after authentication succeeds.
13
+
14
+ Call `req.session.regenerate(cb)` (or your framework's equivalent)
15
+ between authenticating the credentials and writing the user
16
+ identity onto the session.
17
+
18
+ OWASP ASVS V3.2.1: "The session id must be regenerated on
19
+ authentication".
20
+ patterns:
21
+ - pattern-either:
22
+ - pattern: '$REQ.session.user = $X'
23
+ - pattern: '$REQ.session.userId = $X'
24
+ - pattern: '$REQ.session.user_id = $X'
25
+ - pattern: '$REQ.session.uid = $X'
26
+ - pattern: '$REQ.session.authenticated = true'
27
+ - pattern: '$REQ.session.isAuthenticated = true'
28
+ # Callback form: assignment inside regenerate's callback.
29
+ - pattern-not-inside: |
30
+ $REQ.session.regenerate(...)
31
+ # Promisified async form: `await new Promise(r => req.session.regenerate(...))`
32
+ # immediately before the assignment. Scoped to regenerate so it does NOT
33
+ # suppress assignments that merely follow some unrelated await.
34
+ - pattern-not-inside: |
35
+ await new Promise(($R) => $REQ.session.regenerate(...));
36
+ ...
37
+ - pattern-not-inside: |
38
+ await new Promise(($R, $J) => $REQ.session.regenerate(...));
39
+ ...
40
+ - pattern-not-inside: |
41
+ await promisify($REQ.session.regenerate)(...);
42
+ ...
43
+ metadata:
44
+ oauthlint-rule-id: AUTH-SESSION-002
45
+ oauthlint-doc-url: https://oauthlint.dev/rules/session-no-regeneration
46
+ category: security
47
+ cwe: CWE-384
48
+ owasp: API2:2023
49
+ llm-prevalence: MEDIUM
50
+ technology:
51
+ - express
52
+ references:
53
+ - https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html#renew-the-session-id-after-any-privilege-level-change