Skip to main content

not-equals-in-loop

Summary: Use of != in loop

Category: Bugs

Avoid

package policy

import rego.v1

deny if {
"admin" != input.user.roles[_]
}

Prefer

package policy

import rego.v1

deny if {
not "admin" in input.user.roles
}

# Or as a one-liner
deny if not "admin" in input.user.roles

Rationale

Likely one of the most common mistakes in Rego is to use != in a loop thinking it means "not in". It took some years for the in keyword to be added to Rego, so perhaps it's not surprising that this mistake is a common one even to this day. If it doesn't mean "not in", what does it mean?

package policy

import rego.v1

deny if {
"admin" != input.user.roles[_]
}

The body of the deny rule above roughly translates to "for any item in input.user.roles, return true if the item is not admin". This is almost never what the policy author intended. What the policy author likely intended was "deny if admin is not in input.user.roles". The above policy would thus not deny a user with the roles ["user", "admin"] since the first item in the array is not "admin". This is almost never what the policy author intended.

Note: This linter rule currently only checks for != in a non-nested comparison where iteration happens on either side of the comparison in the same expression. This will be improved in time. Another limitation is that this rule currently only checks for wildcard iteration ([_]).

Configuration Options

This linter rule provides the following configuration options:

rules:
bugs:
not-equals-in-loop:
# one of "error", "warning", "ignore"
level: error

Community

If you think you've found a problem with this rule or its documentation, would like to suggest improvements, new rules, or just talk about Regal in general, please join us in the #regal channel in the Styra Community Slack!