We built Argus - it reads your source code to tell you if an attack would actually work

by•

Hi Product Hunt đź‘‹

We're building Argus, our API security platform.

The problem: security tools tell you an endpoint is getting hammered, but not whether that matters. Most abuse traffic is noise. Some of it isn't. Teams burn hours figuring out which is which.

Argus closes that gap. When it sees abnormal abuse frequency on an endpoint, it pulls the raw source code behind that endpoint and uses AI to assess whether an attacker could actually cause damage there. So instead of an alert count, you get a damage path or confirmation that there isn't one.

Still early, and we'd take feedback. Curious how others here handle alert noise, most of what we tried before this didn't hold up.

31 views

Add a comment

Replies

Best

This is an interesting distinction. Request volume alone says very little about actual business impact, especially when different endpoints expose very different capabilities.

How does Argus connect an observed request pattern to the relevant source-code path in practice? And how do you control false positives when legitimate users trigger unusual behaviour?

I’m building an API product myself, so the idea of prioritising alerts by reachable damage rather than raw traffic looks genuinely useful.

 Great questions, those two are exactly what broke every earlier version we tried.

Traffic -> source path: the anomaly is only the trigger, never the analysis. When an endpoint spikes we key off its identity - method + normalized route template (POST /orders/{id}/refund, not the raw /orders/8412/refund) and resolve that to the actual route registration in your source, then walk it into the handler -> service -> the sinks that actually do something (DB writes, payments, file/command execution). So we're not inferring intent from the payload; we use the endpoint as an index into the code and let the analysis read the real path, the auth check, the ownership check, what the handler is genuinely capable of.

False positives: this is the one, and it's why we moved the verdict off the traffic entirely. Abnormal frequency never becomes a finding on its own it only means "look here." A finding exists only if the code at that endpoint has a reachable damage path: a refund route missing an ownership check, user input reaching a query/command, that kind of thing. A legit user hammering an endpoint that's actually well-guarded , we return "no damage path," however weird the traffic looked. Traffic-anomaly and exploitability are two separate axes; only their intersection is worth paging anyone. And we make the model show its work, the concrete source->sink trace so it's confirmable, not a vibe.

Still early and this part's evolving fast, but that split traffic = attention, code = verdict is the first thing that actually held up for us.

Since you're building an API product too: what's been your signal for "this alert is real" raw volume, auth-failure rate, something more semantic? Genuinely curious how you're drawing that line.

 
That split makes a lot of sense—traffic decides where to look, but code and reachable side effects decide whether it matters.

In VAT Engine, I’m currently drawing the line in a more deterministic way rather than using one universal anomaly score. Raw volume, authentication failures, rate-limit hits, or invalid webhook signatures are attention signals, but none of them alone means “incident.”

I treat it as real when the signal is tied to a protected boundary or integrity risk—for example, repeated attempts against a specific identity, a tenant or ownership mismatch, a failed signature before a sensitive workflow, an unexpected state transition, or persistent failures around an operation that writes compliance data.

Most isolated failures stay in structured logs and audit history. The stronger signal is a combination of context: endpoint, authenticated identity, tenant, action attempted, resulting state, and whether the operation could create a durable side effect.

Your traffic = attention, code = verdict model is more semantic than what I currently have, especially the confirmable source-to-sink trace. I’d be interested to see how well that works on systems where the route reaches background jobs or external APIs rather than completing the sensitive action inside the request handler.

yeah that's the case that breaks the naive version of this, because the handler is often just a doorway.

The move is to treat the async/cross-service edge as a continuation of the trace, not the end of it. When a handler's real "sink" is a publish, an enqueue, or an outbound call, we resolve the other side the same way we resolve routes: an event type / topic / job name is just another index into the code - it points at the consumer or worker that handles it, and we keep walking there (handler -> publishes order.refund.requested -> the refund consumer → the DB write / payment that actually does the damage). Same for an internal service call -> the gRPC/HTTP target resolves to that service's route and we continue into it. So the sink set isn't just "DB write / payment / exec," it's also "hands off to X," and X is where the walk resumes, as long as X is in the code you've connected.

And honestly the async hop is usually where the real finding is, because that's where the guarantees change. The auth/ownership context that existed inside the request handler doesn't survive the queue the worker re-derives identity from the job payload, and if it trusts a user_id/tenant_id in that message instead of re-checking ownership, you've got a reachable damage path that's invisible if you only look at the handler (the handler looked fine - it had the check). So we specifically look for "did the downstream re-establish the same boundary the request enforced, or did it inherit trust from a message it shouldn't." Outbox-style event flows and background jobs are full of exactly that.

Where it genuinely degrades is a true third-party API there the trace terminates at the boundary, and the verdict shifts from "here's the source->sink" to "here's the data and authority you're handing across this trust boundary, and what you're assuming about it." Honest that that's a weaker, more assumption-y verdict than an in-code trace.

Still early on cross-async completeness - solid when the target's in the same repo/connected set, thinner across boundaries we can't see. But that's also where the juicy bugs live, so it's where most of the work is going.

 That’s a very useful distinction. The re-derivation of identity and ownership after an asynchronous handoff is the part I had not framed explicitly enough.

In VAT Engine, the pattern I’m aiming for is that queued work carries a stable integration or job reference, while the worker reloads the authoritative tenant, credentials, and current state server-side instead of treating identity fields in the message as proof. Webhook input is verified before enqueueing, and the eventual write path still applies ownership and data-integrity checks.

But I agree that this boundary is where subtle regressions appear: the request handler may be secure while a later consumer quietly trusts a user_id, tenant identifier, or resource reference inherited from the payload.

Your treatment of third-party APIs also sounds appropriately honest. Showing the data, authorization, and assumptions crossing the boundary seems more useful than pretending to prove what happens inside code you cannot inspect.

Can Argus express authorization invariants as policies or annotations? For example: “this worker must derive the tenant from integration_id, never trust tenant_id from the job payload.” That could make it especially valuable for detecting regressions when new consumers or background jobs are added.