Detecting Unauthorized or Shadow AI Tools in our Environments

93 views
Skip to first unread message

minshad

unread,
May 13, 2026, 1:13:33 AM (10 days ago) May 13
to Wazuh | Mailing List

Hello Wazuh Community,

We are currently exploring ways to detect and monitor unauthorized or “Shadow AI” tool usage within our environment (for example: unsanctioned AI assistants, browser-based AI services, local AI models, AI-related applications, or API usage outside approved channels).

We would like to understand whether anyone in the community has already implemented detection use cases for this using Wazuh.

Some areas we are particularly interested in:

  • Detecting installation or execution of AI-related applications
  • Monitoring browser access to public AI platforms
  • Identifying API calls to AI providers
  • Endpoint telemetry or Sysmon rules for AI tooling
  • Detecting local LLM runtimes or GPU-intensive AI processes
  • Any custom Wazuh rules, decoders, or integrations already in use

If anyone has experience implementing this, or can share detection strategies, sample rules, dashboards, or best practices, it would be greatly appreciated.

Bony V John

unread,
May 13, 2026, 1:35:35 AM (10 days ago) May 13
to Wazuh | Mailing List
Hi,

Please allow me some time, I'm working on this and will get back to you with an update as soon as possible

Bony V John

unread,
May 13, 2026, 5:24:08 AM (10 days ago) May 13
to Wazuh | Mailing List

Hi,

Based on your requirement, I tested these use cases on my end, and they are working properly. You can follow the below steps to achieve this.

Screenshot 2026-05-13 141349.png

For detecting AI applications installed on endpoints or AI-related processes running on endpoints, I used custom scripts and rules to trigger alerts.

By default, the Wazuh Syscollector module monitors installed software packages and running processes on the endpoint. You can view these details in the IT Hygiene dashboard.

For AI application detection, I created a custom Python script that queries the wazuh-states-inventory-packages-* index. If an AI-related application is detected, the script writes a JSON log into /var/log/llm_process.log on the Wazuh manager. The script also stores previously detected packages in a local JSON database file to avoid repeatedly reporting the same packages.

Similarly, for process monitoring, the script queries the wazuh-states-inventory-processes-* index. When an LLM-related process is detected, it writes the event into the same log file in JSON format.

To configure this:

Create the script on the Wazuh manager server:

vi /var/ossec/integrations/llm_process_monitor.py

Copy and paste the Python script into the file.

Update the following values inside the script:

INDEXER_URL - Your Wazuh indexer IP

USERNAME and PASSWORD - Wazuh indexer credentials

If you want to monitor additional AI processes, add them into the LLM_PROCESS_KEYWORDS block.

If you want to add more AI applications, update the AI_PACKAGE_KEYWORDS block.

Then update the permissions:

chmod +x /var/ossec/integrations/llm_process_monitor.py

After that, configure the script to run every 5 minutes:

crontab -e

Add the following line:

*/5 * * * * /usr/bin/python3 /var/ossec/integrations/llm_process_monitor.py >/dev/null 2>&1

You can adjust the execution interval based on your requirement.

Then add the following configuration into the Wazuh manager ossec.conf file:

<localfile>
  <log_format>json</log_format>
  <location>/var/log/llm_process.log</location>
</localfile>

Save the configuration and restart the Wazuh manager:

systemctl restart wazuh-manager

Then add the following custom rules to trigger alerts for AI application and AI process detection:

<group name="llm,local_ai,">

  <rule id="110500" level="10">
    <decoded_as>json</decoded_as>
    <field name="event.kind">^alert$</field>
    <field name="event.category">^shadow_ai$</field>
    <field name="event.type">^process$</field>
    <field name="event.action">^detected$</field>
    <description>Shadow AI: Local LLM process detected on endpoint $(agent.name): $(process.name)</description>
    <group>shadow_ai,local_llm,llm_process,</group>
  </rule>

  <rule id="110510" level="10">
    <decoded_as>json</decoded_as>
    <field name="event.kind">^alert$</field>
    <field name="event.category">^shadow_ai$</field>
    <field name="event.type">^package$</field>
    <field name="event.action">^detected$</field>
    <description>Shadow AI: AI-related software detected on endpoint $(agent.name): $(package.name)</description>
    <group>shadow_ai,ai_package,ai_software,</group>
  </rule>

</group>

Save the rules and reload the Wazuh rule engine.

Then install an application listed in AI_PACKAGE_KEYWORDS or execute a process listed in LLM_PROCESS_KEYWORDS to trigger alerts.

Screenshot 2026-05-13 141423.png

Screenshot 2026-05-13 141435.png



For browser-based AI platform access detection, it is generally better to use firewall logs, DNS logs, or proxy logs if those are available in your environment.

In my case, I used another method because I did not have firewall or proxy visibility available.

On Windows endpoints, I used custom scripts to collect browser history from Google Chrome and Microsoft Edge. Then I configured the Wazuh agent to monitor those logs.

After that, I created custom rules to trigger alerts when users accessed AI platforms through the browser.

