Automating Phishing Email Triage with Microsoft Security Copilot

Automating Phishing Email Triage with Microsoft Security Copilot

This post was originally published on this site.


This blog details automating phishing email triage using Azure Logic Apps, Azure Function Apps, and Microsoft Security Copilot. Deployable in under 10 minutes, this solution primarily analyzes email intent without relying on traditional indicators of compromise, accurately classifying benign/junk, suspicious, and phishing emails. Benefits include reducing manual workload, improved threat detection, and (optional) integration seamlessly with Microsoft Sentinel – enabling analysts to see Security Copilot analysis within the incident itself. 

Designed for flexibility and control, this Logic App is a customizable solution that can be self-deployed from GitHub. It helps automate phishing response at scale without requiring deep coding expertise, making it ideal for teams that prefer a more configurable approach and want to tailor workflows to their environment. The solution streamlines response and significantly reduces manual effort.

Access the full solution on the Security Copilot Github:
GitHub – UserReportedPhishing Solution.

For teams looking for a more sophisticated, fully integrated experience, the Security Copilot Phishing Triage Agent represents the next generation of phishing response. Natively embedded in Microsoft Defender, the agent autonomously triages phishing incidents with minimal setup. It uses advanced LLM-based reasoning to resolve false alarms, enabling analysts to stay focused on real threats. The agent offers step-by-step decision transparency and continuously learns from user feedback. Read the official announcement here.

Introduction: Phishing Challenges Continue to Evolve

Phishing continues to evolve in both scale and sophistication, but a growing challenge for defenders isn’t just stopping phishing, it’s scaling response. Thanks to tools like Outlook’s “Report Phishing” button and increased user awareness, organizations are now flooded with user-reported emails, many of which are ambiguous or benign. This has created a paradox: better detection by users has overwhelmed SOC teams, turning email triage into a manual, rotational task dreaded for its repetitiveness and time cost, often taking over 25 minutes per email to review.

Our solution addresses that problem, by automating the triage of user-reported phishing through AI-driven intent analysis. It’s not built to replace your secure email gateways or Microsoft Defender for Office 365; those tools have already done their job. This system assumes the email:

  • Slipped past existing filters,
  • Was suspicious enough for a user to escalate,
  • Lacks typical IOCs like malicious domains or attachments.

As a former attacker, I spent years crafting high-quality phishing emails to penetrate the defenses of major banks. Effective phishing doesn’t rely on obvious IOCs like malicious domains, URLs, or attachments… the infrastructure often appears clean. The danger lies in the intent. This is where Security Copilot’s LLM-based reasoning is critical, analyzing structure, context, tone, and seasonal pretexts to determine whether an email is phishing, suspicious, spam, or legitimate.

What makes this novel is that it’s the first solution built specifically for the “last mile” of phishing defense, where human suspicion meets automation, and intent is the only signal left to analyze. It transforms noisy inboxes into structured intelligence and empowers analysts to focus only on what truly matters.

Solution Overview: How the Logic App Solution Works (and Why It’s Different)

Core Components:

  • Azure Logic Apps: Orchestrates the entire workflow, from ingestion to analysis, and 100% customizable.
  • Azure Function Apps: Parses and normalizes email data for efficient AI consumption.
  • Microsoft Security Copilot: Performs sophisticated AI-based phishing analysis by understanding email intent and tactics, rather than relying exclusively on predefined malicious indicators.

