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.
- package/LICENSE +21 -0
- package/README.md +96 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/loader.d.ts +35 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +72 -0
- package/dist/loader.js.map +1 -0
- package/dist/manifest.d.ts +10 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +10 -0
- package/dist/manifest.js.map +1 -0
- package/dist/schema.d.ts +425 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +71 -0
- package/dist/schema.js.map +1 -0
- package/package.json +61 -0
- package/rules/cookie/long-lived.yml +42 -0
- package/rules/cookie/no-httponly.yml +54 -0
- package/rules/cookie/no-samesite.yml +56 -0
- package/rules/cookie/no-secure.yml +58 -0
- package/rules/cors/wildcard-with-credentials.yml +56 -0
- package/rules/flow/insecure-random.yml +56 -0
- package/rules/flow/no-rate-limit.yml +39 -0
- package/rules/flow/password-min-length.yml +44 -0
- package/rules/flow/password-plaintext.yml +82 -0
- package/rules/flow/timing-unsafe-compare.yml +103 -0
- package/rules/jwt/alg-none.yml +46 -0
- package/rules/jwt/algorithm-confusion.yml +67 -0
- package/rules/jwt/in-url.yml +33 -0
- package/rules/jwt/localstorage.yml +39 -0
- package/rules/jwt/no-audience.yml +49 -0
- package/rules/jwt/no-expiration.yml +45 -0
- package/rules/jwt/no-issuer.yml +40 -0
- package/rules/jwt/weak-secret.yml +56 -0
- package/rules/oauth/broad-scope.yml +39 -0
- package/rules/oauth/hardcoded-secret.yml +41 -0
- package/rules/oauth/implicit-flow.yml +36 -0
- package/rules/oauth/long-token-lifetime.yml +57 -0
- package/rules/oauth/no-pkce.yml +50 -0
- package/rules/oauth/no-state-validation.yml +42 -0
- package/rules/oauth/no-state.yml +41 -0
- package/rules/oauth/open-redirect-callback.yml +47 -0
- package/rules/oauth/wildcard-redirect.yml +45 -0
- package/rules/secret/provider-key.yml +44 -0
- package/rules/session/id-in-url.yml +30 -0
- 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
|