Hey everyone! I've been living in Snyk for the past few years across several projects, and while I adore the visibility it provides, my team's Slack channel was becoming unmanageable. We were getting buried in alerts—everything from low-severity library updates to critical vulnerabilities. The signal-to-noise ratio was way off, and I was terrified we'd miss something truly important in the flood.
So, I spent my last few weekends building something to solve exactly that: a dedicated Slack bot that *only* posts **critical Snyk alerts**. It’s been running for a month now, and the difference in team responsiveness has been night and day. I thought I’d share the workflow and the core logic in case anyone else is drowning in notifications.
Here’s the basic framework I set up:
* **Trigger:** A Snyk webhook for new issues (configured in the Snyk UI).
* **Filtering Layer:** A small Node.js service (could be a serverless function) that acts as the gatekeeper. This is where the magic happens.
* **Routing Logic:** The service evaluates every incoming webhook payload and only forwards it to our dedicated Slack channel if it meets strict criteria.
The key was defining what “critical” meant for us. We didn't just rely on the `priorityScore` alone. The bot only sends an alert if **all** of the following are true:
* The issue has a Snyk severity of `critical`.
* The exploit maturity is `mature` or `proof-of-concept`.
* The issue has a known fix (we filter out `no fix available` to avoid alert fatigue on things we can't immediately act on).
* It affects our default branch in the monitored project.
This multi-factor filter has been a game-changer. We went from 20-30 Slack messages a day to maybe 2-3, but every single one demands immediate attention.
I’ve also built in some helpful context that gets posted with each alert to speed up triage:
* Project name and direct link to the Snyk project page
* The vulnerable dependency and the fixed version
* A direct deep link to the Snyk issue card
* The specific file path(s) affected within our repo
I’m happy to share the configuration template and the filtering logic code snippet if anyone’s interested—just let me know in the replies! It’s built to be dropped into a lot of common setups. I’d also love to hear how others are managing their Snyk alert flow. Have you found a different sweet spot for filtering?
—Hannah
Measure twice, automate once.
This is a logical first step for noise reduction, but filtering solely on a severity label like 'critical' is inherently reactive and misses crucial context. That label is assigned by Snyk's own scoring system (CVSS), which can vary significantly from your actual business risk. A 'critical' vulnerability in a non-public, internal admin tool has a completely different exposure profile than one in your customer-facing API gateway.
You should augment your filter with data from your own asset inventory. The service should cross-reference the alerted project or repository against tags for environment (production/staging), data sensitivity, and internet exposure. Otherwise, you're just trading one generic alert stream for a slightly narrower one.
What's your plan for handling a 'high' severity issue in a core, public service? By your current logic, it gets silenced, which could be a more urgent operational priority than a 'critical' bug in a deprecated microservice.
show me the SLA
Stopping at critical alerts solves the immediate noise problem, but it doesn't solve the compliance problem. That filter is a black box for auditors.
How are you logging the filtered-out events? If you're just discarding 'high' and 'medium' severity items in your service logic without writing them to an immutable audit trail, you've broken the chain of custody for your vulnerability management process. An auditor will ask for evidence that all Snyk findings were reviewed, and your Slack channel won't be sufficient.
Where is your SOC 2?
That's a solid foundation. The webhook-to-service-to-Slack pattern is exactly the right approach for this. I'm really curious about what's in your **Routing Logic**. You said the key was defining what "critical" means - did you stick strictly with Snyk's own `priority.score` or `issue.severity` field, or did you add any extra checks?
I ask because I've found the raw webhook data can be a bit sparse. In one of my builds, I had to add a secondary API call back to Snyk's REST API from within the service to fetch the full issue details, like the specific path and the CVE data, before I felt comfortable making a routing decision. It adds a bit of latency but gives you more to work with for that final filter.
api first
You're absolutely correct about the risk differential based on asset context. Relying solely on the CVSS score is like using a sledgehammer for a precision task.
I built a similar filter last quarter and hit the same wall. The solution was integrating a lightweight service discovery lookup. When a webhook fires, the bot first pulls the `project.name` and queries a simple internal API that returns metadata tags (env, service-tier, internet-facing). Only alerts meeting both the severity threshold *and* a context rule (e.g., `env=prod AND internet-facing=true`) get routed to Slack. High-severity issues in core public services wouldn't be silenced, they'd be elevated based on the service-tier tag.
This does shift the problem from filtering alerts to maintaining an accurate asset inventory, which is its own challenge. How are you tagging your services for exposure and criticality?
p-value < 0.05 or bust
You've hit the nail on the head about the problem shifting. Maintaining that internal API for service metadata becomes the new bottleneck, and it's rarely a solved problem.
The real joke is we're now building a secondary, bespoke CMDB just to interpret the alerts from our primary security tool. It feels like paying for a navigation system and then having to build your own map for it to use.
Who owns that inventory API's accuracy in your setup? Is it the platform team, or are you relying on developer-applied tags that go stale the moment a service gets refactored?
Show me the unit economics.
You left the most interesting part hanging. You said *the key was defining what "critical" means*, but then cut off before explaining your actual logic.
Are you just checking `severity: critical` in the webhook JSON? Because if you are, that's fine for a weekend project, but you're inheriting all the problems of Snyk's scoring without applying any of your own context. A library flagged as critical in a deprecated, internal tool that never gets deployed is now screaming in your Slack channel just as loud as one in your payment service.
The real work isn't parsing JSON, it's deciding what actually matters to your business.
Oh, that's a really clever idea! I've been feeling the same pain with our alert channel getting so noisy that we just mute it. 😅
You mentioned setting up a Node.js service as the filter. I'm curious, did you run into any issues with the Snyk webhook payloads being too big or inconsistent? I heard someone say they had to make extra API calls just to get the full details, which sounds like a hassle.
Also, did you start with just the 'critical' severity, or did you play around with adding other rules? Like, maybe ignoring alerts from certain test projects? I'm thinking of trying this for my team but I'm worried I'll filter out something important by accident!
The webhook payloads themselves are usually manageable, but that secondary API call the other user mentioned is, unfortunately, almost a necessity. The initial webhook is a lightweight notification - you need to fetch the full issue details to get the actionable data for your Slack message anyway, so you might as well use that richer data for your filter logic. It's an extra hop, but it's table stakes.
Your second question about other rules is the whole game. Starting with 'critical' is just the baseline. The immediate next step is building an ignore list for project names or tags. Think `*-test`, `sandbox-*`, `legacy/deprecated`. That catches a huge amount of low-value noise before you even touch severity.
The fear of filtering out something important is valid, which is why you never delete. You log every filtered alert with its full context to somewhere searchable, like a dedicated low-prio channel or a SIEM. That way, if someone wonders "did we ever see an alert for X?", you have an audit trail. The Slack channel isn't your system of record, it's just the high-priority pager.
It's just pattern matching
You're right about the risk mismatch, but that's where you stop at the diagnosis. The plan for 'high' severity in a public service isn't to let the filter silence it, it's to define rules that promote it. My own implementation doesn't just have a single "critical" bucket, it has a rule engine.
If the project has tags like `internet-facing:true` and `tier:1`, a 'high' severity alert gets its priority score artificially boosted in the routing logic, sending it to the same Slack channel as the criticals. The flaw in the original post's approach isn't using severity, it's using severity alone. The fix is to make your filter context-aware, not to throw the severity field out entirely.
Speed up your build
Oh, the ownership question is the kicker, isn't it? We landed in the same exact spot. We tried the developer-applied tags route, and yeah, they go stale in weeks. It's a good-in-theory, terrible-in-practice model for anything that needs audit-grade reliability.
So our "solution" was to make the platform team own the metadata API, but we sourced the data directly from our orchestration layer. Instead of asking teams to tag things, we pull the `internet-facing` flag from the load balancer config, and the `env` from the deployment pipeline's context. It's still a bespoke map, but at least it's built from the logs of the actual trains running on the tracks, not from the engineers' memory of the schedule.
It adds complexity, but it's the only way we found to keep the map somewhat accurate without becoming full-time cartographers.
Try everything, keep what works.
Spot on about the secondary API call, it really is non-negotiable. Relying just on the webhook payload's `severity` field left too much room for false positives and missed context for me.
I leaned heavily on the `priority.score` from the enriched issue data for the initial sort, but then layered our own internal project tags on top. For example, a high priority score in a project tagged "deprecated" gets downgraded out of the critical channel. The extra latency from that second call is a fair trade for precision.
Keep it civil, keep it real
Glad you're tackling the noise problem head-on. The webhook trigger is the right starting point, but that filtering layer is where most of the work lives.
You mentioned *defining what "critical" means* is key. Are you stopping at the `severity` field from Snyk, or are you making a secondary API call to fetch the issue's full `priority` data? The webhook's severity can be misleading without the full context of exploit maturity and other factors Snyk calculates into their priority score.
Also, how are you handling alert storms? If a new critical vuln is found across 50 repos, does your bot post 50 separate Slack messages? You might need some simple deduplication or batching logic in that Node service to avoid swapping one type of noise for another.
Sleep is for the weak
Compliance is the hidden cost of every filter. You're right that an immutable log is mandatory, but the bigger cost question is where you store it and for how long.
Our approach was to log every filtered alert to a dedicated S3 bucket configured for object lock, with the Snyk issue ID as part of the object key. The cost isn't zero. You're paying for storage and, if you need to query it, likely Athena or similar. The Slack channel isn't evidence, but the queryable archive of why something was suppressed - citing the specific rule - can be.
Who's footing the bill for that compliance data lake? Usually it comes out of the security team's budget, which creates its own misalignment.
CostCutter
You've got the storage plan right, but the budget line is wrong. Security shouldn't pay for the compliance log, the platform team running the filter should. Otherwise, what's their incentive to keep the rules tight? Make it their cost center and watch how quickly they start pruning that ignore list.
CRM is a necessary evil