VNX-842: Placement of User into Incorrect Group
A user's role, group or privilege flag is taken from the request, a user model defaults its role or admin flag to an administrative value, or a sign-up function puts the new account into an administrative group (Python, JavaScript/TypeScript).
| Field | Value |
|---|---|
| Rule ID | VNX-842 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | JavaScript / TypeScript, Python |
| CWE | CWE-842 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:L/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:L/DI:H/EX:L/EC:N/P:L |
| Tags | placement-of-user-into-incorrect-group cwe-842 mass-assignment privilege |
| Source | internal/sast/rules/vnx-842.rego |
Overview
VNX-842 maps to CWE-842: Placement of User into Incorrect Group. It reports three shapes in Python and JavaScript/TypeScript:
- The requester picks the group. A role, group or privilege flag set from request data, directly or through a variable assigned from it within the 20 lines above:
user.groups.add(Group.objects.get(name=request.POST[...])),user.role = request.json[...],User(role=...),create_user(is_staff=...), a Mongoose/Sequelize/Prismacreate({ role: req.body.role })(and its shorthand),user.isAdmin = req.body.isAdmin,doc["role"] = request.form["role"],user.roles.push(...)/append(...),user_datastore.add_role_to_user(user, request.form[...]),addUserToGroup(..., req.query.group), a CognitoAdminAddUserToGroupGroupNamefrom the body. - Every account starts privileged. A user model whose role/group/access-level field defaults to an administrative value (
default="admin",default: 'superuser',@Column({ default: 'admin' })) or whoseis_admin/is_staff/is_superuser/isAdminflag defaults to true. - Sign-up grants administration. A register/sign-up/create-account/onboarding function that adds the new user to an administrative group or sets an administrative role or flag.
Not reported: a request-supplied role checked against an allow-list or in a condition first (a bare presence check such as if (!role) is not validation and is still reported), a role change behind an admin or permission check in the 15 lines above (requireAdmin, @admin_required, @permission_required, has_perm, authorize(...)), query filters on a role, constant non-privileged roles, management commands and seed scripts that create administrators on purpose, comments and strings. A privilege granted through a database lookup is not followed.
Why This Matters
Group membership is the authorisation decision. When the request body decides it, or a schema default decides it for every new account, anyone who can register can make themselves an administrator, and every later permission check faithfully honours that.
What Gets Flagged
const user = await User.create({
email: req.body.email,
role: req.body.role, // FLAGGED
});
isAdmin: { type: Boolean, default: true }, // FLAGGED (Mongoose schema)
user.groups.add(Group.objects.get(name=request.POST["group"])) # FLAGGED
role = models.CharField(max_length=20, default="admin") # FLAGGED
def sign_up(request):
...
user.is_superuser = True # FLAGGED
Not flagged: role: 'customer' at registration, if role not in SELF_SERVICE_ROLES: abort(400) before User(role=role), User.find({ role: req.query.role }), a role update in a route behind requireAdmin.
Remediation
- Assign roles on the server. Self-service sign-up gets a fixed, least-privileged default.
- Let only an authorised administrator change a role, and check the requested value against an allow-list.
- Default every role column and admin flag to the least-privileged value.
References
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-842
// nosec vnx-842
Or record an ignore rule: vulnetix ignore add --rule vnx-842 --reason "...". See Suppressing findings.