diff --git a/pages/fraud-prevention/custom-rules/custom-rules-cookbook.mdx b/pages/fraud-prevention/custom-rules/custom-rules-cookbook.mdx index d05b76c..79bb8d1 100644 --- a/pages/fraud-prevention/custom-rules/custom-rules-cookbook.mdx +++ b/pages/fraud-prevention/custom-rules/custom-rules-cookbook.mdx @@ -1,11 +1,11 @@ -# Keyri Rules-Engine Cookbook +# Keyri 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](/fraud-prevention/custom-rules/low-code-rule-builder). -## Recipes +## General Rules ### Reduce False Positives @@ -33,7 +33,10 @@ other rules that might have been triggered. "deviceModel.lieProbability": { "$lte": 0.2 } }, "outcome": "allow", - "signal": "established_user_device_allow" + "signal": "established_user_device_allow", + "strength": 2, + "enabled": true, + "notes": "Allow if device age is at least 7 days, the user has been seen on the device at least 2 times, and the lie probability is less than or equal to 0.2; strength: 2" } ``` @@ -70,16 +73,19 @@ verification. ```json { - "rule": "too_many_user_denials", - "conditions": { + "rule": "too_many_user_denials", + "conditions": { "$or": [ - {"historicalData.user._denials_10_min_": { "$gte": 3 }}, - {"historicalData.user._denials_hour_": { "$gte": 5 }}, - ], - }, - "outcome": "deny", - "signal": "deny_user_id_list", - }, + { "historicalData.user._denials_10_min_": { "$gte": 3 } }, + { "historicalData.user._denials_hour_": { "$gte": 5 } } + ] + }, + "outcome": "deny", + "signal": "deny_user_id_list", + "enabled": true, + "strength": 2, + "notes": "Deny if user has previously been denied at least 3 times in the past 10 minutes or at least 5 times in the past hour; strength: 2" + } ``` #### Explanation: @@ -88,13 +94,13 @@ verification. 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. +- `strength`: A value of 2 means it will override other rules with a lower strength. - `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 true + in an "or" array so if any are true - the whole rule returns as true. - `historicalData.user._denials_10_min_`: If there are more than 2 denials in - 10 minutes on this IP - block it for 10 minutes + 10 minutes on this IP - block it for 10 minutes. - `historicalData.user._denials_hour_`: If there are more than 4 denials in 1 - hour on this IP - block it for an hour + hour on this IP - block it for an hour. --- @@ -107,14 +113,13 @@ If the IP Address you're evaluating is associated with 326 login denials in last 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, whatever +minutes, an hour, etc. #### Code: ```json { "rule": "too_many_ip_denials", - "eventType": "all", "conditions": { "$or": [ { "historicalData.ip._denials_10_min_": { "$gte": 3 } }, @@ -122,7 +127,10 @@ minutes, an hour, whatever ] }, "outcome": "deny", - "signal": "deny_ip_list" + "signal": "deny_ip_list", + "enabled": true, + "strength": 2, + "notes": "Deny if IP has previously been denied at least 3 times in the past 10 minutes or at least 10 times in the past hour; strength: 2" } ``` @@ -132,13 +140,13 @@ minutes, an hour, whatever 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. +- `strength`: A value of 2 means it will override other rules with a lower strength. - `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 true + in an "or" array so if any are true - the whole rule returns as true. - `historicalData.ip._denials_10_min_`: If there are more than 2 denials in 10 - minutes on this IP - block it + minutes on this IP - block it. - `historicalData.ip._denials_hour_`: If there are more than 9 denials in 1 - hour on this IP - block it + hour on this IP - block it. --- @@ -158,7 +166,6 @@ we'll want to deny. ```json { "rule": "too_many_ip_addresses", - "eventType": "all", "conditions": { "$or": [ { "historicalData.user.uniqueIp._totals_day_": { "$gte": 4 } }, @@ -166,7 +173,10 @@ we'll want to deny. ] }, "outcome": "deny", - "signal": "deny_ip_list" + "signal": "deny_ip_list", + "enabled": true, + "strength": 2, + "notes": "Deny if device or user has been seen on at least 4 unique IP addresses in the past 24 hours; strength: 2" } ``` @@ -176,10 +186,196 @@ we'll want to deny. 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. +- `strength`: A value of 2 means it will override other rules with a lower strength. - `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 true + in an "or" array so if any are true - the whole rule returns as true. - `historicalData.user.uniqueIp._totals_day_`: If there are more than 3 IP - Addresses for this user in 24 hours - block it + Addresses for this user in 24 hours - block it. - `historicalData.device.uniqueIp._totals_day_`: If there are more than 3 IP - Addresses for this device in 24 hours - block it + 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. + +#### Code: + +```json +{ + "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, + "notes": "Deny if the device is new to the account and is on VPN; 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. + +#### Code: + +```json +{ + "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, + "notes": "Deny users from any country except for the U.S.; 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 10 to override rules with the default strength +value of 9 or below. + +#### Code: + +```json +{ + "rule": "Override Keyri with own risk model", + "conditions": { + "$and": [ + { + "metadata.riskScore": { + "$lte": 5 + } + } + ] + }, + "outcome": "allow", + "signal": "override_keyri_with_own_risk_model", + "enabled": true, + "strength": 10, + "notes": "Allow if internal risk score is less than or equal to 5 even if Keyri's system has a different determination; strength: 10" +} +``` + +## Financial Rules + +### Limit Transactions to a Certain Amount + +If 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`. + +#### Code: + +```json +{ + "rule": "Transaction threshold - 1000", + "conditions": { + "$and": [ + { + "eventMetadata.amount": { + "$gt": 1000 + } + } + ] + }, + "outcome": "deny", + "signal": "Transaction_threshold_exceeded", + "enabled": true, + "strength": 2, + "notes": "Deny if money being transferred in 1 event is greater than 1,000; 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. + +#### Code: + +```json +{ + "rule": "24-hour spend threshold - 2500", + "conditions": { + "$and": [ + { + "2500": { + "$lte": { + "$sum": [ + "userModel.metadata.amount._sum_24_h_", + "eventMetadata.amount" + ] + } + } + }, + { + "eventMetadata.amount": { + "$gt": 0 + } + } + ] + }, + "outcome": "deny", + "signal": "24-hour_spend_threshold_exceeded", + "enabled": true, + "strength": 2, + "notes": "Deny if money being transferred in the past 24 hours is greater than 2,500; 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. + +#### Code: + +```json +{ + "rule": "new_country_high_value_txn", + "conditions": { + "$and": [ + { + "userModel.country_code.${ipGeoData.country_code}._count_": { "$eq": 1 } + }, + { + "eventMetadata.amount": { + "$gte": 10000 } + } + ] + }, + "outcome": "deny", + "signal": "high_value_new_country", + "enabled": true, + "strength": 2, + "notes": "Deny if user is transferring greater than 10,000 from a new country; strength: 2" +} +```