For browser history collection, I followed the guidance from the Wazuh integration repository for monitoring Chrome and Microsoft Edge history.

Then I used the following custom rule to detect access to AI platforms:

<group name="chrome_history">
    <rule id="110300" level="10">
    <decoded_as>json</decoded_as>

You can modify the above rule to include additional AI platforms as needed.

Screenshot 2026-05-13 141406.png

Please let me know if you face any issues.

llm_process_monitor.txt

minshad

unread,
May 13, 2026, 8:16:12 AM (10 days ago) May 13
to Wazuh | Mailing List
Hi,

Thankyou so much, I appreciate your effort and will get back to you if I am facing any issues.

minshad

unread,
May 15, 2026, 4:40:58 AM (8 days ago) May 15
to Wazuh | Mailing List

Hi,

I tested the provided Shadow AI detection approach in my environment using Wazuh 4.12.

I modified the Python script accordingly, and the script execution itself is working properly. The events are being written successfully into the configured log file (/var/log/llm_process.log), and during wazuh-logtest execution, the events are not matching the custom rules correctly.

I also simplified the rule for testing purposes as below:

<group name="shadow_ai_monitor,"> 
 <rule id="110500" level="10">
 <match>shadow_ai</match>
 <description>Shadow AI Detection Event</description> 
</rule> 
</group>

Even with simplified is not matching  wazuh-logtest validation.

Current observations:

  • Script execution is successful

  • JSON logs are getting written correctly

  • Wazuh manager restart completed successfully

  • Rules are loaded without syntax errors

The issues I am currently facing is:

  • Rule processing

  • Alert generation

Could someone please help verify whether additional configuration changes are required specifically for Wazuh 4.12 to make these alerts visible in the dashboard?

Thanks.

Screenshot 2026-05-15 115024.png
Screenshot 2026-05-15 115035.png

Bony V John

unread,
May 15, 2026, 6:47:58 AM (8 days ago) May 15
to Wazuh | Mailing List

Hi,

The issue is with the custom rule configuration. That is why the alert is not being triggered.

From the logtest screenshot, the event is being decoded by the default JSON decoder. However, your custom rule is not mapped to the JSON decoder, so the rule is not being evaluated properly for that event.

Your custom rule should look like this:

<group name="shadow_ai_monitor,"> 
   <rule id="110500" level="10">
     <decoded_as>json</decoded_as>
     <match>shadow_ai</match>
     <description>Shadow AI Detection Event</description> 
   </rule> 
</group>


In the above rule, the custom rule is mapped to the JSON decoder using:

<decoded_as>json</decoded_as>

So, when an event is decoded by the JSON decoder, this rule will also be evaluated. If the event matches the rule condition, it will trigger an alert.

You can refer to the Wazuh custom rules syntax documentation for more details.

minshad

unread,
May 18, 2026, 2:06:07 AM (5 days ago) May 18
to Wazuh | Mailing List

Hi,

First of all, thanks again for the earlier guidance provided in this thread regarding the Shadow AI detection approach using Wazuh Syscollector and custom integrations. The static detection model is now working in Wazuh 4.12 using package/process inventory monitoring and custom Python logic.

Currently, the implementation is based on:

  • package name matching,

  • process name matching,

  • keyword-based detection for known AI tools (ollama, lm studio, copilot, cursor, etc.).

While this works well for known applications, there are still challenges with:

  • false positives caused by generic package names,

  • partial keyword matches,

  • and especially detecting newly emerging AI tools that are not yet part of the keyword list.

The next area being explored is whether this can evolve into a more dynamic or behavior-based detection approach instead of relying mainly on static IOC matching.

The main objective is to identify and detect unauthorized AI/LLM-related applications being installed or actively used inside the environment, especially tools that are not officially approved.

For example:

  • detecting unknown AI/LLM applications being installed,

  • detecting local AI runtimes or inference tools,

  • identifying AI-assisted IDEs/plugins,

  • detecting unauthorized AI tools actively running on endpoints,

  • or identifying AI-related activity patterns that could indicate Shadow AI usage.

Wanted to ask whether anyone in the community has already explored something similar in Wazuh.

Also interested in understanding:

  1. Best ways to reduce false positives in this use case.

  2. Whether there are better approaches than package/process keyword matching.

  3. If any existing integrations/projects already address dynamic Shadow AI detection in Wazuh.

Would really appreciate any ideas, experiences, or architectural guidance from the community.

Thanks again!

Bony V John

unread,
May 19, 2026, 4:39:24 AM (4 days ago) May 19
to Wazuh | Mailing List

Hi,

Apologies for the late response. Glad to hear that it is working. As you mentioned, the current detection is based on hardcoded model names in custom rules and scripts.

If you want to make the LLM model names dynamic, then you need a source that can provide updated LLM model details to the rules and scripts.

I developed another Windows PowerShell script that runs periodically every hour and downloads LLM model details from Hugging Face to create a model list. The script then checks running processes, installed packages, and IDE plugins, and compares them with the feed list. When a match is detected, it writes the event into a log file. During the next scan, it will not report already detected packages, processes, or plugin details again for the next 6 hours.

