# Auto-triage phishing reports with VirusTotal and Slack

> Every 15 minutes, phishing emails your staff forward in get checked against 70+ security engines and summarised in Slack, with a compliance log kept automatically.

- Workflow type: agent
- Services: VirusTotal, Gmail, Slack Bot, Google Sheets
- Categories: Engineering, Operations
- Published: 2026-08-10

## What it does

- Checks your shared phishing mailbox every 15 minutes and picks up anything staff have forwarded in under your phishing label.
- Pulls out the sender, subject, links and attachments, then checks each one against a large bank of antivirus and URL scanning engines.
- Posts a short verdict to your security channel (malicious, suspicious or clean) with every link rewritten so nobody can click it by accident.
- Records one row per reported email in a spreadsheet for compliance, then relabels the message so it is never triaged twice.

## What you'll need

- A Gmail account for the shared mailbox staff forward phishing to, with a "Phishing Reports" label and a "Triaged" label already set up.
- A VirusTotal account. The free plan works fine, though it caps how many checks can run each day.
- A Slack workspace and the channel where security alerts should land.
- A Google Sheets spreadsheet to hold the running compliance log.

## Prompt

Every 15 minutes, triage the phishing reports our staff forward into our shared security mailbox. Use the Gmail List Messages operation to find unread messages carrying the "Phishing Reports" label. Process at most five messages per run, oldest first, so a backlog drains steadily across runs instead of exhausting our VirusTotal quota in one burst.

For each message, use Gmail Get a Message at full detail to read the sender address, the subject, the date received, and the body. Extract every link in the body, including links hidden behind display text, and note who forwarded the report. Note every attachment, and use Gmail Get Attachment to retrieve each one so you can compute its SHA-256 hash.

Check each extracted link with VirusTotal. Submit it with Scan a URL, which returns an analysis id, then poll Get an Analysis until the status comes back as completed. VirusTotal scans are not always immediately available, so wait roughly fifteen seconds between polls and give up after about five attempts rather than looping forever. For links VirusTotal already knows about, and whenever polling is exhausted, fall back to Get a URL Report to read the stored verdict. Deduplicate links so the same URL is only checked once per email.

For each attachment, look up its hash with VirusTotal Get a File Report. A not-found response means VirusTotal has never seen that file, which is worth reporting as unknown rather than treating it as clean.

Weigh the per-engine detection counts from each report. Treat an indicator as malicious when three or more engines flag it, suspicious when one or two engines flag it or when the file is unknown, and clean when nothing is flagged. The verdict for the whole email is the worst result across all of its links and attachments. Include a one-line explanation of why you landed on that verdict.

Post a short summary to our security channel using Slack Bot Send a Message. Include the verdict, the sender, the subject, who reported it, and one line per link and attachment showing the detection count out of the total engines checked. Defang every URL and every domain so nobody clicks one by accident while reading the alert: write hxxp:// or hxxps:// in place of http:// or https://, and wrap each dot in square brackets, so example.com becomes example[.]com. Apply this to sender domains too. Lead with a clear visual marker when the verdict is malicious so it stands out in the channel.

Log one row per reported email to our compliance spreadsheet with Google Sheets Append Values, capturing the date triaged, the sender, the subject, who reported it, the number of links and attachments checked, the highest detection count seen, and the final verdict. Keep URLs defanged in the sheet as well.

Finally, relabel the message with Gmail Modify Message Labels: add our "Triaged" label and remove the "Phishing Reports" label along with the unread marker, so the same email is never picked up twice.

Pace the work against VirusTotal rate limits. A free key allows only four requests per minute and five hundred per day, so space the lookups out rather than fanning out all at once, and stop early if VirusTotal starts returning quota errors, leaving the remaining emails unread for the next run. If a single email fails to process, log the failure, leave it unread so it retries later, and carry on with the rest.

## How to customize

- Change how often it runs, from every few minutes to once an hour, and cap how many reports it works through per run.
- Adjust how many flagged engines it takes before something counts as malicious rather than just suspicious.
- Point it at a different alert channel, spreadsheet or pair of labels to match how your team already works.

## Example output

🚨 Phishing verdict: MALICIOUS

From: billing@acme-invoices[.]net
Subject: Urgent: unpaid invoice #4417
Reported by: dana@ourcompany.com

Links (1)
• hxxps://acme-invoices[.]net/secure-login
  9 of 72 engines flagged malicious

Attachments (1)
• invoice_4417.pdf
  14 of 68 engines flagged malicious

Logged to the compliance sheet and relabelled Triaged.

## FAQ

### Do I need a paid VirusTotal account?

No. The free plan works and is what most teams start on. It does limit you to a few hundred checks a day, so the workflow deliberately paces its lookups and only works through a handful of reported emails per run, letting any backlog drain steadily across later runs.

### Will this click the links inside reported phishing emails?

No. Links are only ever submitted for a reputation check, never opened or followed. On top of that, every link in the Slack alert and the spreadsheet is written in a defanged form, so a teammate reading the alert cannot accidentally click through to a live phishing page.

### What happens if a security check takes a while to come back?

Scans are not always ready instantly, so the workflow waits and re-checks a few times. If the result still is not ready, it falls back to any report already on file for that link rather than hanging or failing the whole run.

### Can I use this with a shared reporting inbox instead of a personal one?

Yes, that is exactly what it is built for. It is designed around a shared mailbox where staff forward anything suspicious, and it works from a label rather than from individual recipients.

### Does it delete or move the reported emails?

No. Nothing is deleted. Each message is simply relabelled as triaged once it has been processed, which both keeps a record in the mailbox and stops the same email being picked up twice.

Use this prompt in General Input: https://www.generalinput.com/prompts/auto-triage-phishing-reports-with-virustotal-and-slack