Key Benefits:

  • Rapid Analysis: Processes phishing alerts and, in minutes, delivers comprehensive reports that empower analysts to make faster, more informed triage decisions – compared to manual reviews that can take up to 30 minutes. And, unlike analysts, Security Copilot requires zero sleep! 
  • AI-driven Insights: LLM-based analysis is leveraged to generate clear explanations of classifications by assessing behavioral and contextual signals like urgency, seasonal threats, Business Email Compromise (BEC), subtle language clues, and otherwise sophisticated techniques. Most importantly, it identifies benign emails, which are often the bulk of reported emails.
  • Detailed, Actionable Reports: Generates clear, human-readable HTML reports summarizing threats and recommendations for analyst review.
  • Robust Attachment Parsing: Automatically examines attachments like PDFs and Excel documents for malicious content or contextual inconsistencies.
  • Integrated with Microsoft Sentinel: Optional integration with Sentinel ensures central incident tracking and comprehensive threat management. Analysis is attached directly to the incident, saving analysts more time.
  • Customization: Add, move, or replace any element of the Logic App or prompt to fit your specific workflows.
Deployment Guide: Quick, Secure, and Reliable Setup

The solution provides Azure Resource Manager (ARM) templates for rapid deployment:

Prerequisites:

  • Azure Subscription with Contributor access to a resource group.
  • Microsoft Security Copilot enabled.
  • Dedicated Office 365 shared mailbox (e.g., phishing@yourdomain.com) with Mailbox.Read.Shared permissions.
  • (Optional) Microsoft Sentinel workspace.

Refer to the up to date deployment instructions on the Security Copilot GitHub page.

Technical Architecture & Workflow:

The automated workflow operates as follows:

Email Ingestion:

  • Monitors the shared mailbox via Office 365 connector.
  • Triggers on new email arrivals every 3 minutes.
  • Assumes that the reported email has arrived as an attachment to a “carrier” email.

Determine if the Email Came from Defender/Sentinel:

If the email came from Defender, it would have a prepended subject of “Phishing”, if not, it takes the “False” branch. Change as necessary.

Initial Email Processing:

  • Exports raw email content from the shared mailbox.
  • Determines if .msg or .eml attachments are in binary format and converts if necessary.

Email Parsing via Azure Function App:

  • Extracts data from email content and attachments (URLs, sender info, email body, etc.) and returns a JSON structure.
  • Prepares clean JSON data for AI analysis.
  • This step is required to “prep” the data for LLM analysis due to token limits.
  • Click on the “Parse Email” block to see the output of the Function App for any troubleshooting. You’ll also notice a number of JSON keys that are not used but provided for flexibility.

Security Copilot Advanced AI Reasoning:

  • Analyzes email content using a comprehensive prompt that evaluates behavioral and seasonal patterns, BEC indicators, attachment context, and social engineering signals.
  • Scores cumulative risk based on structured heuristics without relying solely on known malicious indicators.
  • Returns validated JSON output (some customers are parsing this JSON and performing other action).
  • This is where you would customize the prompt, should you need to add some of your own organizational situations if the Logic App needs to be tuned:

JSON Normalization & Error Handling:

  • A “normalization” Azure Function ensures output matches the expected JSON schema.
  • Sometimes LLMs will stray from a strict output structure, this aims to solve that problem.
  • If you add or remove anything from the Parse Email code that alters the structure of the JSON, this and the next block will need to be updated to match your new structure.

Detailed HTML Reporting:

  • Generates a detailed HTML report summarizing AI findings, indicators, and recommended actions.
  • Reports are emailed directly to SOC team distribution lists or ticketing systems.

Optional Sentinel Integration:

Adds the reasoning & output from Security Copilot directly to the incident comments. This is the ideal location for output since the analyst is already in the security.microsoft.com portal. It waits up to 15 minutes for logs to appear, in situations where the user reports before an incident is created.

The solution works pretty well out of the box but may require some tuning, give it a test. Here are some examples of the type of Security Copilot reasoning.

Benign email detection: 

 

Example of phishing email detection:

 

 

More sophisticated phishing with subtle clues:

 

 

 

Enhanced Technical Details & Clarifications

Attachment Processing:

  • When multiple email attachments are detected, the Logic App processes each binary-format email sequentially.
  • If PDF or Excel attachments are detected, they are parsed for content and are evaluated appropriately for content and intent.

