Restrictions & Best Practices
Security restrictions and best practices for writing effective policies
For security reasons, policies run in a restricted environment. This page documents what is not allowed and provides best practices for writing effective policies.
Policy Limits
Policies are limited to 2,048 characters in length. This encourages concise, focused rules and ensures fast evaluation times.
Platform-Level Restrictions
The following RPC methods are blocked at the platform level and cannot be enabled by any policy:
| Category | Methods |
|---|---|
| Debug & Trace | debug_*, trace_* |
| Legacy Filters | eth_newFilter, eth_newBlockFilter, eth_newPendingTransactionFilter, eth_getFilterChanges, eth_getFilterLogs, eth_uninstallFilter |
These restrictions apply to all requests regardless of organization or endpoint policies.
eth_getLogs Limitations
The eth_getLogs method is restricted to single block queries only. You must specify either:
block_hash: Query logs from a specific block hashblock_number: Query logs from a specific block number (hex format like0x100or tags likelatest)
Block range queries using fromBlock and toBlock are not supported. This restriction applies to both RPC and MCP requests.
Blocked Keywords
The following patterns are not allowed in policies:
| Pattern | Reason |
|---|---|
import ... | Cannot import external modules |
package ... | Cannot declare packages |
default ... | Cannot override default values |
data.* | Cannot reference external data |
Policies attempting to use these patterns will fail validation.
Disabled Built-ins
These built-in categories are disabled and will be rejected:
| Pattern | Error Message |
|---|---|
http.send | "http.send is disabled" |
crypto.* | "Crypto functions are disabled" |
io.jwt.* | "JWT functions are disabled" |
yaml.* | "YAML functions are disabled" |
uuid.* | "UUID functions are disabled" |
glob.* | "Glob functions are disabled" |
semver.* | "Semver functions are disabled" |
json.schema* | "JSON schema functions are disabled" |
graphql.* | "GraphQL functions are disabled" |
net.cidr* | "Net CIDR functions are disabled" |
opa.runtime* | "OPA runtime functions are disabled" |
rego.metadata* | "Rego metadata functions are disabled" |
Policies using disabled builtins will fail validation with a clear error message indicating which function is not allowed.
Validation Errors
When a policy fails validation, you'll receive errors like:
| Error | Cause |
|---|---|
| "Import statements are not allowed" | Policy contains import |
| "Package declarations are not allowed" | Policy contains package |
| "Default statements are not allowed" | Policy contains default |
| "Data references are not allowed" | Policy contains data. |
When compilation fails due to invalid Rego syntax, you'll receive the line number and error message from the compiler.
Best Practices
Lowercase Addresses
Always use lower() for case-insensitive address matching:
# Good: Normalized comparison
deny if {
lower(input.to_address) == "0xdead..."
}
# Bad: May miss matches due to case differences
deny if {
input.to_address == "0xDead..."
}Handle Nullable Fields
Some input fields can be null. Handle this gracefully:
# Good: Check for null before comparison
deny if {
input.usd_value != null
input.usd_value > 10000
}
# Alternative: Use type checking
deny if {
is_number(input.usd_value)
input.usd_value > 10000
}Test Thoroughly
Before deploying policies to production:
- Test with various input combinations
- Verify both allow and deny cases
- Check edge cases (null values, empty arrays)
- Validate against realistic transaction data
Document Your Rules
Use comments to explain complex logic:
# Block high-value transactions during off-hours
# Business hours are 9 AM - 5 PM UTC, Monday-Friday
deny if {
[hour, _, _] := time.clock(time.now_ns())
hour < 9
input.usd_value > 1000
}Use Meaningful Variable Names
When using local variables, choose descriptive names:
# Good: Clear variable names
deny if {
high_risk_threshold := 10000
input.usd_value > high_risk_threshold
}
# Avoid: Cryptic names
deny if {
x := 10000
input.usd_value > x
}