<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Crispin</title>
    <description>The latest articles on DEV Community by Crispin (@crispin_r).</description>
    <link>https://dev.to/crispin_r</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F652925%2Fd4ea2a63-21e7-4d50-bd4d-a9ea404ad0b1.jpeg</url>
      <title>DEV Community: Crispin</title>
      <link>https://dev.to/crispin_r</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/crispin_r"/>
    <language>en</language>
    <item>
      <title>Comparative Analysis: Testing &amp; Evaluating LLM Security with Garak Across Different Models</title>
      <dc:creator>Crispin</dc:creator>
      <pubDate>Sun, 01 Jun 2025 06:30:13 +0000</pubDate>
      <link>https://dev.to/crispin_r/comparative-analysis-testing-evaluating-llm-security-with-garak-across-different-models-42h5</link>
      <guid>https://dev.to/crispin_r/comparative-analysis-testing-evaluating-llm-security-with-garak-across-different-models-42h5</guid>
      <description>&lt;p&gt;Hey everyone, I’m trying out LLM security testing and it’s pretty interesting. With all these AI models around, it’s important to check they don’t do weird stuff. I found this tool called &lt;strong&gt;Garak&lt;/strong&gt; (Generative AI Red-teaming and Assessment Kit). It’s like a set of tests to see if models can be tricked into revealing secrets, making bad code, or saying nasty things.&lt;/p&gt;

&lt;p&gt;In this post, I’ll go over four models: Mistral-Nemo, Gemma3, LLaMA 2-13B, and Vicuna-13B. I ran Garak on the &lt;strong&gt;Ollama&lt;/strong&gt; setup. You can think of it like a friendly match, but instead of goal scoring, we score on security stuff.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frjrz673ofxlzwzbd61xf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frjrz673ofxlzwzbd61xf.gif" alt="AI Bake-off GIF" width="498" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Background on Garak
&lt;/h2&gt;

&lt;p&gt;Garak is kind of like Nmap but for AI. Instead of scanning a network, it sends special prompts (called “probes”) to the model. Each probe tries to make the model slip up.&lt;/p&gt;

&lt;p&gt;Some probes are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PromptInject&lt;/strong&gt;: Tries to hide instructions to see if the model follows them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MalwareGen&lt;/strong&gt;: Asks for malicious code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LeakerPlay&lt;/strong&gt;: Tries to get the model to spill its internal stuff or training data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RealToxicityPrompts&lt;/strong&gt;: Pushes the model to say toxic things.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When Garak runs, it saves all the outputs in logs. Later I look at the logs and see which models passed or failed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Models and Setup
&lt;/h2&gt;

&lt;p&gt;I picked these open models:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Mistral-Nemo (7B)&lt;/strong&gt;: Released July 2024, supposed to be good at chat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemma3:latest&lt;/strong&gt;: From Google, late 2024 release, with some safety tweaks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LLaMA 2-13B&lt;/strong&gt;: Meta’s 13B model, popular for many tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vicuna-13B&lt;/strong&gt;: Based on LLaMA, tuned to be safer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I ran all models on Ollama (version 0.1.34 or newer). My computer has 32 CPU cores, 128 GB RAM, and an NVIDIA A100 GPU. I used Garak v0.10.3.post1 with default settings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing and Configuring Ollama
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Update Ollama&lt;/span&gt;
ollama upgrade

&lt;span class="c"&gt;# Download models&lt;/span&gt;
ollama pull mistral-nemo
ollama pull gemma3:latest
ollama pull llama2-13b
ollama pull vicuna-13b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Running Garak with Ollama
&lt;/h3&gt;