Security Copilot Reliability:

  • The Security Copilot Logic App API call uses an extensive retry policy (10 retries at 10-minute intervals) to ensure reliable AI analysis despite intermittent service latency.
  • If you run out of SCUs in an hour, it will pause until they are refreshed and continue.

Sentinel Integration Reliability:

  • Acknowledges inherent Sentinel logging delays (up to 15 minutes).
  • Implements retry logic and explicit manual alerting for unmatched incidents, if the analysis runs before the incident is created.

Security Best Practices:

  • Compare the Function & Logic App to your company security policies to ensure compliance.
  • Credentials, API keys, and sensitive details utilize Azure Managed Identities or secure API connections. No secrets are stored in plaintext.
  • Azure Function Apps perform only safe parsing operations; attachments and content are never executed or opened insecurely.

Be sure to check out how the Microsoft Defender for Office team is improving detection capabilities as well Microsoft Defender for Office 365’s Language AI for Phish: Enhancing Email Security | Microsoft Community Hub.

Automating Phishing Email Triage with Microsoft Security Copilot

Using parameterized functions with KQL-based custom plugins in Microsoft Security Copilot

This post was originally published on this site.


 

 

 

In this blog, I will walk through how you can build functions based on a Microsoft Sentinel Log Analytics workspace for use in custom KQL-based plugins for Security Copilot. The same approach can be used for Azure Data Explorer and Defender XDR, so long as you follow the specific guidance for either platform. A link to those steps is provided in the Additional Resources section at the end of this blog.

But first, it’s helpful to clarify what parameterized functions are and why they are important in the context of Security Copilot KQL-based plugins. Parameterized functions accept input details (variables) such as lookback periods or entities, allowing you to dynamically alter parts of a query without rewriting the entire logic

Parameterized functions are important in the context of Security Copilot plugins because of:

  1. Dynamic prompt completion:
    Security Copilot plugins often accept user input (e.g., usernames, time ranges, IPs). Parameterized functions allow these inputs to be consistently injected into KQL queries without rebuilding query logic.
  2. Plugin reusability:
    By using parameters, a single function can serve multiple investigation scenarios (e.g., checking sign-ins, data access, or alerts for any user or timeframe) instead of hardcoding different versions.
  3. Maintainability and modularity:
    Parameterized functions centralize query logic, making it easier to update or enhance without modifying every instance across the plugin spec. To modify the logic, just edit the function in Log Analytics, test it then save it- without needing to change the plugin at all or re-upload it into Security Copilot. It also significantly reduces the need to ensure that the query part of the YAML is perfectly indented and tabbed as is required by the Open API specification, you only need to worry about formatting a single line vs several-potentially hundreds.
  4. Validation:
    Separating query logic from input parameters improves query reliability by avoiding the possibility of malformed queries. No matter what the input is, it’s treated as a value, not as part of the query logic.
  5. Plugin Spec mapping:
    OpenAPI-based Security Copilot plugins can map user-provided inputs directly to function parameters, making the interaction between user intent and query execution seamless.
Practical example

In this case, we have a 139-line KQL query that we will reduce to exactly one line that goes into the KQL plugin. In other cases, this number could be even higher.  Without using functions, this entire query would have to form part of the plugin

Note: The rest of this blog assumes you are familiar with KQL custom plugins-how they work and how to upload them into Security Copilot.

 

