Custom Rules - Examples
Here you'll find example solutions to common problems as copy-and-paste code snippets with explanations. These can be used both with our no-code rule builder and low-code rule builder.
General Rules
Reduce False Positives
Everyone hates captchas, especially when they're not doing anything suspicious on a site they visit frequently. You can enhance the user experience significantly by implementing this simple rule. It allows known good users (probably 98%) to bypass certain checks, reserving stricter measures for those you're less certain about.
How it Works
If you've seen user a@b.com
on device abc123
15 times in the last 3 months,
you can be fairly certain they're not a bad actor, and they can supersede any
other rules that might have been triggered.
Code
{
"rule": "established_user_device_allow",
"conditions": {
"deviceModel.deviceAgeUser": { "$gte": 7 },
"deviceModel.daysUserSeenOnDeviceCount": { "$gte": 2 },
"deviceModel.lieProbability": { "$lte": 0.2 }
},
"outcome": "allow",
"signal": "established_user_device_allow",
"enabled": true,
"strength": 2
}
Explanation
rule
: The name of the rule, here it's "established_user_device_allow".outcome
: Set to "allow", so if the rule evaluates to true, the event is allowed.strength
: A value of 2 means it will override other rules with a lower strength.conditions
: Defines the criteria for the rule:deviceModel.deviceAgeUser
: If the device and user combo is older than 6 days, it returns true.deviceModel.daysUserSeenOnDeviceCount
: If the user has appeared on this device on 2 or more distinct days, it returns true.deviceModel.lieProbability
: The likelihood of device tampering should be under 20% to return true.
Automatically Block Users With Too Many Denials
You don't want to give bad actors unlimited attempts to try logging into a user's account, right? The best policy is to lock the user's account.
How It Works
You're blocking User ID's with more than count
denials in a given period.
After too many denials occur for this account - it can't be used for 10 minutes,
an hour, a day, or until the user provides some additional guidance and
verification.
Code
{
"rule": "too_many_user_denials",
"conditions": {
"$or": [
{ "historicalData.user._denials_10_minutes": { "$gte": 3 } },
{ "historicalData.user._denials_hour": { "$gte": 5 } }
]
},
"outcome": "deny",
"signal": "deny_user_id_list",
"enabled": true,
"strength": 2
}
Explanation
rule
: The name of the rule, here it's "too_many_user_denials" (name it whatever you want).outcome
: Set to "deny", so if the rule evaluates to true, the event is denied.strength
: Doesn't have to be set. We're letting it default to 1.conditions
: Defines the criteria for the rule. In this case they're nested in an "or" array so if any are true - the whole rule returns as truehistoricalData.user._denials_10_minutes
: If there are more than 2 denials in 10 minutes on this IP - block it for 10 minuteshistoricalData.user._denials_hour
: If there are more than 4 denials in 1 hour on this IP - block it for an hour
Automatically Block Abusive IP Addresses
If the IP Address you're evaluating is associated with 326 login denials in last 24 hours, you probably don't want to let any one use it, right?
How It Works
You're blocking IP Addresses with more than count
denials in a given period.
After too many denials occur on the IP Address - nobody can use it for 10
minutes, an hour, etc.
Code
{
"rule": "too_many_ip_denials",
"conditions": {
"$or": [
{ "historicalData.ip._denials_10_minutes": { "$gte": 3 } },
{ "historicalData.ip._denials_hour": { "$gte": 10 } }
]
},
"outcome": "deny",
"signal": "deny_ip_list",
"enabled": true,
"strength": 2
}
Explanation
rule
: The name of the rule, here it's "too_many_ip_denials" (name it whatever you want).outcome
: Set to "deny", so if the rule evaluates to true, the event is denied.strength
: Doesn't have to be set. We're letting it default to 1.conditions
: Defines the criteria for the rule. In this case they're nested in an "or" array so if any are true - the whole rule returns as truehistoricalData.ip._denials_10_minutes
: If there are more than 2 denials in 10 minutes on this IP - block ithistoricalData.ip._denials_hour
: If there are more than 9 denials in 1 hour on this IP - block it
Too Many IP Changes
If the user or device coming in has been on 10 or more IP addresses over the course of the day, you might want to engage in step-up-authentication, as this is pretty suspicious.
How It Works
If the user or device has been on 4 or more unique IP Addresses in 24 hours, we'll want to deny.
Code
{
"rule": "too_many_ip_addresses",
"conditions": {
"$or": [
{ "historicalData.user.uniqueIp._totals_24_hours": { "$gte": 4 } },
{ "historicalData.device.uniqueIp._totals_24_hours": { "$gte": 4 } }
]
},
"outcome": "deny",
"signal": "deny_ip_list",
"enabled": true,
"strength": 2
}
Explanation
rule
: The name of the rule, here it's "too_many_ip_denials" (name it whatever you want).outcome
: Set to "deny", so if the rule evaluates to true, the event is denied.strength
: Doesn't have to be set. We're letting it default to 1.conditions
: Defines the criteria for the rule. In this case they're nested in an "or" array so if any are true - the whole rule returns as truehistoricalData.user.uniqueIp._totals_24_hours
: If there are more than 3 IP Addresses for this user in 24 hours - block ithistoricalData.device.uniqueIp._totals_24_hours
: If there are more than 3 IP Addresses for this device in 24 hours - block it
Block Users on New Device and VPN
Leverage the threat
object to determine whether the user is using a VPN and
the changed
boolean value under deviceUsers
to determine whether that
user-device combination is new.
{
"rule": "New Device and VPN - deny",
"conditions": {
"$and": [
{
"instanceDeltas.deviceUsers.changed": {
"$eq": true
}
},
{
"threat.is_vpn": {
"$eq": true
}
}
]
},
"outcome": "deny",
"signal": "new_device_and_vpn",
"enabled": true,
"strength": 2
}
Only Allow Users from a Certain Country
The following rule will only allow users from the US to access your site. The
user's country is denoted in the ipGeoData.country_code
property.
{
"rule": "Only allow users from the US",
"conditions": {
"ipGeoData.country_code": {
"$ne": "US"
}
},
"outcome": "block",
"signal": "only_allow_users_from_us",
"enabled": true,
"strength": 2
}
Override Keyri's Risk Determination with your Own Risk Model
If you already have a risk model, you can use it in conjunction with Keyri
rulesets or use its determination to simply override Keyri's determination. Pass
in your risk score as metadata and use it in your ruleset. In this example,
we're overriding Keyri if the risk score from your model is very low. It has a
strength
value of 2 to override rules with the default strength value of 1.
{
"rule": "Override Keyri with own risk model",
"conditions": {
"$and": [
{
"metadata.riskScore": {
"$lte": 5
}
}
]
},
"outcome": "allow",
"signal": "override_keyri_with_own_risk_model",
"strength": 10,
"enabled": true
}
Financial Rules
Limit Transactions to a Certain Amount
If you want to limit the amount of money that can be transferred in a single
event, you can add metadata when triggering the event to indicate the amount. Be
sure to name the metadata field the same as the one in the rule. Here's it's
named amount
.
{
"rule": "Transaction threshold - $1000",
"conditions": {
"$and": [
{
"eventMetadata.amount": {
"$gt": 1000
}
}
]
},
"outcome": "deny",
"signal": "Transaction_threshold_exceeded",
"enabled": true,
"strength": 2
}
Limit Transaction Totals over a Period of Time
You can use built-in math functionality to query and sum the total value of the amounts a given user has transacted over a period of time.
{
"rule": "24-hour spend threshold - $2500",
"conditions": {
"$and": [
{
"2500": {
"$lte": {
"$sum": [
"userModel.metadata.amount._sum_24_hours",
"eventMetadata.amount"
]
}
}
},
{
"eventMetadata.amount": {
"$gt": 0
}
}
]
},
"outcome": "deny",
"signal": "24-hour_spend_threshold_exceeded",
"enabled": true,
"strength": 2
}
Block High-Value Transactions from a New Country
Use this rule to block a high-value transaction from a country that the user has never been in before.
{
"rule": "new_country_high_value_txn",
"conditions": {
"$and": [
{
"instanceDeltas.country_code.changed": { "$eq": true }
},
{
"eventMetadata.amount": { "$gte": 10000 }
}
]
},
"outcome": "deny",
"signal": "high_value_new_country",
"enabled": true,
"strength": 2
}
Transaction Anomaly Detection
Your compliance rules say that a user can't have more than 5 transactions over $1,000 in a 72 hour time period. Here's how you can do that:
{
"rule": "Transaction Anomaly Detected", // This is the rule's name
"outcome": "deny", // This is what happens if our "conditions" are true
"signal": "transaction_anomaly_detected", // The string that will be returned to you if the rule is triggered
"enabled": true, // This means the rule is to be used if it is true
"strength": 2, // This means the rule overrides anything with a strength < 2
"conditions": {
// This defines the rule's logic - it resolves to true or false
"$transform": [
// Add the number 4 to the object for later use as 'testValue'
{ "testValue": 4 },
// Put the value from the following calculation on the object
// as 'actualValue'
{
"actualValue": {
// glorified "sumIf" function
"$reduce": {
// What field are we summing?
"input": "userModel.rawMetaData",
// What number do we want to start with
"initialValue": 0,
// What criteria does each element need to meet to
// added to the total?
"conditions": {
// This is an explicit 'AND' so all things must
// be true
"$and": [
// the 'value' field must be >= 500
{ "value": { "$gte": 500 } },
// the 'attribute' field must EQUAL the
// string 'metadata.amount' for this example
{ "attribute": { "$eq": "metadata.amount" } },
// the 'hoursAgo' field must be >= 0
{ "hoursAgo": { "$gte": 0 } },
// the 'hoursAgo' field must be <= 72
{ "hoursAgo": { "$lte": 72 } }
]
},
// What do we want to do to each element that meets
// our criteria?
"math": {
// We're to sum ('$sum') the running total ('$$value')
// and the value of the element's 'count' field
"$sum": ["$$value", "count"]
}
}
}
}
],
// We're out of the "$transform" function and can now do logic
// against the values we added to the object ("actualValue", "testValue")
"$and": [
// If the "actualValue" (the sumIf) >= "testValue" (4)
{ "actualValue": { "$gte": "testValue" } },
// AND the "eventMetadata.amount" >= 500
{ "eventMetadata.amount": { "$gte": 500 } }
]
}
}
This one is verbose - but not really that bad once you see what's going on.
Explanation
rule
: The name of the rule, here it's "Transaction Anomaly Detected" (name it whatever you want).outcome
: Set to "deny", so if the rule evaluates to true, the event is denied.strength
: Optional. Determines the overriding behavior of this rule over others of lesser strength.conditions
: Defines the criteria for the rule.$transform
: This function is an array of things that you want add to the object, or things you want to update. In this case, we're writing the number4
directly to the object so we can use it in logic later. We're also summing up all transactions with thereduce
function.