oauthlint-rules 0.3.0 → 0.3.1
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/dist/schema.d.ts +60 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +12 -0
- package/dist/schema.js.map +1 -1
- package/package.json +1 -1
- package/rules/cookie/samesite-none-insecure.yml +22 -0
- package/rules/flow/open-redirect.yml +11 -0
- package/rules/flow/ssrf.yml +19 -0
- package/rules/flow/timing-unsafe-compare.yml +19 -0
- package/rules/go/oauth/ropc-grant.yml +15 -0
- package/rules/oauth/ropc-grant.yml +8 -3
- package/rules/py/oauth/ropc-grant.yml +12 -4
- package/rules/rust/oauth/ropc-grant.yml +17 -0
- package/rules/rust/oauth/static-state.yml +25 -5
package/dist/schema.d.ts
CHANGED
|
@@ -81,6 +81,16 @@ export declare const RuleSchema: z.ZodEffects<z.ZodObject<{
|
|
|
81
81
|
'pattern-either-regex': z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
82
82
|
patterns: z.ZodOptional<z.ZodArray<z.ZodType<unknown, z.ZodTypeDef, unknown>, "many">>;
|
|
83
83
|
fix: z.ZodOptional<z.ZodString>;
|
|
84
|
+
paths: z.ZodOptional<z.ZodObject<{
|
|
85
|
+
include: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
86
|
+
exclude: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
87
|
+
}, "strip", z.ZodTypeAny, {
|
|
88
|
+
include?: string[] | undefined;
|
|
89
|
+
exclude?: string[] | undefined;
|
|
90
|
+
}, {
|
|
91
|
+
include?: string[] | undefined;
|
|
92
|
+
exclude?: string[] | undefined;
|
|
93
|
+
}>>;
|
|
84
94
|
mode: z.ZodOptional<z.ZodEnum<["search", "taint"]>>;
|
|
85
95
|
'pattern-sources': z.ZodOptional<z.ZodArray<z.ZodType<unknown, z.ZodTypeDef, unknown>, "many">>;
|
|
86
96
|
'pattern-sinks': z.ZodOptional<z.ZodArray<z.ZodType<unknown, z.ZodTypeDef, unknown>, "many">>;
|
|
@@ -109,6 +119,10 @@ export declare const RuleSchema: z.ZodEffects<z.ZodObject<{
|
|
|
109
119
|
'pattern-either-regex'?: string[] | undefined;
|
|
110
120
|
patterns?: unknown[] | undefined;
|
|
111
121
|
fix?: string | undefined;
|
|
122
|
+
paths?: {
|
|
123
|
+
include?: string[] | undefined;
|
|
124
|
+
exclude?: string[] | undefined;
|
|
125
|
+
} | undefined;
|
|
112
126
|
mode?: "search" | "taint" | undefined;
|
|
113
127
|
'pattern-sources'?: unknown[] | undefined;
|
|
114
128
|
'pattern-sinks'?: unknown[] | undefined;
|
|
@@ -137,6 +151,10 @@ export declare const RuleSchema: z.ZodEffects<z.ZodObject<{
|
|
|
137
151
|
'pattern-either-regex'?: string[] | undefined;
|
|
138
152
|
patterns?: unknown[] | undefined;
|
|
139
153
|
fix?: string | undefined;
|
|
154
|
+
paths?: {
|
|
155
|
+
include?: string[] | undefined;
|
|
156
|
+
exclude?: string[] | undefined;
|
|
157
|
+
} | undefined;
|
|
140
158
|
mode?: "search" | "taint" | undefined;
|
|
141
159
|
'pattern-sources'?: unknown[] | undefined;
|
|
142
160
|
'pattern-sinks'?: unknown[] | undefined;
|
|
@@ -165,6 +183,10 @@ export declare const RuleSchema: z.ZodEffects<z.ZodObject<{
|
|
|
165
183
|
'pattern-either-regex'?: string[] | undefined;
|
|
166
184
|
patterns?: unknown[] | undefined;
|
|
167
185
|
fix?: string | undefined;
|
|
186
|
+
paths?: {
|
|
187
|
+
include?: string[] | undefined;
|
|
188
|
+
exclude?: string[] | undefined;
|
|
189
|
+
} | undefined;
|
|
168
190
|
mode?: "search" | "taint" | undefined;
|
|
169
191
|
'pattern-sources'?: unknown[] | undefined;
|
|
170
192
|
'pattern-sinks'?: unknown[] | undefined;
|
|
@@ -193,6 +215,10 @@ export declare const RuleSchema: z.ZodEffects<z.ZodObject<{
|
|
|
193
215
|
'pattern-either-regex'?: string[] | undefined;
|
|
194
216
|
patterns?: unknown[] | undefined;
|
|
195
217
|
fix?: string | undefined;
|
|
218
|
+
paths?: {
|
|
219
|
+
include?: string[] | undefined;
|
|
220
|
+
exclude?: string[] | undefined;
|
|
221
|
+
} | undefined;
|
|
196
222
|
mode?: "search" | "taint" | undefined;
|
|
197
223
|
'pattern-sources'?: unknown[] | undefined;
|
|
198
224
|
'pattern-sinks'?: unknown[] | undefined;
|
|
@@ -242,6 +268,16 @@ export declare const RuleFileSchema: z.ZodObject<{
|
|
|
242
268
|
'pattern-either-regex': z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
243
269
|
patterns: z.ZodOptional<z.ZodArray<z.ZodType<unknown, z.ZodTypeDef, unknown>, "many">>;
|
|
244
270
|
fix: z.ZodOptional<z.ZodString>;
|
|
271
|
+
paths: z.ZodOptional<z.ZodObject<{
|
|
272
|
+
include: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
273
|
+
exclude: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
274
|
+
}, "strip", z.ZodTypeAny, {
|
|
275
|
+
include?: string[] | undefined;
|
|
276
|
+
exclude?: string[] | undefined;
|
|
277
|
+
}, {
|
|
278
|
+
include?: string[] | undefined;
|
|
279
|
+
exclude?: string[] | undefined;
|
|
280
|
+
}>>;
|
|
245
281
|
mode: z.ZodOptional<z.ZodEnum<["search", "taint"]>>;
|
|
246
282
|
'pattern-sources': z.ZodOptional<z.ZodArray<z.ZodType<unknown, z.ZodTypeDef, unknown>, "many">>;
|
|
247
283
|
'pattern-sinks': z.ZodOptional<z.ZodArray<z.ZodType<unknown, z.ZodTypeDef, unknown>, "many">>;
|
|
@@ -270,6 +306,10 @@ export declare const RuleFileSchema: z.ZodObject<{
|
|
|
270
306
|
'pattern-either-regex'?: string[] | undefined;
|
|
271
307
|
patterns?: unknown[] | undefined;
|
|
272
308
|
fix?: string | undefined;
|
|
309
|
+
paths?: {
|
|
310
|
+
include?: string[] | undefined;
|
|
311
|
+
exclude?: string[] | undefined;
|
|
312
|
+
} | undefined;
|
|
273
313
|
mode?: "search" | "taint" | undefined;
|
|
274
314
|
'pattern-sources'?: unknown[] | undefined;
|
|
275
315
|
'pattern-sinks'?: unknown[] | undefined;
|
|
@@ -298,6 +338,10 @@ export declare const RuleFileSchema: z.ZodObject<{
|
|
|
298
338
|
'pattern-either-regex'?: string[] | undefined;
|
|
299
339
|
patterns?: unknown[] | undefined;
|
|
300
340
|
fix?: string | undefined;
|
|
341
|
+
paths?: {
|
|
342
|
+
include?: string[] | undefined;
|
|
343
|
+
exclude?: string[] | undefined;
|
|
344
|
+
} | undefined;
|
|
301
345
|
mode?: "search" | "taint" | undefined;
|
|
302
346
|
'pattern-sources'?: unknown[] | undefined;
|
|
303
347
|
'pattern-sinks'?: unknown[] | undefined;
|
|
@@ -326,6 +370,10 @@ export declare const RuleFileSchema: z.ZodObject<{
|
|
|
326
370
|
'pattern-either-regex'?: string[] | undefined;
|
|
327
371
|
patterns?: unknown[] | undefined;
|
|
328
372
|
fix?: string | undefined;
|
|
373
|
+
paths?: {
|
|
374
|
+
include?: string[] | undefined;
|
|
375
|
+
exclude?: string[] | undefined;
|
|
376
|
+
} | undefined;
|
|
329
377
|
mode?: "search" | "taint" | undefined;
|
|
330
378
|
'pattern-sources'?: unknown[] | undefined;
|
|
331
379
|
'pattern-sinks'?: unknown[] | undefined;
|
|
@@ -354,6 +402,10 @@ export declare const RuleFileSchema: z.ZodObject<{
|
|
|
354
402
|
'pattern-either-regex'?: string[] | undefined;
|
|
355
403
|
patterns?: unknown[] | undefined;
|
|
356
404
|
fix?: string | undefined;
|
|
405
|
+
paths?: {
|
|
406
|
+
include?: string[] | undefined;
|
|
407
|
+
exclude?: string[] | undefined;
|
|
408
|
+
} | undefined;
|
|
357
409
|
mode?: "search" | "taint" | undefined;
|
|
358
410
|
'pattern-sources'?: unknown[] | undefined;
|
|
359
411
|
'pattern-sinks'?: unknown[] | undefined;
|
|
@@ -384,6 +436,10 @@ export declare const RuleFileSchema: z.ZodObject<{
|
|
|
384
436
|
'pattern-either-regex'?: string[] | undefined;
|
|
385
437
|
patterns?: unknown[] | undefined;
|
|
386
438
|
fix?: string | undefined;
|
|
439
|
+
paths?: {
|
|
440
|
+
include?: string[] | undefined;
|
|
441
|
+
exclude?: string[] | undefined;
|
|
442
|
+
} | undefined;
|
|
387
443
|
mode?: "search" | "taint" | undefined;
|
|
388
444
|
'pattern-sources'?: unknown[] | undefined;
|
|
389
445
|
'pattern-sinks'?: unknown[] | undefined;
|
|
@@ -414,6 +470,10 @@ export declare const RuleFileSchema: z.ZodObject<{
|
|
|
414
470
|
'pattern-either-regex'?: string[] | undefined;
|
|
415
471
|
patterns?: unknown[] | undefined;
|
|
416
472
|
fix?: string | undefined;
|
|
473
|
+
paths?: {
|
|
474
|
+
include?: string[] | undefined;
|
|
475
|
+
exclude?: string[] | undefined;
|
|
476
|
+
} | undefined;
|
|
417
477
|
mode?: "search" | "taint" | undefined;
|
|
418
478
|
'pattern-sources'?: unknown[] | undefined;
|
|
419
479
|
'pattern-sinks'?: unknown[] | undefined;
|
package/dist/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,cAAc,yCAAuC,CAAC;AACnE,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiBlC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,cAAc,yCAAuC,CAAC;AACnE,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiBlC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAqBxE,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8CpB,CAAC;AAEJ,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAE9C,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEzB,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC"}
|
package/dist/schema.js
CHANGED
|
@@ -32,6 +32,16 @@ export const OAuthLintMetadataSchema = z.object({
|
|
|
32
32
|
* Semgrep accepts many shapes; we only validate the fields we rely on.
|
|
33
33
|
*/
|
|
34
34
|
const PatternEntrySchema = z.lazy(() => z.union([z.string(), z.record(z.string(), z.unknown()), z.array(PatternEntrySchema)]));
|
|
35
|
+
/**
|
|
36
|
+
* Semgrep `paths:` filter. Lets a rule scope itself to (or away from) files by
|
|
37
|
+
* glob. We use `exclude` to keep production-grant rules from firing on test,
|
|
38
|
+
* example, vendored, or generated code — locations that should never carry a
|
|
39
|
+
* real application's OAuth misuse. Passed straight through to Semgrep.
|
|
40
|
+
*/
|
|
41
|
+
const PathsSchema = z.object({
|
|
42
|
+
include: z.array(z.string()).optional(),
|
|
43
|
+
exclude: z.array(z.string()).optional(),
|
|
44
|
+
});
|
|
35
45
|
export const RuleSchema = z
|
|
36
46
|
.object({
|
|
37
47
|
// auth.<category>.<name> for the JS/TS pack; language packs prepend a
|
|
@@ -53,6 +63,8 @@ export const RuleSchema = z
|
|
|
53
63
|
'pattern-either-regex': z.array(z.string()).optional(),
|
|
54
64
|
patterns: z.array(PatternEntrySchema).optional(),
|
|
55
65
|
fix: z.string().optional(),
|
|
66
|
+
// Scope a rule to/away from files by glob (passed through to Semgrep).
|
|
67
|
+
paths: PathsSchema.optional(),
|
|
56
68
|
// Taint-mode rules (Semgrep dataflow).
|
|
57
69
|
mode: z.enum(['search', 'taint']).optional(),
|
|
58
70
|
'pattern-sources': z.array(PatternEntrySchema).optional(),
|
package/dist/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -4,6 +4,28 @@ rules:
|
|
|
4
4
|
- javascript
|
|
5
5
|
- typescript
|
|
6
6
|
severity: WARNING
|
|
7
|
+
# Non-production code (example apps, demos, docs, vendored copies, tests)
|
|
8
|
+
# is not the library surface users ship, so findings there are noise for a
|
|
9
|
+
# low-FP linter. In particular this skips vendored third-party cookie
|
|
10
|
+
# serializers (e.g. packages/core/src/lib/vendored/cookie.ts) whose
|
|
11
|
+
# incremental `"; SameSite=None"` attribute fragment is not a complete
|
|
12
|
+
# insecure cookie. Globs intentionally omit `**/tests/**` / `**/fixtures/**`
|
|
13
|
+
# so the rule still fires on its own fixtures under rules/tests/fixtures/.
|
|
14
|
+
paths:
|
|
15
|
+
exclude:
|
|
16
|
+
- "**/test/**"
|
|
17
|
+
- "**/__tests__/**"
|
|
18
|
+
- "**/*.test.*"
|
|
19
|
+
- "**/*.spec.*"
|
|
20
|
+
- "**/example/**"
|
|
21
|
+
- "**/examples/**"
|
|
22
|
+
- "**/apps/**"
|
|
23
|
+
- "**/docs/**"
|
|
24
|
+
- "**/__mocks__/**"
|
|
25
|
+
- "**/mocks/**"
|
|
26
|
+
- "**/vendored/**"
|
|
27
|
+
- "**/node_modules/**"
|
|
28
|
+
- "**/*.stories.*"
|
|
7
29
|
message: |
|
|
8
30
|
A cookie is being set with `SameSite=None` but WITHOUT `Secure`.
|
|
9
31
|
`SameSite=None` *requires* `Secure`: modern browsers reject a
|
|
@@ -61,6 +61,17 @@ rules:
|
|
|
61
61
|
- pattern: "$RES.setHeader('Location', $SINK)"
|
|
62
62
|
- pattern: '$RES.setHeader("Location", $SINK)'
|
|
63
63
|
- pattern: "$RES.writeHead($S, {..., Location: $SINK, ...})"
|
|
64
|
+
# `$RES.redirect(...)` / `$RES.location(...)` also match a bare,
|
|
65
|
+
# receiver-less `redirect(...)` / `location(...)` call. Those are the
|
|
66
|
+
# framework navigation primitives exported by Next.js
|
|
67
|
+
# (`next/navigation`), SvelteKit and Remix — they send the user to a
|
|
68
|
+
# server-constructed application URL, not the Express `res.redirect`
|
|
69
|
+
# open-redirect sink this rule targets. Requiring an explicit receiver
|
|
70
|
+
# removes that over-match (the dominant FP class seen on next-auth)
|
|
71
|
+
# without affecting any `res.redirect` / `res.location` detection.
|
|
72
|
+
- pattern-not: redirect($SINK)
|
|
73
|
+
- pattern-not: redirect($CODE, $SINK)
|
|
74
|
+
- pattern-not: location($SINK)
|
|
64
75
|
- focus-metavariable: $SINK
|
|
65
76
|
metadata:
|
|
66
77
|
oauthlint-rule-id: AUTH-FLOW-010
|
package/rules/flow/ssrf.yml
CHANGED
|
@@ -4,6 +4,25 @@ rules:
|
|
|
4
4
|
- javascript
|
|
5
5
|
- typescript
|
|
6
6
|
severity: ERROR
|
|
7
|
+
# Non-production code (example apps, demos, docs, vendored copies, tests)
|
|
8
|
+
# is not the library surface users ship, so findings there are noise for a
|
|
9
|
+
# low-FP linter. Globs intentionally omit `**/tests/**` / `**/fixtures/**`
|
|
10
|
+
# so the rule still fires on its own fixtures under rules/tests/fixtures/.
|
|
11
|
+
paths:
|
|
12
|
+
exclude:
|
|
13
|
+
- "**/test/**"
|
|
14
|
+
- "**/__tests__/**"
|
|
15
|
+
- "**/*.test.*"
|
|
16
|
+
- "**/*.spec.*"
|
|
17
|
+
- "**/example/**"
|
|
18
|
+
- "**/examples/**"
|
|
19
|
+
- "**/apps/**"
|
|
20
|
+
- "**/docs/**"
|
|
21
|
+
- "**/__mocks__/**"
|
|
22
|
+
- "**/mocks/**"
|
|
23
|
+
- "**/vendored/**"
|
|
24
|
+
- "**/node_modules/**"
|
|
25
|
+
- "**/*.stories.*"
|
|
7
26
|
message: |
|
|
8
27
|
Untrusted request input flows into the URL of an outbound HTTP request.
|
|
9
28
|
Because the destination is attacker-controlled, this is a Server-Side
|
|
@@ -4,6 +4,25 @@ rules:
|
|
|
4
4
|
- javascript
|
|
5
5
|
- typescript
|
|
6
6
|
severity: WARNING
|
|
7
|
+
# Non-production code (example apps, demos, docs, vendored copies, tests)
|
|
8
|
+
# is not the library surface users ship, so findings there are noise for a
|
|
9
|
+
# low-FP linter. Globs intentionally omit `**/tests/**` / `**/fixtures/**`
|
|
10
|
+
# so the rule still fires on its own fixtures under rules/tests/fixtures/.
|
|
11
|
+
paths:
|
|
12
|
+
exclude:
|
|
13
|
+
- "**/test/**"
|
|
14
|
+
- "**/__tests__/**"
|
|
15
|
+
- "**/*.test.*"
|
|
16
|
+
- "**/*.spec.*"
|
|
17
|
+
- "**/example/**"
|
|
18
|
+
- "**/examples/**"
|
|
19
|
+
- "**/apps/**"
|
|
20
|
+
- "**/docs/**"
|
|
21
|
+
- "**/__mocks__/**"
|
|
22
|
+
- "**/mocks/**"
|
|
23
|
+
- "**/vendored/**"
|
|
24
|
+
- "**/node_modules/**"
|
|
25
|
+
- "**/*.stories.*"
|
|
7
26
|
message: |
|
|
8
27
|
A secret-shaped value (`password`, `token`, `secret`, `apiKey`,
|
|
9
28
|
`csrf`, `hmac`) is being compared with `===` / `!==` /
|
|
@@ -34,6 +34,21 @@ rules:
|
|
|
34
34
|
# value so only the password grant matches.
|
|
35
35
|
- pattern-regex: |-
|
|
36
36
|
[?&"`]grant_type=password(?:[&"`\s\\]|$)
|
|
37
|
+
# We flag an application sending ROPC, not the example/test code or vendored
|
|
38
|
+
# client libraries that legitimately implement the grant. Excluding these
|
|
39
|
+
# trees keeps the signal on first-party application code; a vendored copy of
|
|
40
|
+
# `golang.org/x/oauth2`, for instance, must not trip this rule.
|
|
41
|
+
paths:
|
|
42
|
+
exclude:
|
|
43
|
+
- "**/test/**"
|
|
44
|
+
- "**/*_test.go"
|
|
45
|
+
- "**/*_test.*"
|
|
46
|
+
- "**/example/**"
|
|
47
|
+
- "**/examples/**"
|
|
48
|
+
- "**/mock*/**"
|
|
49
|
+
- "**/testdata/**"
|
|
50
|
+
- "**/vendor/**"
|
|
51
|
+
- "**/node_modules/**"
|
|
37
52
|
metadata:
|
|
38
53
|
oauthlint-rule-id: AUTH-GO-OAUTH-001
|
|
39
54
|
oauthlint-doc-url: https://oauthlint.dev/rules/go-oauth-ropc-grant
|
|
@@ -16,10 +16,15 @@ rules:
|
|
|
16
16
|
(`grant_type=authorization_code`) for user login, or
|
|
17
17
|
`client_credentials` for machine-to-machine.
|
|
18
18
|
pattern-either:
|
|
19
|
-
# Object literal
|
|
20
|
-
#
|
|
19
|
+
# Object literal entry: `{ grant_type: 'password' }` (bare or quoted key).
|
|
20
|
+
# The colon anchors it to a property, not a bare variable assignment.
|
|
21
21
|
- pattern-regex: |-
|
|
22
|
-
grant_type\s
|
|
22
|
+
grant_type\s*:\s*['"]password['"]
|
|
23
|
+
# Property write that builds a request body: `body.grant_type = 'password'`.
|
|
24
|
+
# The leading `.` requires a member assignment, so a library's own bare
|
|
25
|
+
# local `grant_type = 'password'` (an internal constant) is NOT flagged.
|
|
26
|
+
- pattern-regex: |-
|
|
27
|
+
\.grant_type\s*=\s*['"]password['"]
|
|
23
28
|
# URL-encoded request body: "grant_type=password&username=…" (single,
|
|
24
29
|
# double, or template-literal string). The value is bounded so
|
|
25
30
|
# `grant_type=password_reset` and friends are not flagged.
|
|
@@ -21,12 +21,20 @@ rules:
|
|
|
21
21
|
# (dict / kwarg form) or bounded token (URL-encoded form), so
|
|
22
22
|
# `grant_type=password_reset` and `grant_type=client_credentials` never
|
|
23
23
|
# fire, and a dynamic `grant_type=grant` variable is not a literal and is
|
|
24
|
-
# not flagged.
|
|
24
|
+
# not flagged. Each form anchors `grant_type` to a request-parameter
|
|
25
|
+
# position (dict key, call keyword, query string, or pair) so a library's
|
|
26
|
+
# own bare local assignment — `grant_type = "password"`, as in Authlib's
|
|
27
|
+
# `_guess_grant_type` — is NOT treated as an application sending the grant.
|
|
25
28
|
pattern-either:
|
|
26
|
-
# Dict entry `"grant_type": "password"
|
|
27
|
-
#
|
|
29
|
+
# Dict / mapping entry: `{"grant_type": "password"}`. The key is a quoted
|
|
30
|
+
# literal followed by a colon, which a bare variable assignment is not.
|
|
28
31
|
- pattern-regex: |-
|
|
29
|
-
|
|
32
|
+
['"]grant_type['"]\s*:\s*['"]password['"]
|
|
33
|
+
# Call keyword argument: `fetch_token(..., grant_type="password")`. The
|
|
34
|
+
# leading `(` or `,` anchors it to an argument list, so a top-level
|
|
35
|
+
# statement `grant_type = "password"` (library internal) does not match.
|
|
36
|
+
- pattern-regex: |-
|
|
37
|
+
[(,]\s*grant_type\s*=\s*['"]password['"]
|
|
30
38
|
# URL-encoded request body: "grant_type=password&username=…". The value is
|
|
31
39
|
# bounded so `grant_type=password_reset` is not flagged.
|
|
32
40
|
- pattern-regex: |-
|
|
@@ -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
|
-
|
|
23
|
-
- pattern:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|