
Research
/Security News
Mini Shai-Hulud Campaign Hits Red Hat Cloud Services npm Packages
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.
A self-hostable AI dedupe/triage relay for high-volume security & bug mailing lists. Deterministic near-duplicate clustering + validity-ranking + a triaged digest for human triage. Never auto-discards a report. Optional Anthropic LLM layer sharpens validi
Groups the flood of near-identical bug reports on a busy security mailing list into one tidy digest a human can actually get through.
A few very high-traffic security/bug mailing lists are buried under waves of the same AI-written report sent over and over. listsift reads the mailbox, bundles the near-duplicate copies of each report together, sorts the bundles so the ones most likely to be real float to the top, and hands the maintainer one digest to read. It only ever groups, ranks, and labels — it never throws anything away. A human still decides.
Nothing is ever auto-deleted. Every message stays in the digest, just grouped and ordered. This is enforced in code and tested — see
test/no-discard.test.js.
This is a narrow tool for a small audience. It exists because a few very high-traffic security/bug mailing lists are, in their maintainers' own public words, becoming "almost entirely unmanageable" under a flood of mass-duplicated, often-made-up AI bug reports (HN discussion). AI is good at spotting and grouping duplicates; mailing-list software has no built-in duplicate detection. listsift is a small, honest tool you run yourself that fills exactly that gap.
Being blunt about the size of the problem this addresses:
git clone and run. Nothing more is promised.If you maintain a list that isn't drowning in duplicate AI reports, you almost certainly don't need this. That's fine — it's built for the ones that are.
listsift is fully usable with no API key and no internet. The core runs entirely on your machine, gives the same result every time, and has no outside dependencies. The steps:
parse (mbox/maildir/message)
-> normalize (strip quoting/signatures/Re:/[list] tags, mask volatile tokens)
-> cluster (threading + normalized-subject + body-shingle Jaccard, union-find)
-> validity heuristics (advisory; transparent signals)
-> ranked digest (every input message represented)
Without a key it produces a complete, useful, byte-stable digest:
References / In-Reply-To are one issue.Re: prefixes) collapse into one
cluster, reported as "N duplicates collapsed". All original Message-IDs,
senders, and dates are preserved in the digest.npm ci # only dev dependency is the test runner (vitest)
# Triage an mbox -> human-readable digest (no key, no network):
node bin/listsift.js digest /path/to/list.mbox
# Or a maildir, or a directory of one-message files, or stdin:
node bin/listsift.js digest /path/to/Maildir
cat list.mbox | node bin/listsift.js digest -
# Machine-readable:
node bin/listsift.js digest list.mbox --json
# Tune the near-duplicate threshold (default 0.5; higher = stricter):
node bin/listsift.js digest list.mbox --similarity 0.6
Example (the test fixture): 9 messages → 4 issues, 5 duplicates collapsed; the
real use-after-free report ranks first, a 5-way mass-duplicated report
collapses into one cluster, and a grandiose-but-empty "SEVERE VULNERABILITY"
message is ranked last as low-signal — but still present in the digest.
There's an optional second pass that uses an LLM (a large language model — the kind of AI behind chat assistants). It only sharpens the "is this real" score on the hard, borderline cases (confident-sounding text with no actual evidence is exactly where the plain rules are weakest). It is off unless you turn it on with your own key.
export ANTHROPIC_API_KEY=sk-ant-... # YOUR key. Never bundled. Never shared.
node bin/listsift.js digest list.mbox --llm
test/no-network.test.js.)combineScores in
src/scorer.js), so even a model that hallucinates "this
is invalid → 0" cannot single-handedly bury a real report at the
default weight. Unparseable model output falls back to a neutral score,
never a silent zero. A scorer error falls back to the deterministic score
and is surfaced in the digest rationale — never swallowed. The no-discard
invariant (every message present, exactly once) always holds regardless of
LLM weight; the weighted-mean design keeps a real report out-ranking noise
at the default setting.FakeScorer;
the real AnthropicScorer is a thin, documented HTTP call to the Anthropic
Messages API.Security-list mail is sensitive (sometimes embargoed). listsift's posture:
fetch and runs a full digest expecting it to never be
called.--llm with your own key. In that mode, only the
representative (richest) message of a cluster is sent, truncated — never the
full list, never your whole mailbox. If you never pass --llm, no message
content leaves your machine.FEEDBACK.local.ndjson, gitignored)
and is never transmitted anywhere.A hallucinated low validity score silently dropping a real vulnerability report would be catastrophic for a security list. So:
sum(cluster sizes) === input message count is verified at runtime; the CLI
refuses to emit a digest that lost a message (exit code 3) rather than
silently drop one.This is tested directly, including an adversarial scorer that returns 0 for
everything and one that throws — in both cases every message still appears.
--similarity for
your list and report misfires (see FEEDBACK.md).From -line heuristic.npm ci
npm test # vitest — no network, no API key required or used
src/parse.js, normalize.js, cluster.js, validity.js,
digest.js, feedback.js, scorer.js) is pure and dependency-free.
Filesystem I/O is isolated in src/io.js; the only network I/O is the
optional AnthropicScorer in src/scorer.js.ANTHROPIC_API_KEY
present, zero network in the deterministic path, Anthropic-only (no
competing provider endpoint/SDK in src/), no hardcoded key, the
nothing-auto-discarded invariant (incl. adversarial/throwing scorers), and
byte-stable deterministic output..github/workflows/ci.yml) runs
npm ci && npm test only — no secrets, no network.Misfires (false merges, missed duplicates, misleading ranks) are the single
most useful signal — see FEEDBACK.md. Reports are stored and
read verbatim (no summarization). Zero-friction path: add the
listsift-feedback label to a related issue, or append a line to your local
FEEDBACK.local.ndjson via listsift feedback <kind> "<text>".
MIT — see LICENSE.
FAQs
A self-hostable AI dedupe/triage relay for high-volume security & bug mailing lists. Deterministic near-duplicate clustering + validity-ranking + a triaged digest for human triage. Never auto-discards a report. Optional Anthropic LLM layer sharpens validi
We found that listsift demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.

Research
/Security News
The North Korean malware loader hides in a Packagist-listed package and its GitHub branch to fetch and execute remote code in a likely Contagious Interview-style lure.

Security News
The Rust project is moving toward formal rules on LLM use in contributions after months of internal debate over maintainer burden, code quality, and contributor experience.