All work
2025/ Security · Automation/ Technologia × 42 Beirut

AI-Driven SOC Pipeline

Raw logs in, actionable intelligence out. Built at Lebanon's first Agentic AI & Cybersecurity Hackathon: an n8n pipeline that ingests security logs, enriches every suspicious IP, and hands the SOC analyst a written incident report instead of ten thousand lines to read.

Interactive demo

Pick a log source and watch it move through the pipeline

n8n · soc_enrichment_workflow
Ingestwebhook
Parseregex + JSON
EnrichIP intel
AnalyseGemini
ReportSOC channel
// select a log source above to start the run

Idle · workflow armed, waiting on webhook.

At a glance

My role
Pipeline + prompt design
Stack
n8n · Gemini · JavaScript
Built in
48-hour hackathon
Result
Raw log → written report

Architecture

Where the analyst's twenty minutes went

automated · n8n Log shippers auth · firewall Webhook batched burst Parse common schema Enrich IP · geo · ASN Gemini severity + prose SOC channel report + page facts flow through · the model only writes around them
Every factual value in the report comes from the enrichment step, not the model.

Code

The two decisions that mattered

parsers/auth_log.js sshd → common event schema

const FAILED   = /Failed password for (?:invalid user )?(\S+) from (\S+) port (\d+)/;
const ACCEPTED = /Accepted password for (\S+) from (\S+) port (\d+)/;

export function parse(line) {
  const fail = FAILED.exec(line);
  if (fail) return event("auth.fail", fail);

  const ok = ACCEPTED.exec(line);
  if (ok) return event("auth.success", ok);

  return null;      // not an auth line. drop it here, not three nodes downstream
}

function event(type, [, user, ip, port]) {
  return { type, user, ip, port: Number(port), source: "sshd" };
}

Failures and successes are separate event types. The alert fires on the sequence, not the count.

workflows/enrich_guard.js a dead API must not eat the event

const LOOKUP_TIMEOUT_MS = 2500;

export async function enrich(event) {
  try {
    const intel = await withTimeout(lookupIP(event.ip), LOOKUP_TIMEOUT_MS);
    return { ...event, intel, enriched: true };
  } catch {
    // flag it and keep going: an analyst still needs to see this event
    return { ...event, intel: null, enriched: false, reason: "lookup_timeout" };
  }
}

Early versions dropped events when the reputation API stalled. The worst possible failure mode for a security tool.

Inside the repo

Structure

  • workflows/exported n8n JSON
  • soc_enrichment.jsonthe main pipeline
  • ip_enrichment_sub.jsonreusable sub-workflow
  • alert_router.jsonseverity → channel routing
  • prompts/LLM prompt templates
  • incident_report.mdconstrained report prompt
  • severity_rubric.mdscoring rules given to the model
  • parsers/log format handling
  • auth_log.jssshd / auth.log
  • firewall.jsconnection + drop events
  • normalise.jscommon event schema
  • samples/test fixtures
  • bruteforce.logreplayable sample
  • portscan.logreplayable sample
  • docker-compose.ymln8n + local test stack
  • README.mdimport + credential setup

Skills, in context

Where each one actually showed up

n8n Orchestration, plus the timeout fallback in enrich_guard.js above.
LLM / Gemini Report writing under a fixed rubric: facts injected, never generated.
Webhooks Ingestion and outbound posting; bursts batched instead of one run per line.
Security operations Alerting on velocity and success-after-failure, not raw failed-login counts.
Next project ByteMed