Mostafa Negm
Selected work

CASE-02 / Workflow

AI-assisted vulnerability triage workflow

A Python and LLM pipeline that validates, groups and explains findings before they become tickets, with a human approving every decision.

Focus
AI-assisted triageFinding validationSecurity automation
Tools and sources
PythonSQLLLMTenableQualysWiz

The problem

Scanners are thorough and noisy. One root cause shows up as hundreds of findings across hosts, version detection is sometimes wrong, and a large part of a reviewer's day goes into reading advisories, checking whether a finding really applies, and rewriting vendor text into something an engineer can act on.

When unvalidated findings go straight to engineers, two things happen. Trust in the security team erodes, and real issues wait behind false ones.

What I did

I designed a triage workflow where deterministic code does the checking, a language model does the reading and drafting, and a human makes the call.

  1. Normalize and validate. Findings from Tenable, Qualys and Wiz are pulled into one schema with Python and SQL. Rule-based checks confirm the essentials: is the detected version actually vulnerable, is the asset still alive and owned, is the service reachable, has the finding already been fixed or accepted?
  2. Group by root cause. Findings that share a fix (one missing patch, one outdated base image, one misconfigured template) are clustered, so a team gets one ticket per fix instead of one per host.
  3. Enrich and draft. For each cluster, the model drafts a plain-language summary, the likely fix and the questions a reviewer should confirm, using the advisory text and the validated context as input. It does not set severity, and it never sees credentials or sensitive data.
  4. Human review. An analyst approves, edits or rejects every draft before it reaches an engineer. Edits and rejections are logged, which shows where the rules or prompts need work.

The guardrails matter more than the model. Inputs are minimized and stripped of sensitive fields. Outputs are checked against the validated facts, so a drafted fix that names the wrong version is caught before review. The pipeline fails closed: if the model is unavailable or returns something malformed, the finding drops into the normal manual queue. Prompt injection is treated as a real risk, since advisories and finding text are untrusted input.

The outcome

Engineers receive fewer, better tickets: validated, grouped by fix, and written in their language. Reviewers spend their time on judgment calls instead of copy-editing advisories, and every decision still has a named person behind it.

Because clusters point at root causes, the same data shows which teams keep reintroducing the same issue. That is where training does the most good, and it is how repeat findings stop coming back instead of being re-ticketed every scan cycle.