
Hello and welcome to the first talk of Bides 2026. You're in theater 13. If you want to be in a different theater, this is your cue to go. I'd like to welcome everybody to our first talk. Uh and specifically, I'd like to welcome Gorov Singh and Dario Amiri from Google who will be telling us about detection at scale, abstracting detection intent. Welcome. >> Thank you. Hello bsides. My name is Dario Amiri. I'm a senior staff software engineer at Google. Uh I worked on the team that builds detection systems at Google for 7 years. First as a tech lead and later on as a manager. Our presentation today is about detection at scale. A topic that's
actually so vast it would probably take dozens of presentations to cover it exhaustively. So the focus of today's presentation is how abstracting detection intent is a useful tool for scaling threat detection coverage. >> Before we get started, uh I'd like to acknowledge that the subject matter we are presenting on today is based on the work of tens of people over many years. In particular, I'd like to highlight that what we built is the result of a very close and successful collaboration between software engineers and security engineers at Google's detection and response organization. Some of the most significant contributors are called out in this slide. And with that, I'll hand it over to Garav for the next session.
>> Right. Thank you, Dario. Um, hi, I'm Garov. Um, I work on the detection systems teams at Google, uh, working closely with security engineers and software engineers to detect and respond to information security threats. I've been on the team for almost a decade, first as an engineer and now as a manager. So today we're going to start with a background on what is detection to make sure we're on the same page. Uh, and then we're going to split the talk into two parts. How to capture detection intent and how to execute detection intent. uh and I want to call give a caveat that all the examples in this talk are for illustrative purposes only and they're not intended to be useful
detections or a reflection of what we do in practice. So with that let's get started on what is detection. So detection is the last line of defense. It's trying to detect bad events that happened that you didn't prevent. Uh and this can happen anywhere. can be malware on a machine. This can be unauthorized access to systems. This could be combining signals across multiple systems and infrastructure. And often there's a heristic about what your detection is and there's an acceptable rate of false positives. If you had a perfect detection to determine something is definitely bad, you would probably just prevent it in the first place. So why is this hard? Detection at scale involves thousands of detections um
constantly being created and updated. There'll be a specialization of rules where there people focused on the detection platform, people focused on developing rules, triaging alerts, investigating alerts and not everyone is an expert at everything and people have are better at some parts than others. This also means there are large teams of people across the globe where each detection is read, modified or triaged by many different people. And so it's important that the knowledge is not just in a single person's head. This is a thing that everyone can understand and improve. So what are some of the key constraints and trade-offs here? Uh first constraint is the trade-off between latency of when you detect something, how many false positives you
create and how complete the data is or if you're missing something. Uh so for example, if you say uh want to find if something is rare, if you say I saw this process, I think it's rare and you say that immediately when you see the process, you don't actually know if it's rare because you don't know if this is actually common. If you waited say another couple minutes or an hour, you might know that actually this happens all the time. This is just a software update and this is not actually rare. Uh and there's also another constraint of like how do you make sure you're not missing things. Um sometimes this tension is fundamental to
the detection like if you're looking whether something is rare. Sometimes this uh tension is just about the implementation choices you make in how you get there. The next key constraint is cost. There are two big things I want to call out. First is human time. The amount of time people are spending developing detections, dealing with alerts is not infinite. There is some limit imposed by your company. How much value it has like you as a company are not going to spend more money than you earn on security. So this is a limit. What the limit is is a trade-off, but it is a like key factor in this. And machine cost similarly, like if you want to do something where
you're storing a bunch of information or you're doing really expensive detections, there are some limits as how many machines you're able to use for that processing. The final constraint we're going to focus on is how maintainable and adaptable is your logic. uh if you have detection rules, is this a thing where you write it once but in order to modify it or make changes, it's as much work as you wrote it in the first place? Is this a thing where you can change over time? Uh detections, given that they're heristics, some of them will become less effective over time. Something that was bad will become a common practice that's not actually telling you anything anymore and
requires changes to keep it effective. And this brings us to uh one of the big things we want to focus on today of if you have a bunch of different detections and you have a bespoke implementation for each of them. This is a good way to get off the ground. Long-term this means that uh it more complexity for an organization though the more detections you have for each of them is bespoke. If you're able to have some sort of abstraction that will take more time to get off the ground but long term will be less complexity for an organization and our focus on is basically looking at this and saying how does this help an
organization scale to do detection. So now looking at expressing detection intent. When we say detection intent, we're thinking of uh basically how do you express what you mean with a detection. If you have a detection rule, you could break it down into say a combination of highle patterns where where the intent of what you're trying to do and you're trying to detect is separate from the implementation. This allows you to focus on only the details that matter. So what are these detection patterns? We're going to be dividing these into simple detection patterns of generally stateless processing like filtering some events, adding some information from complex detection processing where you don't have just a single event. You need
to do something stateful whether this is a correlating different events, aggregations or or something like that. And in determining these detection patterns, we had a few guiding principles. First, we wanted to look at like what is actually necessary. Look at what we have. Look at what detections are doing. What is the functionality they need and use that to determine what is the minimal set of uh patterns that we're finding and focus on making sure it's readable, making sure it's ready to change. So if it's if we can keep something simple where people can read it, understand what's going on and make changes but it still gets covers whatever they want to do. This makes it
much easier to both understand things, maintain things, make changes without exposing too much complexity to everyone. And so we split this up into three ways into three parts. The first part is capturing the intent some sort of user experience. We've been using a Go API for this. You could imagine this is a custom DSL or various other ways to express this. The next part is how do you represent this intent? We take this and then we turn this into like a protobuff or like as a structured representation of what you're trying to do. This makes it clear that the intent and like how you're expressing it are not tied to the implementation. Um, this is not really a necessary step, but it
is a step to force you to avoid taking shortcuts to make sure you're maintaining this abstraction. And the final step is what do you do about it? Once you have this intent, how do you execute it? Um, so for example, you could think of doing this in a query engine or like batch or streaming processing. Uh, and there are many options here. So we're going to now focus on the first two parts of these and then I'll come back to the execution. So, we're going to get started by looking at simple detection patterns. Uh, for all the patterns we're going to look at, um, there's going to be like three things we're looking at. First,
what is the pattern doing? What are we trying to do with the pattern? Second is go or pseudo code very closely inspired by go to fit on a slide that describes how you would actually write something like this uh and express this intent. And then the third is basically like a diagram showing the representation of this intent um of like what this might look like at a at that level. And the point I like we're trying to take away from this is we can take whatever this intent is and we can turn it into a form that's not that hard to understand. So looking at predicates, this is used to like filter events or select events.
Um and so this is both like looking at um something that's about scoping your detection rule. Like if your rule only cares about Windows, you want to filter to OS Windows or security logic, right? So you might want to say add a filter of does this user match the user on the device or something like that. And this is basically the core way you make decisions. Detection is about making decisions about like what is worth investigating or not. And this is one of the core primitives for that. And here we can see basically an example of how you might write that uh where you're taking executions and applying filters to it. The next pattern we're going to look at
is enrichments of if you have an event adding context. So as as an example, right, if you have an execution, you might want to know for this execution, is it malware? Like if you have the hash, you can look it up in virus total to get more information about the uh execution hash. And enrichment is useful for things which are not changing so much over time. If something is malware now, it's probably going to be malware an hour from now. Um it's probably going to be malware two days from now. But if something is changing all the time, um this may be less effective or or there may be surprises where you say, I'm getting
some context, 30 seconds later it changes, 30 seconds after that it changes, and then something like enrichment doesn't really um uh meet that. And so this is in contrast, we'll be looking at correlations, which sound similar, but uh are are with things that might vary over time. We'll get to that later. The last simple detection pattern we'll look at is essentially userdefined functions of take take an input call some function and go or or something like that kind of as an escape hatch of it's it's with some restrictions of it's it's you can't use side effects. You take your one input you can do something with it. Strictly speaking this is not necessary. Strictly speaking you would have an
abstraction which covered all this logic and you did not need this. um with more sophisticated predicates, more sophisticated data transformations. Uh but it is an escape hatch as some of that is not worth your time to build. Now we're going to go into uh complex detection patterns. These are ones where you need more than a single event. Uh and we're starting with correlation. Um so a correlation here is looking for two events that are uh happening at the same time uh or similar times right and there are a few variants here like one of this is you could think of they're happening near each other in time or they could be a sequence of one event followed by
another um and there are other variants of saying like you might be looking for something which doesn't exist. So these are kind of similar to enrichments if you think of it of you have one set of events for example file downloads and you want to know are there any executions nearby. Uh the the difference we're showing here is that like there's not just like an execution at all time for a file download like whether an execution happened happens some of the time and it there are like when it happens right like if it's you download a file and then execute it that might be interesting and might be a signal that you would want to look at. Um and the
difference also is which we'll get to later of like if you have data coming in with different times you can signal to the system you expect a correlation the relationship between the events matters and the system can think about if data is coming in late what should we do differently for the two of these. Um and so for example for like a correlation like this you would say you could be saying something like if you download a file and that same file path is executed within an hour that might be interesting. The next pattern we're going to look at is thresholds of is there a large volume of something happening like a user has more than 10 login attempts within an
hour. Um and similarly here you could say get login for each user. Do you see more than 10 in an hour? And this is again like not just like a single event but looking at like collectively across all the events you're processing. Do you see this related to thresholds uh is instead of looking at like a fixed number, you could be looking at what is abnormal. So you could say compute a baseline of what does it mean to be normal? How many times do we see a specific execution a specific execution hash executing per day, right? And we could be saying okay for this let's see what we see every day and create a baseline of that.
And then you could say take this and a second rule reads the baseline of like for for this execution for the hash what is the normal number we see. If we see an execution that is rare like we see it less than 10 times per day that might be interesting. This is probably not necessarily bad but it might be interesting and worth further investigation. Um, and the pattern, this is a pattern of just like looking at like what do you see on the fleet? What are what's going on in all the machines and using that to make decisions. And the last complex pattern we're looking at is clustering of let's suppose you have an alert of there's
malware on a host. looking at if there's one malware execution on a host or a thousand malware executions on the host, the things you're going to be doing are probably the same. And this is essentially saying uh managing human time for investigation. Is it worth investigating malware in the host a thousand times in a day? Or do you want to say for this host, let's investigate the malware once and maybe there's some complex investigation there, but then you're done. And if it happens again on another day, you might investigate it. But it it's essentially saying we're making a trade-off on how we are managing our investigative time to like pick a representative event and cluster as of that cluster of
detections. So now let's look at an example of what this might look together as you stitch this into detection. If you want to say detect malware executions, uh you might read executions like look at all the executions, check virus total on the hash to get information about them. Check to see if virus total thinks it's malware and then format it for a person to investigate it to make sure the context that they need is there and then create an alert. For more complex detection, you might want to do something which says if there are a lot of uh failed login attempts for a user that there's not a successful login attempt afterwards. So here you
might say take login split them into whether or not they were successful or not and then first use a threshold to see are there a lot of failed login attempts and if that's the case make sure it's not followed by a successful login attempt for that user within an hour. And so this is how you might express some something like that. And in terms of like a diagram expressing the same intent, right? You could say you're reading executions, splitting it into two branches, checking if there's a threshold, and then doing a correlation between those at the end. The fact that the read of the login is the same for both of them does is more just an optimization detail
from the system. But that's helpful in how we're thinking about how this processing is working. And so the key takeaways uh we want you to take away from this is that it's important to look at what patterns are people using, what patterns are showing up, and that this actually allows us to express detection intent, understand it, and it can be intuitive. Like it takes work to get there, but it's not like a uh impossible problem. And that focusing this intent on the business logic allows us to focus on like what really matters like what are the decisions we're making here. Um and this is the like business logic or decision decision logic. Um and with
that I'm going to hand it over to Dario to talk about execution.
Okay. This mic this mic is a little hot. All right. Thanks Gav. Um so uh thus far we've talked about how to express detection intent. This next section of the presentation dives a bit deeper into how we translate that intent into execution. So one of the guiding principles of our architecture is to have abstractions that separate detection intent from detection implementation. It is more complicated to build a system this way. However, over time, as the number of users and the volume of detection logic increases, it pays for itself in a few ways. First, by allowing users to focus on what patterns they're looking for in their detections, what we call the detection intent. And second,
by allowing developers to optimize the systems that execute that detection intent, what we call the detection implementation. and the focus of these next slides. Crucially, changes to detection implementation should not impact detection intent. This shields users from the cognitive load and impact of implementation decisions made by developers. This is an important advantage because there are many aspects of system implementation that can divert user focus away from increasing threat detection coverage. For example, optimizing the system to balance cost and latency or one of the many other trade-offs necessary to extract the best possible results from what's usually a limited set of tools, frameworks, infrastructure, and machine resources. There are always trade-offs to be made. Uh, and in fact, an optimal system is
not static. For example, at Google, migrations are a fact of life. So the optimal stack for building anything today is likely to change over time. Also, business priorities shift and so does the math on trade-offs. The appropriate balance between cost and latency today might not be appropriate tomorrow. Without a separation between detection intent and detection implementation, users are forced to deal with all these problems rather than focusing on growing detection logic and coverage. The example in these slides illustrates these principles. As Gorov covered earlier, our systems translate the rules and UDFs written by users in Go the detection intent into a framework agnostic format. Then layers of orchestration logic analyze that and determine how to best execute the
detection depending upon various aspects of processing and data necessary. A single detection can consist of one or more rules. Each rule can map to one or more stages of processing. And the orchestrator assigns each stage of processing to one or more underlying systems. The diagram on the left represents detection intent, what we want the detection to do, what patterns we're looking for. It tells us the data we want to read that we want to perform some filtering to remove uninteresting events that we want to correlate this data with some other data and look for some statistical patterns. Importantly, it says nothing about how to specific accomp specifically accomplish any of this at a systems level. There are in
fact many ways to implement the intent expressed in the diagram. The diagram on the right represents one potential way to implement the detection. It provides detail on the type of infrastructure and processing used to compute the results. Logs provided through PubSub are filtered and warehoused using stream processing. Then batch processing is used to perform correlation. And finally, a query engine is used to determine statistical rarity. The reasons for assigning processings processing excuse me to different system can vary right. Sometimes this is due to framework constraints. It may be easier or more cost-effective or more convenient to implement detection logic using a particular framework. Sometimes it's due to the evolution of infrastructure. You know as I talked
about earlier the infrastructure evolves over time. Migrations are a fact of life. Sometimes this is due to foundational issues. For example, determining the rarity of events requires searching through very large data sets over long time frames for similar events. This is generally more efficiently accomplished with queries over indexed fields. In this next slide, we'll cover some of the examples of how the separation between detection intent and implementation reduces cognitive load for the user. First, we'll cover how it reduces the cognitive load of thinking about time. Time is complicated. Time is especially complicated when you're building event processing systems. At the lowest levels, you have to think about the relationship between event time, when things happen, and processing
time, when systems receive that information. Initially, legacy detection systems at Google used much lower level abstractions that force users to think about time in both ways. That meant that users writing detection logic had to think about low-level details such as how to handle late arriving data. How to reconcile data between log sources with different latency characteristics. How to dduplicate data to reduce noise. The newer higher level abstractions were designed to reduce this cognitive load by allowing the user to express their detection logic in event time alone without having to worry about what's going on in processing time. A higher level abstraction also reduces the cognitive burden of figuring out how to correctly and optimally aggregate or
join data. For example, aggregation can be non-monotonic or monotonic. An example of non-monotonic aggregation is accurately counting the number of login attempts per hour. Whereas an example of monotonic aggregation is determining whether the number of login attempts has exceeded some threshold. Whereas we can optimize monotonic aggregations to return a result as soon as the events observed indicate a pattern match. Non-monotonic aggregations on the other hand require implementations that carefully balance correctness and latency. Specifically, if we don't wait long enough to ensure the aggregation has received all relevant inputs, the aggregation produces incorrect results. Whereas if we wait too long, latency may be unacceptably high. Sometimes satisfying business requirements means releasing an early result with a certain likelihood
of correcting it later. Once again, a higher level abstraction shields the user from having to worry about these details. In addition to shielding the user from cognitive overload, the abstraction also simplifies optimization. In a previous slide, we covered how users had to implement late data handling when writing detections. There were best practices for how to do this. However, every detection had essentially a bespoke implementation for handling late data. As a consequence, validating troubleshooting and optimizing late data handling required bespoke efforts. One example of how this can go badly is that a logic bug in late data handling can result in false negatives. Essentially returning no result when the intent of the detection implies there should be some.
Upleveling the abstraction allows us to ensure a single consistent correct and optimized implementation of late data handling across all detections. This also makes it easier to spot bugs and fix them. As we've seen, abstracting, detection, intent, and implementation is the lynch pin of our architecture. Coming back to the theme of balancing the abstraction, there is a spectrum of trade-offs between lower level and higher level abstraction. Lower level abstractions provide more flexibility and options for handling use cases out of the box. Detection logic expressed in lower level abstractions is generally complicated by lower level implementation detail and therefore typically less readable and harder to maintain. Users have more power to unblock themselves and also more ways to shoot themselves in the
foot. Higher level abstractions introduce constraints that limit how users can solve problems. Detection logic expressed in higher level abstractions is generally simpler, more concise, easier to read and maintain. Users have to work within a framework that provides safeguards. However, sometimes dealing with edge cases, navigating the constraints around those can slow the user down. To understand how this spectrum of trade-off relates to cyber security, we have to consider that threats are constantly evolving and multiplying. So organizations have to constantly increase and evolve their threat coverage. Superficially, the flexibility of lower levels abstractions is attractive and the constraints of higher level abstractions may seem like unnecessary friction. However, in the long term, security engineers will spend much more of their
time reading, understanding, and maintaining existing detection logic. They'll spend much more time doing that than writing new detection logic. Therefore, higher level abstractions are to an extent necessary for organizations to sustainably grow their threat coverage. But how to balance the abstraction is the question here. A key principle we applied was to be opinionated about the things that are difficult to do and get right and flexible about the things that are easy to do. So for example, our rule language requires that users express patterns in the data that they're looking for as a higher level declarative opinionated uh Go API. We did this because efficient and correct data processing and pattern matching is full of hard problems to
solve such as the ones presented in earlier slides. dealing with late arriving data, non-monotonic aggregation, optimizing joins for reasonable resource usage, etc., etc., etc. On the other hand, our rule language allows users to write userdefined functions in Go to express simple stateless logic such as mapping data from one structure or format to another. The kind of things that are easy enough to implement where the benefits of a higher level abstraction are probably not worth the costs. In userdefined functions, users can pretty much write any code they want with some important restrictions. They shouldn't access state directly or have side effects. Overall, this approach allows users to express simpler and safer detection logic with less constraints while still te steering them
towards our more opinionated declarative API to express detection logic that is hard to get right. Ideally, this frees the user from cognitive load, safeguards the system, and reduces the cost of adapting and optimizing over time. Generally speaking, providing escape hatches when the risk or impact of breaking things is low is a good way to balance abstractions. Finally, I should say that fine-tuning an abstraction takes time. Don't expect to achieve perfection on the first try. However, the abstraction always serves as an important organization tool to guide discussion and make decisions about separation of concerns. And with that, I'll open it up for questions.
>> All right. Thank you, gentlemen. If you have questions for our speakers, you can use Slido. You can access the Slido by going in your phone to besides.org. That's Quebec Nancy Alpha. Oh, shoot. November Alpha. Uh there'll be a link there to Slido. We are in theater 13 if you wanted to submit any questions through that. And we'll give folks uh a couple minutes to type in their questions while I pull up the questions on my iPad here. In the meantime, do I have anyone who wants to kick us off with a first question in person? Uh question back in the middle there. Yes.
just so I can repeat the question. uh how do you guys handle maintaining your predicate language and what dec what things you decide to implement with things you don't decide to implement is that a decent summary okay >> um I think there's a mix of using what is there so in many ways SQL is a predicate language it works pretty well so if it works use it sometimes there are limitations where we need to extend it or do other things and we balance that but I think It's generally looking at what is a good UX for people and what is easy to maintain and trying to balance those. Okay, next question. >> Yes, up on the right.
So the question was how do you determine alert cooldown and avoid things like stampeding alerts for large data sets. >> Um so I think I don't think that's a thing we covered. Uh there is we have additional tools looking at that as well. Uh it is a balance there between how do you like around managing people's time essentially of if you had a lot of alerts of the same type trying not to flood them like detecting them and deciding what to do about that. It is it is a heristic of looking at what you see adding some protections and creating a balance. Um and it it wasn't covered by this. >> Yeah. Yeah, I guess I'll just add it.
It's sort of like outside the scope of this uh but but you need tools for that, right? And a lot of it is just sort of like connecting the feedback from the people who are doing security operations like back into the system and the better the user experience for doing that um the better a result you'll get. Okay, I have a question on Slido. Rule coverage affects endto-end detection quality. How can you enhance rule coverage?
Um, I guess it kind of depends on what's sort of like meant by like enhance like is this about like reducing falsing um or if this is about um I don't know just like writing more detections over time right uh if it's about sort of reducing falsing I think the thing there is you want to be able to have something where it's intuitive what your detections are doing and the cost of tuning them is low, right? Because you're just not going to get it right the first time. And so what you really want to be able to do is you need to be able to say, "Okay, well, I understand what it's doing and so I know
I can turn this knob or that knob to get a better result." Um, if this is about increasing detection coverage over time, then you know, obviously having something that's sort of like easy to use is better than having something that's difficult to use. Um, and something having something powerful to use can be great, but then if everyone is is using that power, then over time you have something that is really hard for people to understand. Um, so there's all kinds of trade-offs there, I guess I would say. I don't know, Gav, if you want to add anything to that. >> All right. I think I have a question here in the front. >> Yeah. So um as the attacker pattern
evolve uh do you have um feedback loop to retrain to update those patterns or is this a manual process? >> Just so I can repeat the question as attackers evolve how do you what kind of feedback mechanism do you have to update your rule sets? Uh so I think there's one of which is looking at like for the specific patterns and like updating the rules and I think you're pointing more at are is this list of patterns complete. Um I think the set of patterns we've seen changing over time does happen like we do find new patterns but it changes slowly like even there's new attacks or new vectors often times the things you're trying to detect fall into
the same type of patterns. Um and I would say the feedback loop is there's a lot of people in industry, people at Google doing research into what are the threats we're seeing and uh between those researchers, between security engineers and the software engineering teams, we closely collaborate and look at what's coming up are there how would we detect new things? Are there patterns or missing? Um and this is basically looking at that seeing what is changing most of the time. We are seeing the patterns are still the same patterns we want to detect, but there are new things we want to detect. There's new data we need to look at. There's new types of patterns. There's
new like things that might be bad or interesting to look at. And there's a lot more work in that area uh than there's a totally novel thing that we have not like we were not able to detect before and the patterns don't cover it. Maybe the only thing I I might add to that is that there is a little bit of a distinction between you know maybe what we in the industry call like uh patterns and what we're talking about which is more like event processing patterns right like a correlation is a type of event processing pattern like did this thing happen after this thing or did this thing happen after this thing and after that thing in sequence. um those
types of patterns are, you know, we we don't find as many new ones of those over time. Um but yeah, definitely different ways attackers are attacking us. Uh that happens a lot. And so there's a question of like, oh, can we use the same event processing patterns to represent those new attacker patterns, right? And generally we find that yeah, the event processing patterns, we don't need to add as much to them over time. All right, I have a question from the slidoho. Does separating intent allow you to apply these higher level abstracted detections to multiple incoming data sets? This would be in the vein of something like building a unified rule set. >> Yes, I guess you would
>> I mean the short answer is yes. uh like if you have a pattern and a lot of different sets of data and it's the same thing you can either do it both ways of saying this data is all the same kind of unifying the data and then processing it together you could say this logic is the same make copies for processing the different types of data if you have this pattern which applies for all of them it is easy to do that uh I think some of how you want to combine it ends up being as the person maintaining the detection what is easy to think about and so there's not a like correct answer. Both things are
supported. Okay. Uh question in the back. Yes. How has how have you been thinking about augmenting this with a support AI use cases skills that ability to move?
>> So the question was two-parter. The first part is have you uh looked at enabling AI skills or MCP or other kinds of AI integrations with this and also how have you looked at using this to shift left and do more simulation of these rule sets. >> Um those are great questions and uh I I don't know how much I can say about this. I I'll say that like there's a a lot of people looking at this right now and that's sort of like outside the scope of this talk. Um, the only thing I'd add to that is that I think Oh, I think they would agree that uh if they were here that in general like those
tools uh and automation in general works much better when you're working with very structured data uh and very structured logic um sort of garbage in garbage out. So, I'll probably just, you know, leave it at that. Um, but yes, there's a lot of uh there's a lot of people looking into that and who knows, maybe one day they'll be on the stage and give a talk about that. Uh, and it's designed to complement what we built uh with these systems. And I'll leave it at that. We have another Slido question. Were there any functions or primitives which turned out to be user favorites or exceptionally powerful that initially weren't seen as needed? Um, probably off the top of my head, uh,
I'm not I'm not sure. Um, but I think we definitely work with a lot of security engineers. The security engineers we work with are extremely opinionated about what they like, what they don't like. They give us a ton of feedback. Uh, they've written a bunch of the code of the API, right? Like they're they're contributors to what we're building. So um there's a lot of feedback there. We work very closely with the security engineers in in building it off the top of my head. Uh I don't remember details. I I'll just say that I think initially we kind of like underestimated the importance of enrichment and getting additional context into uh detections. um that ended up being a thing where we
ended up investing you know more and more time um especially around optimizing that. I'll I'll add a question of my own actually. Have you taken uh UDFs that are particularly popular and adopted those as first class citizens ever like things that are built into the framework? >> Um we have done some of that. I think most of it is looking at why people are doing things and then saying okay for for this UDF is there a way to turn into abstraction. Um more often it's looking at if we did it this as an abstraction would it make it easier for people to understand. Um, so more work we've put more work into making the UDFs cheaper
and like than we have to copy them and like translate them as usually the UDFs are still easy to understand what they're doing and putting it in the abstraction doesn't make it easier to understand. All right, thank you very much. That is all the time we have for questions. If you'd like to come down and speak with our speakers, they might be able to take some time with you. It's up to them. Uh so thank you very much to Garav and Dario. We really appreciate all your insights here and thank you all for coming to our first round of talks. I have some announcements as we get out of here, but I'll let you applaud for these
fine folks first.