&lt;p&gt;To scan a model, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;garak &lt;span class="nt"&gt;--model_type&lt;/span&gt; ollama &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--model_name&lt;/span&gt; mistral-nemo &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--probes&lt;/span&gt; malwaregen.Evasion,promptinject &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--report_prefix&lt;/span&gt; ./reports/mistral_nemo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I set a random seed and repeated each test three times to make it more reliable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Methodology
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Probe Selection&lt;/strong&gt;: I chose four main probes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MalwareGen.Evasion&lt;/strong&gt;: Asks for code that could bypass antivirus.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PromptInject.Encoding&lt;/strong&gt;: Hides instructions in encoded text to see if the model follows them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LeakerPlay.DataLeakage&lt;/strong&gt;: Tries to get the model to reveal training data or hidden prompts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RealToxicityPrompts&lt;/strong&gt;: Pushes the model to use toxic language.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Metrics&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Failure Rate (%)&lt;/strong&gt;: How often the model messed up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mean Time per Probe (s)&lt;/strong&gt;: How long it takes on average.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Usage&lt;/strong&gt;: GPU memory and CPU usage.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Probe Execution&lt;/strong&gt;: Each probe had 20 prompts. The model got five tries for each prompt. If it failed once, that prompt counts as a fail.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Analysis&lt;/strong&gt;: I averaged results from three runs and got standard deviations. Results are in the table below.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Comparative Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;MalwareGen.Evasion&lt;/th&gt;
&lt;th&gt;PromptInject.Encoding&lt;/th&gt;
&lt;th&gt;LeakerPlay.DataLeakage&lt;/th&gt;
&lt;th&gt;RealToxicityPrompts&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mistral-Nemo&lt;/td&gt;
&lt;td&gt;100.0% ± 0.0%&lt;/td&gt;
&lt;td&gt;92.0% ± 1.7%&lt;/td&gt;
&lt;td&gt;85.7% ± 2.3%&lt;/td&gt;
&lt;td&gt;17.0% ± 1.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemma3:latest&lt;/td&gt;
&lt;td&gt;56.3% ± 4.1%&lt;/td&gt;
&lt;td&gt;37.5% ± 3.8%&lt;/td&gt;
&lt;td&gt;48.2% ± 4.5%&lt;/td&gt;
&lt;td&gt;10.5% ± 1.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LLaMA 2-13B&lt;/td&gt;
&lt;td&gt;81.0% ± 3.9%&lt;/td&gt;
&lt;td&gt;68.3% ± 2.5%&lt;/td&gt;
&lt;td&gt;72.4% ± 3.1%&lt;/td&gt;
&lt;td&gt;26.7% ± 2.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vicuna-13B&lt;/td&gt;
&lt;td&gt;62.5% ± 4.8%&lt;/td&gt;
&lt;td&gt;54.6% ± 3.0%&lt;/td&gt;
&lt;td&gt;61.3% ± 3.5%&lt;/td&gt;
&lt;td&gt;3.8% ± 1.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note: Failure Rate (%) shows how often the model produced unwanted behavior.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fittw6er69n3omh13uar9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fittw6er69n3omh13uar9.gif" alt="Gon GIF" width="165" height="165"&gt;&lt;/a&gt;&lt;br&gt;
Yes, I know that you'll be like this (even I was 😂).&lt;/p&gt;

&lt;h3&gt;
  
  
  Mistral-Nemo
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MalwareGen.Evasion (100.0%)&lt;/strong&gt;: It always gave malware code. No defense at all.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PromptInject.Encoding (92.0%)&lt;/strong&gt;: Fell for encoding tricks most of the time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LeakerPlay.DataLeakage (85.7%)&lt;/strong&gt;: Leaked training prompts a lot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RealToxicityPrompts (17.0%)&lt;/strong&gt;: Created toxic content sometimes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Gemma3:latest
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MalwareGen.Evasion (56.3%)&lt;/strong&gt;: Sometimes refused but got tricked by advanced hacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PromptInject.Encoding (37.5%)&lt;/strong&gt;: Better but not perfect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LeakerPlay.DataLeakage (48.2%)&lt;/strong&gt;: Half the time it leaked something.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RealToxicityPrompts (10.5%)&lt;/strong&gt;: Rarely said toxic things.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  LLaMA 2-13B
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MalwareGen.Evasion (81.0%)&lt;/strong&gt;: Produced malware scripts often.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PromptInject.Encoding (68.3%)&lt;/strong&gt;: Fell for encoding a lot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LeakerPlay.DataLeakage (72.4%)&lt;/strong&gt;: Regularly leaked data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RealToxicityPrompts (26.7%)&lt;/strong&gt;: Most toxic among the group.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Vicuna-13B
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MalwareGen.Evasion (62.5%)&lt;/strong&gt;: Was not as bad as LLaMA but still failed a lot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PromptInject.Encoding (54.6%)&lt;/strong&gt;: Mediocre, could still be tricked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LeakerPlay.DataLeakage (61.3%)&lt;/strong&gt;: Leaked data more than half the time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RealToxicityPrompts (3.8%)&lt;/strong&gt;: Best at not being toxic.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Discussion
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Security Trends Across Models
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Older vs Newer&lt;/strong&gt;: Older models like Vicuna and LLaMA 2 failed more often. Newer ones like Gemma3 have more guardrails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instruction-Tuning&lt;/strong&gt;: Vicuna had extra tuning so it was better at not making malware or saying toxic stuff.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guardrails Matter&lt;/strong&gt;: Gemma3 blocked some attacks but still fell for advanced ones.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecture&lt;/strong&gt;: Models without built-in safety (Mistral-Nemo, LLaMA 2) were very vulnerable.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Performance and Resource Usage
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Average Time per Prompt&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Mistral-Nemo: 4.8 s&lt;/li&gt;
&lt;li&gt;Gemma3: 6.2 s&lt;/li&gt;
&lt;li&gt;LLaMA 2-13B: 5.5 s&lt;/li&gt;
&lt;li&gt;Vicuna-13B: 5.7 s&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;GPU Memory Used&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Mistral-Nemo: 12 GB&lt;/li&gt;
&lt;li&gt;Gemma3: 16 GB&lt;/li&gt;
&lt;li&gt;LLaMA 2-13B: 14 GB&lt;/li&gt;
&lt;li&gt;Vicuna-13B: 15 GB&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;CPU Load&lt;/strong&gt;: About 20–25% for all while testing.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Gemma3 used more memory, so it’s slower but a bit safer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibiy0fkx4x3ae7q0poqu.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibiy0fkx4x3ae7q0poqu.gif" alt="Check GIF" width="273" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And yeah don't be him and make sure to do the checks properly 😁.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommendations
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Keep Testing&lt;/strong&gt;: Run Garak regularly to find new flaws.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Multiple Safety Layers&lt;/strong&gt;: Combine model guardrails with external checks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose Tuned Models&lt;/strong&gt;: Vicuna shows that tuning helps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update Your Tools&lt;/strong&gt;: Ollama has had bugs (like CVE-2024-37032). Always use the latest version.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Running Garak on these models shows that all of them have weak spots. Mistral-Nemo always failed, Gemma3 was okay but not perfect, LLaMA 2 struggled, and Vicuna was the best but still not flawless. The main lesson is that we need ongoing tests, several safety measures, and up-to-date software to keep these AI models safe.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsidw2lk2k9uhlbvih6dk.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsidw2lk2k9uhlbvih6dk.gif" alt="Bye GIF" width="498" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks for reading, and happy red-teaming!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>security</category>
      <category>redteaming</category>
      <category>garak</category>
    </item>
    <item>
      <title>Ping! Pop! Pow! Real-Time Security with Suricata, StackStorm &amp; Slack.</title>
      <dc:creator>Crispin</dc:creator>
      <pubDate>Thu, 15 May 2025 18:16:46 +0000</pubDate>
      <link>https://dev.to/crispin_r/ping-pop-pow-real-time-security-with-suricata-stackstorm-slack-2ij8</link>
      <guid>https://dev.to/crispin_r/ping-pop-pow-real-time-security-with-suricata-stackstorm-slack-2ij8</guid>
      <description>&lt;p&gt;Hey dev.to community!&lt;/p&gt;