CloudAppEvents | where RawEventData.TargetDomain has_any ( ‘grok.com’, ‘x.ai’, ‘mistral.ai’, ‘cohere.ai’, ‘perplexity.ai’, ‘huggingface.co’, ‘adventureai.gg’, ‘ai.google/discover/palm2’, ‘ai.meta.com/llama’, ‘ai2006.io’, ‘aibuddy.chat’, ‘aidungeon.io’, ‘aigcdeep.com’, ‘ai-ghostwriter.com’, ‘aiisajoke.com’, ‘ailessonplan.com’, ‘aipoemgenerator.org’, ‘aissistify.com’, ‘ai-writer.com’, ‘aiwritingpal.com’, ‘akeeva.co’, ‘aleph-alpha.com/luminous’, ‘alphacode.deepmind.com’, ‘analogenie.com’, ‘anthropic.com/index/claude-2’, ‘anthropic.com/index/introducing-claude’, ‘anyword.com’, ‘app.getmerlin.in’, ‘app.inferkit.com’, ‘app.longshot.ai’, ‘app.neuro-flash.com’, ‘applaime.com’, ‘articlefiesta.com’, ‘articleforge.com’, ‘askbrian.ai’, ‘aws.amazon.com/bedrock/titan’, ‘azure.microsoft.com/en-us/products/ai-services/openai-service’, ‘bard.google.com’, ‘beacons.ai/linea_builds’, ‘bearly.ai’, ‘beatoven.ai’, ‘beautiful.ai’, ‘beewriter.com’, ‘bettersynonyms.com’, ‘blenderbot.ai’, ‘bomml.ai’, ‘bots.miku.gg’, ‘browsegpt.ai’, ‘bulkgpt.ai’, ‘buster.ai’, ‘censusgpt.com’, ‘chai-research.com’, ‘character.ai’, ‘charley.ai’, ‘charshift.com’, ‘chat.lmsys.org’, ‘chat.mymap.ai’, ‘chatbase.co’, ‘chatbotgen.com’, ‘chatgpt.com’, ‘chatgptdemo.net’, ‘chatgptduo.com’, ‘chatgptspanish.org’, ‘chatpdf.com’, ‘chattab.app’, ‘claid.ai’, ‘claralabs.com’, ‘claude.ai/login’, ‘clipdrop.co/stable-diffusion’, ‘cmdj.app’, ‘codesnippets.ai’, ‘cohere.com’, ‘cohesive.so’, ‘compose.ai’, ‘contentbot.ai’, ‘contentvillain.com’, ‘copy.ai’, ‘copymatic.ai’, ‘copymonkey.ai’, ‘copysmith.ai’, ‘copyter.com’, ‘coursebox.ai’, ‘coverler.com’, ‘craftly.ai’, ‘crammer.app’, ‘creaitor.ai’, ‘dante-ai.com’, ‘databricks.com’, ‘deepai.org’, ‘deep-image.ai’, ‘deepreview.eu’, ‘descrii.tech’, ‘designs.ai’, ‘docgpt.ai’, ‘dreamily.ai’, ‘editgpt.app’, ‘edwardbot.com’, ‘eilla.ai’, ‘elai.io’, ‘elephas.app’, ‘eleuther.ai’, ‘essayailab.com’, ‘essay-builder.ai’, ‘essaygrader.ai’, ‘essaypal.ai’, ‘falconllm.tii.ae’, ‘finechat.ai’, ‘finito.ai’, ‘fireflies.ai’, ‘firefly.adobe.com’, ‘firetexts.co’, ‘flowgpt.com’, ‘flowrite.com’, ‘forethought.ai’, ‘formwise.ai’, ‘frase.io’, ‘freedomgpt.com’, ‘gajix.com’, ‘gemini.google.com’, ‘genei.io’, ‘generatorxyz.com’, ‘getchunky.io’, ‘getgptapi.com’, ‘getliner.com’, ‘getsmartgpt.com’, ‘getvoila.ai’, ‘gista.co’, ‘github.com/features/copilot’, ‘giti.ai’, ‘gizzmo.ai’, ‘glasp.co’, ‘gliglish.com’, ‘godinabox.co’, ‘gozen.io’, ‘gpt.h2o.ai’, ‘gpt3demo.com’, ‘gpt4all.io’, ‘gpt-4chan+)’, ‘gpt6.ai’, ‘gptassistant.app’, ‘gptfy.co’, ‘gptgame.app’, ‘gptgo.ai’, ‘gptkit.ai’, ‘gpt-persona.com’, ‘gpt-ppt.neftup.app’, ‘gptzero.me’, ‘grammarly.com’, ‘hal9.com’, ‘headlime.com’, ‘heimdallapp.org’, ‘helperai.info’, ‘heygen.com’, ‘heygpt.chat’, ‘hippocraticai.com’, ‘huggingface.co/spaces/tiiuae/falcon-180b-demo’, ‘humanpal.io’, ‘hypotenuse.ai’, ‘ichatwithgpt.com’, ‘ideasai.com’, ‘ingestai.io’, ‘inkforall.com’, ‘inputai.com/chat/gpt-4’, ‘instantanswers.xyz’, ‘instatext.io’, ‘iris.ai’, ‘jasper.ai’, ‘jigso.io’, ‘kafkai.com’, ‘kibo.vercel.app’, ‘kloud.chat’, ‘koala.sh’, ‘krater.ai’, ‘lamini.ai’, ‘langchain.com’, ‘laragpt.com’, ‘learn.xyz’, ‘learnitive.com’, ‘learnt.ai’, ‘letsenhance.io’, ‘letsrevive.app’, ‘lexalytics.com’, ‘lgresearch.ai’, ‘linke.ai’, ‘localbot.ai’, ‘luis.ai’, ‘lumen5.com’, ‘machinetranslation.com’, ‘magicstudio.com’, ‘magisto.com’, ‘mailshake.com/ai-email-writer’, ‘markcopy.ai’, ‘meetmaya.world’, ‘merlin.foyer.work’, ‘mieux.ai’, ‘mightygpt.com’, ‘mosaicml.com’, ‘murf.ai’, ‘myaiteam.com’, ‘mygptwizard.com’, ‘narakeet.com’, ‘nat.dev’, ‘nbox.ai’, ‘netus.ai’, ‘neural.love’, ‘neuraltext.com’, ‘newswriter.ai’, ‘nextbrain.ai’, ‘noluai.com’, ‘notion.so’, ‘novelai.net’, ‘numind.ai’, ‘ocoya.com’, ‘ollama.ai’, ‘openai.com’, ‘ora.ai’, ‘otterwriter.com’, ‘outwrite.com’, ‘pagelines.com’, ‘parallelgpt.ai’, ‘peppercontent.io’, ‘perplexity.ai’, ‘personal.ai’, ‘phind.com’, ‘phrasee.co’, ‘play.ht’, ‘poe.com’, ‘predis.ai’, ‘premai.io’, ‘preppally.com’, ‘presentationgpt.com’, ‘privatellm.app’, ‘projectdecember.net’, ‘promptclub.ai’, ‘promptfolder.com’, ‘promptitude.io’, ‘qopywriter.ai’, ‘quickchat.ai/emerson’, ‘quillbot.com’, ‘rawshorts.com’, ‘read.ai’, ‘rebecc.ai’, ‘refraction.dev’, ‘regem.in/ai-writer’, ‘regie.ai’, ‘regisai.com’, ‘relevanceai.com’, ‘replika.com’, ‘replit.com’, ‘resemble.ai’, ‘resumerevival.xyz’, ‘riku.ai’, ‘rizzai.com’, ‘roamaround.app’, ‘rovioai.com’, ‘rytr.me’, ‘saga.so’, ‘sapling.ai’, ‘scribbyo.com’, ‘seowriting.ai’, ‘shakespearetoolbar.com’, ‘shortlyai.com’, ‘simpleshow.com’, ‘sitegpt.ai’, ‘smartwriter.ai’, ‘sonantic.io’, ‘soofy.io’, ‘soundful.com’, ‘speechify.com’, ‘splice.com’, ‘stability.ai’, ‘stableaudio.com’, ‘starryai.com’, ‘stealthgpt.ai’, ‘steve.ai’, ‘stork.ai’, ‘storyd.ai’, ‘storyscapeai.app’, ‘storytailor.ai’, ‘streamlit.io/generative-ai’, ‘summari.com’, ‘synesthesia.io’, ‘tabnine.com’, ‘talkai.info’, ‘talkpal.ai’, ‘talktowalle.com’, ‘team-gpt.com’, ‘tethered.dev’, ‘texta.ai’, ‘textcortex.com’, ‘textsynth.com’, ‘thirdai.com/pocketllm’, ‘threadcreator.com’, ‘thundercontent.com’, ‘tldrthis.com’, ‘tome.app’, ‘toolsaday.com/writing/text-genie’, ‘to-teach.ai’, ‘tutorai.me’, ‘tweetyai.com’, ‘twoslash.ai’, ‘typeright.com’, ‘typli.ai’, ‘uminal.com’, ‘unbounce.com/product/smart-copy’, ‘uniglobalcareers.com/cv-generator’, ‘usechat.ai’, ‘usemano.com’, ‘videomuse.app’, ‘vidext.app’, ‘virtualghostwriter.com’, ‘voicemod.net’, ‘warmer.ai’, ‘webllm.mlc.ai’, ‘wellsaidlabs.com’, ‘wepik.com’, ‘we-spots.com’, ‘wordplay.ai’, ‘wordtune.com’, ‘workflos.ai’, ‘woxo.tech’, ‘wpaibot.com’, ‘writecream.com’, ‘writefull.com’, ‘writegpt.ai’, ‘writeholo.com’, ‘writeme.ai’, ‘writer.com’, ‘writersbrew.app’, ‘writerx.co’, ‘writesonic.com’, ‘writesparkle.ai’, ‘writier.io’, ‘yarnit.app’, ‘zevbot.com’, ‘zomani.ai’ ) | extend sit = parse_json(tostring(RawEventData.SensitiveInfoTypeData)) | mv-expand sit | summarize Event_Count = count() by tostring(sit.SensitiveInfoTypeName), CountryCode, City, UserId = tostring(RawEventData.UserId), TargetDomain = tostring(RawEventData.TargetDomain), ActionType = tostring(RawEventData.ActionType), IPAddress = tostring(RawEventData.IPAddress), DeviceType = tostring(RawEventData.DeviceType), FileName = tostring(RawEventData.FileName), TimeBin = bin(TimeGenerated, 1h) | extend SensitivityScore = case(tostring(sit_SensitiveInfoTypeName) in~ (“U.S. Social Security Number (SSN)”, “Credit Card Number”, “EU Tax Identification Number (TIN)”,”Amazon S3 Client Secret Access Key”,”All Credential Types”), 90, tostring(sit_SensitiveInfoTypeName) in~ (“All Full names”), 40, tostring(sit_SensitiveInfoTypeName) in~ (“Project Obsidian”, “Phone Number”), 70, tostring(sit_SensitiveInfoTypeName) in~ (“IP”), 50,10 ) | join kind=leftouter ( IdentityInfo | where TimeGenerated > ago(lookback) | extend AccountUpn = tolower(AccountUPN) ) on $left.UserId == $right.AccountUpn | join kind=leftouter ( BehaviorAnalytics | where TimeGenerated > ago(lookback) | extend AccountUpn = tolower(UserPrincipalName) ) on $left.UserId == $right.AccountUpn //| where BlastRadius == “High” //| where RiskLevel == “High” | where Department == User_Dept | summarize arg_max(TimeGenerated, *) by sit_SensitiveInfoTypeName, CountryCode, City, UserId, TargetDomain, ActionType, IPAddress, DeviceType, FileName, TimeBin, Department, SensitivityScore | summarize sum(Event_Count) by sit_SensitiveInfoTypeName, CountryCode, City, UserId, Department, TargetDomain, ActionType, IPAddress, DeviceType, FileName, TimeBin, BlastRadius, RiskLevel, SourceDevice, SourceIPAddress, SensitivityScore