For this, I used a custom script that runs every hour to perform the complete process. You can follow the below steps to configure it.

Run the below commands in Windows PowerShell as Administrator:

New-Item -ItemType Directory -Path "C:\WazuhLogs\LLM-Inventory-Monitor" -Force

Create the script file:

notepad C:\WazuhLogs\LLM-Inventory-Monitor\llm_inventory_monitor.ps1

Then add the script from the attached file.

This is a sample script that you can use as a reference to achieve a similar use case. You can further fine-tune the script based on your requirements and also change the feed URL if you want to use a different source for model details.

Then, on the Wazuh agent, add the below configuration to run the script every hour and monitor the log file:

<wodle name="command">
  <disabled>no</disabled>
  <interval>3600</interval>
  <command>powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\WazuhLogs\LLM-Inventory-Monitor\llm_inventory_monitor.ps1"</command>
  <run_on_start>yes</run_on_start>
  <ignore_output>no</ignore_output>
</wodle>

<localfile>
  <log_format>json</log_format>
  <location>C:\WazuhLogs\LLM-Inventory-Monitor\llm_inventory_events.json</location>
</localfile>

Then restart the Wazuh agent.

You can refer to the Wazuh wodle configuration and localfile monitoring documentation for more details.

Then add the below custom rules to trigger alerts on the dashboard:

<group name="windows,shadow_ai,llm_inventory,">

  <!-- Base rule for all logs generated by llm_inventory_monitor.ps1 -->
  <rule id="108900" level="1" noalert="1">
    <decoded_as>json</decoded_as>
    <field name="sai_log_source">^llm_inventory_monitor$</field>
    <field name="sai_detection_name">^runtime_llm_model_match$</field>
    <description>Shadow AI inventory monitor event detected</description>
  </rule>

  <!-- Installed LLM/AI package -->
  <rule id="108901" level="8">
    <if_sid>108900</if_sid>
    <field name="sai_asset_type">^llm_package$</field>
    <description>Shadow AI: LLM/AI package detected on $(sai_endpoint_name): $(sai_asset_name) $(sai_asset_version). Publisher: $(sai_asset_publisher). Matched: $(sai_detection_matched_keywords)</description>
    <group>shadow_ai,llm_package,shadow_ai_inventory,</group>
    <mitre>
      <id>T1204</id>
    </mitre>
  </rule>

  <!-- Running LLM/AI process -->
  <rule id="108902" level="10">
    <if_sid>108900</if_sid>
    <field name="sai_asset_type">^llm_process$</field>
    <description>Shadow AI: LLM/AI process running on $(sai_endpoint_name): $(sai_asset_name). User: $(sai_asset_user). Path: $(sai_asset_path). Matched: $(sai_detection_matched_keywords)</description>
    <group>shadow_ai,llm_process,shadow_ai_inventory,</group>
    <mitre>
      <id>T1059</id>
    </mitre>
  </rule>

  <!-- LLM/AI IDE plugin -->
  <rule id="108903" level="9">
    <if_sid>108900</if_sid>
    <field name="sai_asset_type">^llm_ide_plugin$</field>
    <description>Shadow AI: LLM/AI IDE plugin detected on $(sai_endpoint_name): $(sai_asset_name). IDE: $(sai_asset_source). User: $(sai_asset_user). Matched: $(sai_detection_matched_keywords)</description>
    <group>shadow_ai,llm_ide_plugin,shadow_ai_inventory,</group>
    <mitre>
      <id>T1059</id>
    </mitre>
  </rule>

  <!-- Local LLM model file/folder -->
  <rule id="108904" level="9">
    <if_sid>108900</if_sid>
    <field name="sai_asset_type">^llm_model$</field>
    <description>Shadow AI: Local LLM model detected on $(sai_endpoint_name): $(sai_asset_name). Source: $(sai_asset_source). User: $(sai_asset_user). Path: $(sai_asset_path). Matched: $(sai_detection_matched_keywords)</description>
    <group>shadow_ai,llm_model,shadow_ai_inventory,</group>
    <mitre>
      <id>T1105</id>
    </mitre>
  </rule>
 
</group>


Save the rules on the Wazuh manager and restart the manager service:

systemctl restart wazuh-manager

This is a different approach compared to the previous one. Here, we are collecting all the details directly from the endpoint itself and only sending positive match events to the Wazuh manager to trigger alerts.

In the case of browser history monitoring, you can consider a similar approach by updating the script. Another option is to use a CDB list that contains LLM model URLs and match the URL field with the CDB list to trigger alerts for LLM model access through browsers.

You can refer to the Wazuh CDB list documentation for more details.

llm_inventory_monitor.txt

minshad

unread,
May 20, 2026, 12:53:22 AM (3 days ago) May 20
to Wazuh | Mailing List
Hi,

Once again, thank you. Let me try this out, and if I face any issues, I’ll get back to you.

Reply all
Reply to author
Forward
0 new messages