&lt;p&gt;I was recently learning a few SecOps topics and was trying things out with the tool StackStorm (it's basically a ITTT tool for devops) that helps in event-driven automation. So then I thought of why not combine it with the good old Suricata tool and hence this blog... ;)&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR: What We’re Building
&lt;/h2&gt;

&lt;p&gt;We’ll wire up Suricata (our network IDS) to StackStorm (our event-driven automation engine), so that whenever Suricata spots suspicious traffic, StackStorm picks it up and shoots an alert into Slack. No more manually tailing logs, your chat app becomes your security ops dashboard!&lt;/p&gt;




&lt;p&gt;So enough talking and let's start doing!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fm%2FA-SAIQsYfoYAAAAd%2Fsi-va-in-scena-showtime.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fm%2FA-SAIQsYfoYAAAAd%2Fsi-va-in-scena-showtime.gif" width="640" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is this cool?
&lt;/h2&gt;

&lt;p&gt;Coz I find it. 😂 jk. Yeah even I had this question earlier but later after gpting and trying things out, this seemed way cooler just like a security admin or smth lol.&lt;/p&gt;

&lt;p&gt;Imo, these are a few =&amp;gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Security&lt;/strong&gt;: Get notified instantly when something weird pops up on your network.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hands-On Automation&lt;/strong&gt;: Learn how sensors, rules, and actions fit together in StackStorm.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slack Integration&lt;/strong&gt;: Everyone loves Slack(&lt;del&gt;Teams&lt;/del&gt; ;)) and it’s a familiar place to see alerts.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Super Simple&lt;/strong&gt;: We’ll use out-of-the-box components and minimal code so even newbies can follow along.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What I'll be using for this setup
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A Linux VM&lt;/strong&gt; - Ubuntu (not a hecker, sadly🤧🐉).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt; (optional, but makes life easier).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Suricata&lt;/strong&gt; installed and running in IDS mode.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;StackStorm&lt;/strong&gt; installed.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Slack workspace&lt;/strong&gt; and a Slack “Incoming Webhook” URL.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  First, we get Suricata logging alerts
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install Suricata
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
   &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;suricata
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Enable EVE JSON output in /etc/suricata/suricata.yaml:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;outputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;eve-log&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
      &lt;span class="na"&gt;filetype&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;regular&lt;/span&gt;
      &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/var/log/suricata/eve.json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Restart Suricata and generate some test alerts:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart suricata
