Skip to main content

New to Google SecOps: Excluding Entities from Rules Using Data Tables

  • October 28, 2025
  • 0 replies
  • 86 views

jstoner
Staff
Forum|alt.badge.img+22

Last time, we built rules that leveraged the graph_override command in YARA-L to, unsurprisingly, override values from the entity graph with values in a data table. The concepts and data that we used for those examples will be leveraged today as we take a look at another command, graph_exclude.

 

graph_exclude

The graph_exclude command provides detection engineers with the ability to collect all of their users from the entity graph and then exclude users that exist within the referenced data table. By using this technique, we can quickly and easily exclude for instance, certain assets or users, from rule logic consideration.

 

If the entire circle below consists of all of the users within my organization captured with the  entity graph, we could create a listing of users in a data table and use graph_exclude to reduce the users from the population and just focus rules on those remaining users.

 

 

The syntax for graph_exclude is very similar to graph_override. One or more fields can be mapped using boolean logic between the entity graph and the data table. In the example below, we are mapping the field entity.user.userid in the entity graph with the userid column in the subsidiary_users data table. 

setup:
   graph_exclude($graph.graph.entity.user.userid = %subsidiary_users.userid) 

 

Because we are using the same data table as we did in the previous examples, let’s take a quick look at it. Remember, if a user exists in both the data table and the entity graph, those users would not be considered in the broader rule, only those that are NOT in the data table would be evaluated.

 

 

This rule detects process launch events pertaining to NTDS. There is a reference list that contains a list of processes that we want to detect when they are being executed. Btw, this reference list could just as easily be a data table. In fact, reference lists will be deprecated in June 2026.

rule utilities_associated_with_ntdsdit_entity_graph {


 meta:
   author = "Google Cloud Security"
   description = "Detects process launches from processes related to ntds"
   assumption = "Assumes list for ntds suspicious processes have been created"
   data_source = "microsoft sysmon, microsoft windows events"
   severity = "High"

 events:
   $process.metadata.event_type = "PROCESS_LAUNCH"
   // ntds_suspicious_processes includes values like ntdsutil, vssadmin, diskshadow, esentutl
   (
       re.capture($process.principal.process.file.full_path, /.*\\(.*).exe/) in %ntds_suspicious_processes or
       re.capture($process.src.process.file.full_path, /.*\\(.*).exe/) in %ntds_suspicious_processes or
       re.capture($process.target.process.file.full_path, /.*\\(.*).exe/) in %ntds_suspicious_processes
   )
   $process.principal.user.userid = $userid

   $graph.graph.metadata.entity_type = "USER"
   $graph.graph.metadata.source_type = "ENTITY_CONTEXT"
   $graph.graph.entity.user.userid = $userid

 match: 
   $userid over 5m

 condition:
   $process and $graph
}

 

Our rule joins the principal.user.userid in the events to the entity.user.userid in the entity graph. We can see we have a few detections, including frank.kolzig and tim.smith_admin. Notice we have expanded both of the detections to highlight that we have entities and events for each one. 

 

Now, let’s apply the graph_exclude command to the same rule and see what we get. Remember the data table we are using is displayed above.

rule utilities_associated_with_ntdsdit_entity_graph {

 meta:
   (snip)

 setup:
   graph_exclude($graph.graph.entity.user.userid = %subsidiary_users.userid)

 events:
   $process.metadata.event_type = "PROCESS_LAUNCH"
   // ntds_suspicious_processes includes values like ntdsutil, vssadmin, diskshadow, esentutl
   (
       re.capture($process.principal.process.file.full_path, /.*\\(.*).exe/) in %ntds_suspicious_processes or
       re.capture($process.src.process.file.full_path, /.*\\(.*).exe/) in %ntds_suspicious_processes or
       re.capture($process.target.process.file.full_path, /.*\\(.*).exe/) in %ntds_suspicious_processes
   )
   $process.principal.user.userid = $userid

   $graph.graph.metadata.entity_type = "USER"
   $graph.graph.metadata.source_type = "ENTITY_CONTEXT"
   $graph.graph.entity.user.userid = $userid

 match: 
   $userid over 5m

 condition:
   $process and $graph
}

 

By adding the setup section to the rule above, we first identify the values from the entity graph field entity.user.userid that match the subsidiary_users data table field userid and exclude them from consideration within the rest of the rule. The result is that the other detections, except for tim.smith_admin are excluded and we get a single detection returned.

 

 

Now, you may be thinking, why bother with all that? We could easily exclude a list of users using a NOT statement in front of a data table that contains userids. You would not be wrong drawing that conclusion. Here is what that rule might look like.

rule utilities_associated_with_ntdsdit_entity_graph {

 meta:
   (snip)

 events:
   $process.metadata.event_type = "PROCESS_LAUNCH"
   // ntds_suspicious_processes includes values like ntdsutil, vssadmin, diskshadow, esentutl
   (
       re.capture($process.principal.process.file.full_path, /.*\\(.*).exe/) in %ntds_suspicious_processes or
       re.capture($process.src.process.file.full_path, /.*\\(.*).exe/) in %ntds_suspicious_processes or
       re.capture($process.target.process.file.full_path, /.*\\(.*).exe/) in %ntds_suspicious_processes
   )
   $process.principal.user.userid = $userid

   NOT $process.principal.user.userid IN %subsidiary_users.userid

 match: 
   $userid over 5m

 condition:
   $process
}

 

However, you may also encounter additional values that either aren’t in the data table or entity graph that are flagged in the detection like the userid administrator, which is shown below. We can quibble that these administrator process launches should probably be detected, but the point is that these are considerations that we need to make when choosing the right tool to use.

 

 

This example also highlights how the rule logic processes. The setup section excludes common values first and then the rest of the rule runs on the subset of users in the entity graph. The user Administrator is not in the entity graph, so the exclusion didn’t process this userid. The logic then moved to the event section and because the principal.user.userid of Administrator is not in the data table, the detection logic continues and we have the detection results above.

 

So, let’s circle back to the when and why would we use graph_exclude? I’m going to bring back this flowchart I showed in the blog introducing these commands.

 

 

The last example I showed didn’t use the graph_exclude command because perhaps a data table with a list of users and the NOT operator can do the job. So in the flowchart above, I determined that I don’t really need the entity graph to get the job done and focused on enriched fields, if needed, built my rule and moved along.

 

However, there may be times when there are users in the entity graph and we can use one or more joins between it and a data table to exclude users from our detection logic.

 

Remember that while my example today used users from the entity graph, your rule could leverage other entities, whether they are IOCs, assets or other entity types. Here are a few things to keep in mind:

  • Determine if a data table can be used by itself to exclude
  • If not, identify one or more values in the entity graph to align with a data table to perform the exclusion
  • Make sure the entity graph is referenced in the events section of the rule


To me, graph_exclude is the simplest of the three commands in the data table and entity graph integration and provides you with another tool to have at your disposal. If you have existing rules that leverage the entity graph and you need a quick way to exclude a subset of those users or assets, this is a quick way to do this. And don’t forget, this can be used for other entities including threat intel indicators, so if you have domains, IPs or hashes that you want to suppress, this is a quick and easy way to do that!

0 replies

Be the first to reply!