28 security issues fixed
in the first 30 days
83% of findings
were actionable, not noise
NoSQL injection
missed by other tools
It's like having a pentester reviewing every PR you are making.
About Novu
Novu is an open-source notification infrastructure platform: a single API for sending notifications across 15+ channels (in-app, email, SMS, push), used by both cloud and air-gapped on-prem deployments. The project has 39,000 GitHub stars and 400+ external contributors on its open-source edition. It’s now expanding into two-way agent communication with Novu Connect, letting AI agents complete tasks directly inside Slack and other channels instead of just redirecting users elsewhere.
The challenge: trusting a codebase 400 contributors touch
Novu runs a zero-trust policy on every external contribution. With 400+ outside contributors, nothing ships without scrutiny. Two things are happening at once: AI is increasing how much code Novu ships, and the team has grown skeptical of what compliance-driven vendor security reviews actually catch.
The more yearly vendor reviews I do, the less trust I have in them. They just run a ten-point playbook on all of their companies and usually find things that are pretty irrelevant.
It gets the checkmarks done, but internally we have no trust in that.
Novu already runs a layered stack (CodeQL, Greptile, Cursor’s security reviewer, and periodic DeepSec scans) at two checkpoints: every PR submission and again before tagging a release.
With AI, we are generating more outcomes in terms of the product surface area.
And of course this puts the human error factor during reviews much higher.
Where Hacktron fits: confidence, not process change
Dima was direct about what changed and what didn’t:
Nothing in our process changed with Hacktron. The only thing that really changed is the level of confidence we have: knowing that we are catching much more elaborate patterns.
And that confidence brings the ability to increase velocity, too.
That confidence comes down to signal quality. Novu’s existing tools mostly flag issues visible in a PR’s diff (Dima described these as “one-hop” exploits). Hacktron builds a code graph of the repository and diffs those graphs across PRs, surfacing second-order issues: vulnerabilities that only become visible when you trace how a change in one file affects code elsewhere in the system.
When we see comments from other tools, in many cases those are out of scope or acceptable risk.
When we see something from Hacktron, the team pays attention and gives it thought. In many cases we find them quite relevant.
Dima also named the risk he’s actively managing against: noise fatigue.
You don't want it to be the boy who cried wolf.
There are many notifications in the reports that you start to miss the point.
Signal quality isn’t a nice-to-have here. It’s the difference between a tool the team actually reads and one they learn to ignore.
Analysis of Hacktron Reviews on Novu
Over Novu’s first 30 days on Hacktron (July 6 - Aug 6, 2026):

| Metric | Value |
|---|---|
| Unique PRs reviewed | 230 |
| Total findings surfaced | 61 |
| Findings triaged to a final state | 42 |
| True positive / Accepted risk / Resolved / False positive | 1 / 6 / 28 / 7 |
| Actionable rate (TP + AR + Resolved vs. total evaluated) | 83% |
18 findings are still pending triage. 1 more was withdrawn when its source PR was abandoned.
What kinds of vulnerabilities does it find?
Novu’s own tools mostly catch issues visible in a single file or a single PR diff. The findings that Dima singled out as valuable are the ones that only show up when you trace a call across several files, exactly the kind of thing a pattern-matching scanner has no way to flag.
NoSQL injection and cross-conversation authorization bypass (High)
Caught in PR #12062, fixed in the same PR before merge.
Novu was rolling out a new ingestion path for self-hosted AI agents to emit structured events (messages, replies, approvals) into the platform. Part of that pipeline needed to resolve an inbound event back to the right conversation activity by matching on a client-supplied message ID:
private async resolveActivityByClientId( environmentId: string, conversationId: string, messageId: string): Promise<ConversationActivityEntity | null> { for (let attempt = 0; attempt < ACTIVITY_RESOLVE_MAX_ATTEMPTS; attempt += 1) { const activity = await this.activityRepository.findOne( { _environmentId: environmentId, identifier: messageId }, '*' ); if (activity) { return activity; } if (attempt < ACTIVITY_RESOLVE_MAX_ATTEMPTS - 1) { await delay(ACTIVITY_RESOLVE_DELAY_MS); } } return this.activityRepository.findByPlatformMessageId(environmentId, conversationId, messageId);}Two problems compounded here. First, the query filter never checked which conversation the activity belonged to, only the environment. Second, the incoming messageId wasn’t validated as a plain string before being used directly in that filter, meaning it could be replaced with a MongoDB query operator instead of an ID. Together, an authenticated caller could resolve, and then edit or delete, activity belonging to a conversation that wasn’t theirs.
Hacktron’s Review caught this by tracing the call chain across three files: the ingest controller that accepts the raw event payload, the use case that casts it into a typed event without deep validation, and the sink service that passes the unvalidated ID into the query above.
The result
Novu gets continuous review across a codebase 400+ external contributors touch, without the noise fatigue that makes teams stop reading security tooling, and with confidence that’s letting them ship faster rather than slower.