rego_unsafe_var_error: var {name}
is unsafe
This is one of the most common errors reported by OPA. When a variable is "unsafe" it simply means that OPA wasn't able
to determine where to find it. This is commonly caused by misspelling the name of the variable, or perhaps by
referencing a rule or function that doesn't (yet) exist. Note that this check happens at compile time. This means that
references like input.username
will not be considered unsafe even when there is no username
attribute in the input
— as the value of input
isn't known at compile time.
Stage | Category | Message |
---|---|---|
compilation | rego_unsafe_var_error | var {name} is unsafe (where {name} is the name of the variable) |
Examples
Can you spot the unsafe variable in the following policy?
package policy
import future.keywords.if
import future.keywords.in
allow if {
user_is_developer
input.request.path == "/api"
}
allow if user_is_admin
user_is_developer if "developer" in input.user.roles
Not that easy! But luckily we won't have to, as the compiler does it for us:
1 error occurred: policy.rego:11: rego_unsafe_var_error: var user_is_admin is unsafe
Of course! We had forgotten to provide an actual user_is_admin
rule before we used it, and hence why it's
considered unsafe.
Sometimes, the location of the errors isn't as clear-cut, even when reading the errors. Consider the following example. Which variable is unsafe?
package policy
import future.keywords.if
import future.keywords.in
allow if {
first_user := users[0]
title := first_user.title
title_upper := upper(title)
title_upper == "CEO"
}
You'd be excused to say users
, and you'd even be right. But it doesn't stop there:
4 errors occurred:
policy.rego:7: rego_unsafe_var_error: var first_user is unsafe
policy.rego:7: rego_unsafe_var_error: var users is unsafe
policy.rego:8: rego_unsafe_var_error: var title is unsafe
policy.rego:9: rego_unsafe_var_error: var title_upper is unsafe
Since users
is unsafe, every variable that depend on users
is also considered unsafe. This means that all the
variables in our allow
rule will be considered unsafe, and we'll have to do some investigative work to figure out
what the actual root cause was. Whether this should be needed or not is
up for debate, and perhaps we'll be able to skip this in future
OPA versions.
How To Fix It
Fixing this is luckily easy. Once you've found the unsafe variable, first of all figure out why it's considered unsafe. In most cases you'll find it was a typo, and those are luckily easy to fix! In some cases it could be that you're referencing a rule or a function from another package, but have forgotten to load that file during compilation.
One thing to keep in mind is that all OPA commands that accept a file may just as well be provided a directory, which will be loaded recursively. This is is often the best way to ensure all the files you may depend on are loaded and available during compilation.
More Information
Remember how we said earlier that the compiler won't consider a reference like input.usrname
(note the typo!)
unsafe, even though we clearly intended to say input.username
? Wouldn't it be great if we had some way to tell the
OPA compiler what the input
object should look like, and have it include that in this type of check? Luckily, there
is! The desired structure (i.e. the schema) of both input
and data
may be provided to the compiler via OPA's
JSON schema capability, thus extending the
compiler and the type checker with this information. It'll take some work to set up, but it's well worth it!
Community
For questions, discussions and announcements related to OPA, or Styra products, services and open source projects, please join the Styra Community on Slack.