You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
core: fail a check whose value has an object key that isn't a string #108
Low priority. It only affects policies written in Rego, because JSON and YAML can't express these keys.
Rego lets an object key be any value. When ergo writes such a value into an expression, two cases come out badly. Seen on main (19c9395), with OPA 1.19.0:
A key that is itself an object or a list is written in a different order under Wasm, because sorting inside a key would need the JSON writer to call itself, which Rego doesn't allow:
"value": {{"b": 1, "a": 2}: "x"}
opa eval: x == {"{\"a\":2,\"b\":1}": "x"}
opa test --target wasm: x == {"{\"b\":1,\"a\":2}": "x"}
Two keys that are written the same way both appear, where json.marshal silently keeps one:
Number, boolean and null keys are fine otherwise: they're written as JSON strings, the same in every runtime.
Proposal
Treat an object key that isn't a string, anywhere in a value written in the policy, as a badly written value: the check fails with cause absent, and the expression says so, for example <invalid key>. That's easy to state in a spec and matches failing closed elsewhere.
Open question
Should number keys stay allowed? They work in every runtime today, and a Rego policy might use them on purpose. Failing only on composite keys and on keys that collide once written would close both gaps with less impact.
#155 fixed the failing-closed half of this. A set, or an object key that isn't a string, anywhere in a check now makes it written wrong. Both examples above now fail $well_formed with holds a key that isn't a string, and the check fails as ill_formed:
The expression part is still open. On main (b4eb645), the first one still renders as x == {"{\"a\":2,\"b\":1}": "x"} with opa eval, and a test pinning that string fails under opa test --target wasm. So the report's bytes can still differ between runtimes. Writing <invalid key> in the expression, as proposed above, would close it.
Activity
jbpros commentedon Oct 7, 2026
#155 fixed the failing-closed half of this. A set, or an object key that isn't a string, anywhere in a check now makes it written wrong. Both examples above now fail
$well_formedwithholds a key that isn't a string, and the check fails asill_formed:The expression part is still open. On main (
b4eb645), the first one still renders asx == {"{\"a\":2,\"b\":1}": "x"}withopa eval, and a test pinning that string fails underopa test --target wasm. So the report's bytes can still differ between runtimes. Writing<invalid key>in the expression, as proposed above, would close it.