With parameterized functions, follow these steps to simplify the plugin that will be built based on the query above

  1. Define the variable/parameters upfront in the query (BEFORE creating the parameters in the UI). This will put the query in a “temporary” unusable state because the parameters will cause syntax problems in this state. However, since the plan is to run the query as a function this is ok

Fig. 1: Image showing partial query with the parameters to defined highlighted in red i.e. lookback and User_Dept

  1. Create the parameters in the Log Analytics UI

Fig 2. Screenshot showing how the function menu in the Log Analytics UI

Give the function a name and define the parameters exactly as they show up in the query in step 1 above. In this example, we are defining two parameters: lookback – to store the lookback period to be passed to the time filter and User_Dept to the user’s department.

Fig. 3. Function menu showing the two parameters defined in the function creation menu of Log Analytics

3. Test the query. Note the order of parameter definition in the UI. i.e. first the User_Dept THEN the lookback period. You can interchange them if you like but this will determine how you submit the query using the function. If the User_Dept parameter was defined first then it needs to come first when executing the function. See the below screenshot. Switching them will result in the wrong parameter being passed to the query and consequently 0 results will be returned.

Fig. 4: Sample run of the function with the parameters specified in the correct order

Effect of switched parameters:

Fig. 5: Sample function run with the functions switched to show effect of this situation