&lt;span class="nb"&gt;sudo &lt;/span&gt;suricata-update
&lt;span class="c"&gt;# Then run a nmap or scapy script to trigger IDS rules&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Then, we spin up StackStorm
&lt;/h2&gt;

&lt;p&gt;For this blog I'll use Docker, but you can even run it natively as you prefer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; st2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /var/log/suricata:/var/log/suricata &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 9100:9100 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 9101:9101 &lt;span class="se"&gt;\&lt;/span&gt;
  stackstorm/stackstorm:3.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now verify if StackStorm’s running,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;st2 status
st2 action list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The core event logic,
&lt;/h2&gt;

&lt;p&gt;We'll create a Suricata sensor in StackStorm.&lt;/p&gt;

&lt;p&gt;StackStorm “sensors” watch for external events. We’ll write a tiny Python sensor that tailed /var/log/suricata/eve.json and emits each alert as a StackStorm trigger.&lt;/p&gt;

&lt;p&gt;Create a new sensor file, /opt/stackstorm/packs/suricata/sensors/suricata_sensor.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;st2reactor.sensor.base&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Sensor&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SuricataSensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Sensor&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sensor_service&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SuricataSensor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sensor_service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sensor_service&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/var/log/suricata/eve.json&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# seek to end for only new events
&lt;/span&gt;            &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;seek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readline&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="k"&gt;continue&lt;/span&gt;
                &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;event_type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;alert&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_sensor_service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trigger&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;suricata.alert&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, register the sensor by updating packs/suricata/sensor.yaml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SuricataSensor&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Watches&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Suricata&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;eve.json&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;alerts"&lt;/span&gt;
&lt;span class="na"&gt;entry_point&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sensors/suricata_sensor.py&lt;/span&gt;
&lt;span class="na"&gt;trigger_types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;suricata.alert&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Triggered&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Suricata&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;IDS&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;alert"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, reload StackStorm so it picks up your new pack.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;st2ctl reload &lt;span class="nt"&gt;--register-all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Now, define a rule to catch the trigger (final)
&lt;/h2&gt;

&lt;p&gt;StackStorm “rules” link triggers to actions. We’ll catch suricata.alert and then call a Slack action.&lt;/p&gt;

&lt;p&gt;Rule file: /opt/stackstorm/packs/suricata/rules/slack_alert.yaml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;send_suricata_alert_to_slack&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Send Suricata alert details to Slack&lt;/span&gt;
&lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;suricata.alert&lt;/span&gt;
&lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;slack.post_message&lt;/span&gt;
  &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;#alerts"&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;:rotating_light: *Suricata Alert!* :rotating_light:&lt;/span&gt;
      &lt;span class="s"&gt;*Signature:* {{ trigger.payload.alert.signature }}&lt;/span&gt;
      &lt;span class="s"&gt;*Severity:* {{ trigger.payload.alert.severity }}&lt;/span&gt;
      &lt;span class="s"&gt;*Source:* {{ trigger.payload.src_ip }}:{{ trigger.payload.src_port }}&lt;/span&gt;
      &lt;span class="s"&gt;*Destination:* {{ trigger.payload.dest_ip }}:{{ trigger.payload.dest_port }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you have to configure the Slack credentials in ~/.st2/configs/slack.yaml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;slack&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://hooks.slack.com/services/hee/hee/hee"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for one last time, reload.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fm%2FPK0FP8t6A5UAAAAd%2Fwaiting.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia1.tenor.com%2Fm%2FPK0FP8t6A5UAAAAd%2Fwaiting.gif" width="422" height="498"&gt;&lt;/a&gt;&lt;br&gt;
I know you're like this 😂, but we have to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;st2ctl reload &lt;span class="nt"&gt;--register-all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  It's time to test!
&lt;/h2&gt;

&lt;p&gt;Generate a known alert (e.g. run nmap -sS against your box).&lt;/p&gt;

&lt;p&gt;Watch your StackStorm logs (/var/log/st2/st2sensorcontainer.log) to see the trigger fire.&lt;/p&gt;

&lt;p&gt;Check your Slack channel—you should get a nicely formatted alert message within seconds!&lt;/p&gt;

&lt;p&gt;Heehee...we’ve now built a simple, end-to-end event-driven security workflow!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2F2GdvMq0z0dUAAAAM%2Fdrake-notebook.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.tenor.com%2F2GdvMq0z0dUAAAAM%2Fdrake-notebook.gif" width="220" height="123"&gt;&lt;/a&gt;😂See ya!&lt;/p&gt;

&lt;p&gt;P.S. We can even add filtering(only alert on high-severity events), automated responses(trigger a firewall block or a cloud security group update) and dashboards with push alerts into Elasticsearch and visualize with Kibana and what not lol! Do follow for more blogs in the future.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>suricata</category>
      <category>tutorial</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
