codeintely-cli 0.1.0__py3-none-any.whl
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.
- codeintely_cli/__init__.py +1 -0
- codeintely_cli/binaries.py +178 -0
- codeintely_cli/main.py +76 -0
- codeintely_cli/output.py +63 -0
- codeintely_cli/rules/appsec_breadth.yaml +220 -0
- codeintely_cli/rules/identity_security.yaml +691 -0
- codeintely_cli/rules/jsts_backend.yaml +167 -0
- codeintely_cli/rules/mass_assignment.yaml +37 -0
- codeintely_cli/rules/owasp_generic.yaml +94 -0
- codeintely_cli/rules/tenant_isolation.yaml +100 -0
- codeintely_cli/scanners.py +298 -0
- codeintely_cli-0.1.0.dist-info/METADATA +72 -0
- codeintely_cli-0.1.0.dist-info/RECORD +17 -0
- codeintely_cli-0.1.0.dist-info/WHEEL +5 -0
- codeintely_cli-0.1.0.dist-info/entry_points.txt +2 -0
- codeintely_cli-0.1.0.dist-info/licenses/LICENSE +193 -0
- codeintely_cli-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
# --- JS/TS backend authz gap closure ---------------------------------------
|
|
3
|
+
#
|
|
4
|
+
# Every JS/TS rule shipped before this file was React-*frontend*-only
|
|
5
|
+
# (owasp_generic.yaml: dangerouslySetInnerHTML, JWT-in-localStorage) —
|
|
6
|
+
# zero Express/NestJS backend tenant-isolation/authz coverage existed.
|
|
7
|
+
# These retarget the same IDOR/privilege-escalation/RBAC categories
|
|
8
|
+
# already proven reliable for Django/FastAPI (identity_security.yaml,
|
|
9
|
+
# tenant_isolation.yaml) at the two most common modern Node backend
|
|
10
|
+
# stacks: Express+Prisma/Mongoose, and NestJS's decorator-based routing.
|
|
11
|
+
#
|
|
12
|
+
# Real Semgrep behavior difference from Python, found by testing rather
|
|
13
|
+
# than assumed: a JS/TS object-literal pattern like `{ id: $ID }` (no
|
|
14
|
+
# ellipsis) matches ANY object containing at least an `id` key,
|
|
15
|
+
# regardless of what else is in it — unlike Python's dict patterns,
|
|
16
|
+
# which need an explicit `...` to mean "and possibly more" and default
|
|
17
|
+
# to an exact match without one. This meant the first version of the
|
|
18
|
+
# Prisma rules below, using a `pattern-not` with an explicit `...` to
|
|
19
|
+
# try to exclude "has more than just id," instead matched NOTHING at
|
|
20
|
+
# all — `...` in a JS object pattern also matches the zero-additional-
|
|
21
|
+
# keys case, so the pattern-not cancelled out the intended vulnerable
|
|
22
|
+
# match too. Fixed with a `pattern-not-regex` naming the common
|
|
23
|
+
# tenant/ownership field names directly (organizationId/orgId/
|
|
24
|
+
# tenantId/userId/ownerId/accountId) instead of trying to express "no
|
|
25
|
+
# additional keys of any kind" structurally.
|
|
26
|
+
|
|
27
|
+
- id: express-prisma-find-unique-missing-tenant-filter
|
|
28
|
+
languages: [js, ts]
|
|
29
|
+
severity: ERROR
|
|
30
|
+
message: >-
|
|
31
|
+
This Prisma `findUnique` looks up a row by `id` alone, with no
|
|
32
|
+
tenant/org/user field in the same `where` clause. In a multi-tenant
|
|
33
|
+
app this is a direct IDOR: any authenticated caller can fetch another
|
|
34
|
+
tenant's row by guessing/incrementing the id. Add the caller's
|
|
35
|
+
tenant/owner as an extra field in the same `where` object, e.g.
|
|
36
|
+
`where: { id, organizationId: req.user.organizationId }`. (Heuristic
|
|
37
|
+
rule based on common field names — expect some false positives on
|
|
38
|
+
genuinely single-tenant/global models.)
|
|
39
|
+
metadata:
|
|
40
|
+
owasp_category: "A01:2021 - Broken Access Control"
|
|
41
|
+
cwe: "CWE-639"
|
|
42
|
+
internal_severity: HIGH
|
|
43
|
+
patterns:
|
|
44
|
+
- pattern: '$PRISMA.$MODEL.findUnique({ where: { id: $ID } })'
|
|
45
|
+
- pattern-not-regex: '(?i)(organizationId|orgId|tenantId|userId|ownerId|accountId)'
|
|
46
|
+
|
|
47
|
+
- id: express-prisma-find-first-missing-tenant-filter
|
|
48
|
+
languages: [js, ts]
|
|
49
|
+
severity: ERROR
|
|
50
|
+
message: >-
|
|
51
|
+
This Prisma `findFirst` filters by `id` alone, with no tenant/org/
|
|
52
|
+
user field in the same `where` clause — the same IDOR shape as
|
|
53
|
+
`findUnique` with only an id filter. Add the caller's tenant/owner as
|
|
54
|
+
an extra field in the same `where` object. (Heuristic rule based on
|
|
55
|
+
common field names — expect some false positives on genuinely
|
|
56
|
+
single-tenant/global models.)
|
|
57
|
+
metadata:
|
|
58
|
+
owasp_category: "A01:2021 - Broken Access Control"
|
|
59
|
+
cwe: "CWE-639"
|
|
60
|
+
internal_severity: HIGH
|
|
61
|
+
patterns:
|
|
62
|
+
- pattern: '$PRISMA.$MODEL.findFirst({ where: { id: $ID } })'
|
|
63
|
+
- pattern-not-regex: '(?i)(organizationId|orgId|tenantId|userId|ownerId|accountId)'
|
|
64
|
+
|
|
65
|
+
- id: express-mongoose-findbyid-no-tenant-scoping
|
|
66
|
+
languages: [js, ts]
|
|
67
|
+
severity: WARNING
|
|
68
|
+
message: >-
|
|
69
|
+
`Model.findById(id)` looks up a row by id alone with no way to add a
|
|
70
|
+
tenant/owner filter in the same call (unlike `findOne`/`find`, which
|
|
71
|
+
take a full query object) — in a multi-tenant app this is a direct
|
|
72
|
+
IDOR unless ownership is verified separately after the fetch. Prefer
|
|
73
|
+
`Model.findOne({ _id: id, organizationId: req.user.organizationId })`
|
|
74
|
+
instead, or explicitly verify the fetched document's owner/tenant
|
|
75
|
+
field before returning it. (Heuristic rule — flags every bare
|
|
76
|
+
`findById` call as worth a second look, since this shape has no
|
|
77
|
+
inline way to show a tenant check even when one does happen
|
|
78
|
+
elsewhere; expect some false positives where ownership is verified
|
|
79
|
+
in a separate line.)
|
|
80
|
+
metadata:
|
|
81
|
+
owasp_category: "A01:2021 - Broken Access Control"
|
|
82
|
+
cwe: "CWE-639"
|
|
83
|
+
internal_severity: MEDIUM
|
|
84
|
+
pattern: $MODEL.findById($ID)
|
|
85
|
+
|
|
86
|
+
- id: express-mass-assignment-from-body
|
|
87
|
+
languages: [js, ts]
|
|
88
|
+
severity: ERROR
|
|
89
|
+
message: >-
|
|
90
|
+
This ORM write passes the raw request body straight through with no
|
|
91
|
+
field allowlist. Any field the client includes in the body — a
|
|
92
|
+
privilege/tenancy field like `role`/`isAdmin`/`organizationId`
|
|
93
|
+
included — gets written as-is. Explicitly pick only the fields this
|
|
94
|
+
endpoint should accept (destructure the specific fields, or use your
|
|
95
|
+
ORM's field-allowlist option) instead of passing the whole body
|
|
96
|
+
object through.
|
|
97
|
+
metadata:
|
|
98
|
+
owasp_category: "A01:2021 - Broken Access Control"
|
|
99
|
+
cwe: "CWE-915"
|
|
100
|
+
internal_severity: CRITICAL
|
|
101
|
+
patterns:
|
|
102
|
+
- pattern-either:
|
|
103
|
+
- pattern: $MODEL.create(req.body)
|
|
104
|
+
- pattern: '$MODEL.create({ data: req.body })'
|
|
105
|
+
- pattern: $MODEL.update(req.body)
|
|
106
|
+
- pattern: $MODEL.updateOne(req.body)
|
|
107
|
+
- pattern: Object.assign($OBJ, req.body)
|
|
108
|
+
|
|
109
|
+
- id: express-privilege-field-from-body
|
|
110
|
+
languages: [js, ts]
|
|
111
|
+
severity: ERROR
|
|
112
|
+
message: >-
|
|
113
|
+
A privilege/tenancy attribute is being set directly from
|
|
114
|
+
`req.body`. If this code path is reachable by a normal
|
|
115
|
+
(non-admin) authenticated user, they can grant themselves elevated
|
|
116
|
+
privileges or move themselves into another tenant by sending that
|
|
117
|
+
field in the request body. Set this field only from trusted
|
|
118
|
+
server-side logic, gated behind an explicit admin/role check.
|
|
119
|
+
metadata:
|
|
120
|
+
owasp_category: "A01:2021 - Broken Access Control"
|
|
121
|
+
cwe: "CWE-269"
|
|
122
|
+
internal_severity: CRITICAL
|
|
123
|
+
patterns:
|
|
124
|
+
- pattern-either:
|
|
125
|
+
- pattern: $OBJ.role = req.body.role
|
|
126
|
+
- pattern: $OBJ.isAdmin = req.body.isAdmin
|
|
127
|
+
- pattern: $OBJ.is_admin = req.body.is_admin
|
|
128
|
+
- pattern: $OBJ.isStaff = req.body.isStaff
|
|
129
|
+
- pattern: $OBJ.organizationId = req.body.organizationId
|
|
130
|
+
- pattern: $OBJ.tenantId = req.body.tenantId
|
|
131
|
+
|
|
132
|
+
- id: nestjs-controller-missing-guard
|
|
133
|
+
languages: [ts]
|
|
134
|
+
severity: WARNING
|
|
135
|
+
message: >-
|
|
136
|
+
This `@Controller` class has no `@UseGuards(...)` anywhere on the
|
|
137
|
+
class or its route handlers. Being routable isn't the same as being
|
|
138
|
+
authorized — every route on this controller is reachable by anyone
|
|
139
|
+
who can reach the app at all, with no authentication/authorization
|
|
140
|
+
check. Add `@UseGuards(AuthGuard(...))` (or your app's equivalent) at
|
|
141
|
+
the class level, or per-method if only some routes need it.
|
|
142
|
+
metadata:
|
|
143
|
+
owasp_category: "A01:2021 - Broken Access Control"
|
|
144
|
+
cwe: "CWE-862"
|
|
145
|
+
internal_severity: HIGH
|
|
146
|
+
patterns:
|
|
147
|
+
- pattern: |
|
|
148
|
+
@Controller(...)
|
|
149
|
+
class $CTRL {
|
|
150
|
+
...
|
|
151
|
+
}
|
|
152
|
+
- pattern-not: |
|
|
153
|
+
@Controller(...)
|
|
154
|
+
@UseGuards(...)
|
|
155
|
+
class $CTRL {
|
|
156
|
+
...
|
|
157
|
+
}
|
|
158
|
+
- pattern-not: |
|
|
159
|
+
@Controller(...)
|
|
160
|
+
class $CTRL {
|
|
161
|
+
...
|
|
162
|
+
@UseGuards(...)
|
|
163
|
+
$METHOD(...) {
|
|
164
|
+
...
|
|
165
|
+
}
|
|
166
|
+
...
|
|
167
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
- id: drf-serializer-fields-all
|
|
3
|
+
languages: [python]
|
|
4
|
+
severity: WARNING
|
|
5
|
+
message: >-
|
|
6
|
+
This DRF ModelSerializer uses `fields = "__all__"`. Any field added to the
|
|
7
|
+
model later (including sensitive ones like `is_admin`, `tenant_id`, `role`)
|
|
8
|
+
becomes writable through this serializer without a deliberate decision.
|
|
9
|
+
Prefer an explicit `fields` list or `read_only_fields` for anything the
|
|
10
|
+
client shouldn't set.
|
|
11
|
+
metadata:
|
|
12
|
+
owasp_category: "A01:2021 - Broken Access Control"
|
|
13
|
+
cwe: "CWE-915"
|
|
14
|
+
internal_severity: MEDIUM
|
|
15
|
+
patterns:
|
|
16
|
+
- pattern: |
|
|
17
|
+
class $META:
|
|
18
|
+
model = $MODEL
|
|
19
|
+
fields = "__all__"
|
|
20
|
+
|
|
21
|
+
- id: django-mass-assignment-from-request-data
|
|
22
|
+
languages: [python]
|
|
23
|
+
severity: ERROR
|
|
24
|
+
message: >-
|
|
25
|
+
This creates/updates a model directly from `request.data`/`request.POST`
|
|
26
|
+
without going through a serializer's field allowlist. A client can set any
|
|
27
|
+
model field this way — including ones they shouldn't control, like
|
|
28
|
+
`is_admin`, `tenant_id`, or `role`.
|
|
29
|
+
metadata:
|
|
30
|
+
owasp_category: "A01:2021 - Broken Access Control"
|
|
31
|
+
cwe: "CWE-915"
|
|
32
|
+
internal_severity: HIGH
|
|
33
|
+
patterns:
|
|
34
|
+
- pattern-either:
|
|
35
|
+
- pattern: $MODEL.objects.create(**request.data)
|
|
36
|
+
- pattern: $MODEL.objects.create(**request.POST)
|
|
37
|
+
- pattern: $MODEL.objects.create(**request.POST.dict())
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
- id: django-raw-sql-string-built
|
|
3
|
+
languages: [python]
|
|
4
|
+
severity: WARNING
|
|
5
|
+
message: >-
|
|
6
|
+
This raw SQL call looks string-built (f-string/`.format()`/`%`) rather than
|
|
7
|
+
using parameterized placeholders. If any part of the query comes from user
|
|
8
|
+
input, this is SQL injection. Use parameterized placeholders (`%s` with a
|
|
9
|
+
params list/tuple) instead of formatting user input into the query string.
|
|
10
|
+
metadata:
|
|
11
|
+
owasp_category: "A03:2021 - Injection"
|
|
12
|
+
cwe: "CWE-89"
|
|
13
|
+
internal_severity: HIGH
|
|
14
|
+
patterns:
|
|
15
|
+
- pattern-either:
|
|
16
|
+
- pattern: $MODEL.objects.raw($QUERY)
|
|
17
|
+
- pattern: $CURSOR.execute($QUERY)
|
|
18
|
+
- metavariable-regex:
|
|
19
|
+
metavariable: $QUERY
|
|
20
|
+
regex: '.*(f"|f''|\.format\(|%\s*\().*'
|
|
21
|
+
|
|
22
|
+
- id: django-debug-true
|
|
23
|
+
languages: [python]
|
|
24
|
+
severity: ERROR
|
|
25
|
+
message: >-
|
|
26
|
+
DEBUG = True must never ship to production — it leaks stack traces, settings
|
|
27
|
+
values, and source snippets on error pages to anyone who can trigger a 500.
|
|
28
|
+
metadata:
|
|
29
|
+
owasp_category: "A05:2021 - Security Misconfiguration"
|
|
30
|
+
cwe: "CWE-215"
|
|
31
|
+
internal_severity: CRITICAL
|
|
32
|
+
pattern: DEBUG = True
|
|
33
|
+
|
|
34
|
+
- id: django-cors-allow-all-origins
|
|
35
|
+
languages: [python]
|
|
36
|
+
severity: ERROR
|
|
37
|
+
message: >-
|
|
38
|
+
CORS_ALLOW_ALL_ORIGINS = True lets any website make cross-origin requests to
|
|
39
|
+
this API, including ones carrying a logged-in user's credentials if
|
|
40
|
+
CORS_ALLOW_CREDENTIALS is also on. Set an explicit CORS_ALLOWED_ORIGINS
|
|
41
|
+
allowlist instead.
|
|
42
|
+
metadata:
|
|
43
|
+
owasp_category: "A05:2021 - Security Misconfiguration"
|
|
44
|
+
cwe: "CWE-942"
|
|
45
|
+
internal_severity: HIGH
|
|
46
|
+
pattern: CORS_ALLOW_ALL_ORIGINS = True
|
|
47
|
+
|
|
48
|
+
- id: django-fileupload-original-filename
|
|
49
|
+
languages: [python]
|
|
50
|
+
severity: WARNING
|
|
51
|
+
message: >-
|
|
52
|
+
This saves an uploaded file using its original filename with no visible
|
|
53
|
+
extension/content-type validation nearby. A crafted filename (path
|
|
54
|
+
traversal, double extension, disguised executable) could be written as-is.
|
|
55
|
+
Validate extension/content-type and generate a safe filename before saving.
|
|
56
|
+
metadata:
|
|
57
|
+
owasp_category: "A04:2021 - Insecure Design"
|
|
58
|
+
cwe: "CWE-434"
|
|
59
|
+
internal_severity: MEDIUM
|
|
60
|
+
patterns:
|
|
61
|
+
- pattern-either:
|
|
62
|
+
- pattern: default_storage.save($FILE.name, $FILE)
|
|
63
|
+
- pattern: open($FILE.name, ...)
|
|
64
|
+
|
|
65
|
+
- id: react-dangerously-set-inner-html
|
|
66
|
+
languages: [js, ts]
|
|
67
|
+
severity: WARNING
|
|
68
|
+
message: >-
|
|
69
|
+
`dangerouslySetInnerHTML` renders raw HTML without React's normal escaping.
|
|
70
|
+
If any part of this value comes from user input or an API response, this is
|
|
71
|
+
a stored/reflected XSS vector. Sanitize with a library like DOMPurify before
|
|
72
|
+
rendering, or avoid raw HTML entirely.
|
|
73
|
+
metadata:
|
|
74
|
+
owasp_category: "A03:2021 - Injection"
|
|
75
|
+
cwe: "CWE-79"
|
|
76
|
+
internal_severity: HIGH
|
|
77
|
+
pattern: <$EL dangerouslySetInnerHTML={...} />
|
|
78
|
+
|
|
79
|
+
- id: jwt-stored-in-localstorage
|
|
80
|
+
languages: [js, ts]
|
|
81
|
+
severity: WARNING
|
|
82
|
+
message: >-
|
|
83
|
+
Storing a JWT/access token in localStorage exposes it to any XSS on the
|
|
84
|
+
page — localStorage is readable by any script running on the origin.
|
|
85
|
+
Prefer an httpOnly, Secure, SameSite cookie for session/auth tokens.
|
|
86
|
+
metadata:
|
|
87
|
+
owasp_category: "A02:2021 - Cryptographic Failures"
|
|
88
|
+
cwe: "CWE-522"
|
|
89
|
+
internal_severity: MEDIUM
|
|
90
|
+
patterns:
|
|
91
|
+
- pattern: localStorage.setItem($KEY, $TOKEN)
|
|
92
|
+
- metavariable-regex:
|
|
93
|
+
metavariable: $KEY
|
|
94
|
+
regex: '(?i).*(token|jwt|auth).*'
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
- id: django-viewset-missing-permission-classes
|
|
3
|
+
languages: [python]
|
|
4
|
+
severity: ERROR
|
|
5
|
+
message: >-
|
|
6
|
+
This DRF ViewSet/APIView does not declare `permission_classes`. Without it, DRF
|
|
7
|
+
falls back to the global DEFAULT_PERMISSION_CLASSES (or AllowAny if that's unset),
|
|
8
|
+
which can expose this endpoint to unauthenticated or unauthorized users.
|
|
9
|
+
metadata:
|
|
10
|
+
owasp_category: "A01:2021 - Broken Access Control"
|
|
11
|
+
cwe: "CWE-862"
|
|
12
|
+
internal_severity: HIGH
|
|
13
|
+
patterns:
|
|
14
|
+
- pattern: |
|
|
15
|
+
class $VIEW(...):
|
|
16
|
+
...
|
|
17
|
+
- pattern-not: |
|
|
18
|
+
class $VIEW(...):
|
|
19
|
+
...
|
|
20
|
+
permission_classes = ...
|
|
21
|
+
...
|
|
22
|
+
- metavariable-regex:
|
|
23
|
+
metavariable: $VIEW
|
|
24
|
+
regex: ".*(ViewSet|APIView)$"
|
|
25
|
+
|
|
26
|
+
- id: django-orm-query-missing-tenant-filter
|
|
27
|
+
languages: [python]
|
|
28
|
+
severity: WARNING
|
|
29
|
+
message: >-
|
|
30
|
+
This ORM lookup filters only by id/pk with no tenant/org scoping visible in the
|
|
31
|
+
same call. In a multi-tenant app, a user could read another tenant's row by
|
|
32
|
+
guessing/incrementing the id. Scope the query with the caller's tenant, e.g.
|
|
33
|
+
`.filter(id=pk, tenant=request.user.tenant)`. (Heuristic rule — expect some
|
|
34
|
+
false positives on genuinely single-tenant models; a strong candidate for
|
|
35
|
+
suppression-pattern learning once that exists.)
|
|
36
|
+
metadata:
|
|
37
|
+
owasp_category: "A01:2021 - Broken Access Control"
|
|
38
|
+
cwe: "CWE-639"
|
|
39
|
+
internal_severity: HIGH
|
|
40
|
+
patterns:
|
|
41
|
+
- pattern-either:
|
|
42
|
+
- pattern: $MODEL.objects.get(id=$ID)
|
|
43
|
+
- pattern: $MODEL.objects.get(pk=$PK)
|
|
44
|
+
- pattern: $MODEL.objects.filter(id=$ID)
|
|
45
|
+
- pattern: $MODEL.objects.filter(pk=$PK)
|
|
46
|
+
|
|
47
|
+
- id: fastapi-route-missing-auth-dependency
|
|
48
|
+
languages: [python]
|
|
49
|
+
severity: ERROR
|
|
50
|
+
message: >-
|
|
51
|
+
This FastAPI route has no `Depends(...)` in its decorator/signature. If this
|
|
52
|
+
endpoint should require authentication, add a dependency such as
|
|
53
|
+
`Depends(get_current_user)`.
|
|
54
|
+
metadata:
|
|
55
|
+
owasp_category: "A01:2021 - Broken Access Control"
|
|
56
|
+
cwe: "CWE-306"
|
|
57
|
+
internal_severity: HIGH
|
|
58
|
+
patterns:
|
|
59
|
+
- pattern-either:
|
|
60
|
+
- pattern: |
|
|
61
|
+
@$APP.get($PATH, ...)
|
|
62
|
+
def $FUNC(...):
|
|
63
|
+
...
|
|
64
|
+
- pattern: |
|
|
65
|
+
@$APP.post($PATH, ...)
|
|
66
|
+
def $FUNC(...):
|
|
67
|
+
...
|
|
68
|
+
- pattern: |
|
|
69
|
+
@$APP.put($PATH, ...)
|
|
70
|
+
def $FUNC(...):
|
|
71
|
+
...
|
|
72
|
+
- pattern: |
|
|
73
|
+
@$APP.delete($PATH, ...)
|
|
74
|
+
def $FUNC(...):
|
|
75
|
+
...
|
|
76
|
+
- pattern-not-regex: "Depends\\("
|
|
77
|
+
|
|
78
|
+
- id: fastapi-admin-route-missing-role-check
|
|
79
|
+
languages: [python]
|
|
80
|
+
severity: WARNING
|
|
81
|
+
message: >-
|
|
82
|
+
This route's path looks admin/internal-only but its body has no visible
|
|
83
|
+
role/permission check (e.g. `require_role(...)`, `.is_admin`,
|
|
84
|
+
`check_permission(...)`). Being authenticated isn't the same as being
|
|
85
|
+
authorized — verify the caller's role explicitly for privileged actions.
|
|
86
|
+
(Heuristic rule based on path naming; adjust the regex to your project's
|
|
87
|
+
conventions.)
|
|
88
|
+
metadata:
|
|
89
|
+
owasp_category: "A01:2021 - Broken Access Control"
|
|
90
|
+
cwe: "CWE-862"
|
|
91
|
+
internal_severity: MEDIUM
|
|
92
|
+
patterns:
|
|
93
|
+
- pattern: |
|
|
94
|
+
@$APP.$METHOD($PATH, ...)
|
|
95
|
+
def $FUNC(...):
|
|
96
|
+
...
|
|
97
|
+
- metavariable-regex:
|
|
98
|
+
metavariable: $PATH
|
|
99
|
+
regex: '.*(admin|internal).*'
|
|
100
|
+
- pattern-not-regex: "(require_role|check_permission|is_admin|is_staff|is_superuser)"
|