To edit the function, follow the steps below:

Navigate to the Logs menu for your Log Analytics workspace then select the function icon

 

Fig. 6: Partial view of the function being edited within the Log Analytics UI

Fig. 7: Image showing how to select the code button in the function menu to edit the function code

Once satisfied with the query and function, build your spec file for the Security Copilot plugin. Note the parameter definition and usage in the sections highlighted in red below

Fig. 8: Partial view of the YAML plugin showing the encapsulation of the 139 lines of KWL into a single one

And that’s it, from 139 unwieldy KQL lines to one very manageable one! You are welcome 😊

Let’s now put it through its paces once uploaded into Security Copilot. We start by executing the plugin using its default settings via the direct skill invocation method. We see indeed that the prompt returns results based on the default values passed as parameters to the function:

Fig. 9: View of Secuity Copilot landing page showing an example of direct skill execution of the created pluginFig. 10: Sample output showing records of users from the Sales department

Next, we still use direct skill invocation, but this time specify our own parameters:

Fig. 11: Direct skill invocation example but with specified parameters-Department, and lookback periodFig 12: Prompt run showing the output corresponding to the selections of the previous direct skill invocation prompt

Lastly, we test it out with a natural language prompt:

Fig 13: Security Copilot prompt bar showing example of natural language prompt seeking events related to users in the Human Resources departmentFig 14: Output from previous natural language prompt focused on users from the HR department

Tip: The function does not execute successfully if the default summarize function is used without creating a variable i.e. If the summarize count() command is used in your query, it results in a system-defined output variable named count_. To bypass this issue, ensure to use a user-defined variable such as Event_Count as shown in line 77 below:

Fig. 15: Highlighting the creation of a variable to store results from the summarize count() command

Conclusion

In conclusion, leveraging parameterized functions within KQL-based custom plugins in Microsoft Security Copilot can significantly streamline your data querying and analysis capabilities. By encapsulating reusable logic, improving query efficiency, and ensuring maintainability, these functions provide an efficient approach for tapping into data stored across Microsoft Sentinel, Defender XDR and Azure Data Explorer clusters. Start integrating parameterized functions into your KQL-based Security Copilot plugins today and let us have your feedback.

Additional Resources

Using parameterized functions in Microsoft Defender XDR

Using parameterized functions with Azure Data Explorer

Functions in Azure Monitor log queries – Azure Monitor | Microsoft Learn

Kusto Query Language (KQL) plugins in Microsoft Security Copilot | Microsoft Learn

Harnessing the power of KQL Plugins for enhanced security insights with Copilot for Security | Microsoft Community Hub