Known bad, no known bad, unknown: a three-state policy model for agent artifacts
Your agent artifact policy needs three answers, not two. Known bad means a trusted source has a record that matches this exact package, skill or server version. No known bad means someone you trust checked this exact build and found nothing. Unknown means nobody you trust has checked it. Most of what agents install today is unknown: in one August 2026 census of the skills.sh catalogue, 87.8% of listings had never been audited. A two-state "safe or unsafe" verdict forces you either to block most new artifacts or to wave through code nobody has read. Three states let you block, log or ask a person, each where it fits.
The question you are actually asking
You want a rule your agents can follow without a person reading every install. You have some sources of bad news: advisories, scanners, a list someone curates. When those sources say nothing about an artifact, you have to decide what "nothing" means.
That is the whole problem. "Nothing" can mean two very different things.
Why "safe" is the wrong word
Think of a food-safety inspector. A restaurant can be in three states. It failed an inspection. It passed an inspection last month. Or it opened yesterday and nobody has inspected it yet. The third restaurant is not unsafe. It is also not "passed." A sign on the door that says "no violations on record" would be true and misleading at the same time.
Agent artifacts work the same way. A scanner that returns no findings has told you something only if it actually scanned that exact version. A lookup that finds no record in an advisory database has told you nothing about an artifact the database has never seen.
The tools you already use hint at this. ClawHub sorts VirusTotal results into benign, suspicious and malicious, and still warns users that "a clean scan doesn't mean a skill is safe" (OpenClaw, 7 February 2026). The OSV format, which most open advisory data uses, has no field for "checked and clean" at all. A version that matches no record is simply a non-match (OSV schema). If your policy needs to know that someone checked, you have to store that fact yourself.
How big the unknown pile is
The Skillselion census took a dump of the skills.sh catalogue on 12 August 2026 (Skillselion, Agent Skill Security Census):
- 79,848 listings, with 41,791 audit verdicts from five providers: Socket, Snyk, Gen Agent Trust Hub, ZeroLeaks and Runlayer.
- 87.8% of listings had never been audited.
- The audited 12.2% held 83.3% of installs, so popular skills are more likely to have been checked.
- Among the 1,233 listings rated by more than one auditor, 12.7% had one auditor rate them HIGH or CRITICAL while another rated them LOW or SAFE.
The census counts registry install events, not active users, and it inherits each auditor's standards. Even so, the shape is clear. Most listings sit in the unknown pile. And even "checked" is not one answer when checkers disagree one time in eight.
The three states, defined
State What must be true What it is NOT
------------- ------------------------------------------------- -----------------------------
known_bad A trusted, non-withdrawn record matches this A guess, a heuristic score,
exact name and version (or content hash) or a similar-looking name
no_known_bad A named checker examined this exact build, on a A promise. It expires and it
recorded date, and reported nothing malicious resets on every new version
unknown Neither of the above Unsafe. Just unexamined
Two rules keep the states honest.
A new version starts at unknown. A check of version 1.0.15 says nothing about 1.0.16. The postmark-mcp case shows why: the hidden BCC line that copied every outgoing email arrived in version 1.0.16, not in the package's first release (The Hacker News, 29 September 2025).
Conflicting verdicts are unknown, not no known bad. If one auditor says CRITICAL and another says SAFE, nobody has given you a clean answer. Treat the artifact as unexamined until a person resolves the conflict.
Default actions by state and place
The same state can deserve a different action on a laptop, in CI and at a gateway. Here is a starting table:
State Developer laptop CI pipeline Remote MCP gateway
------------- ------------------------------- ------------------------------- ------------------------------
known_bad Block Block, fail the build Block the connection
no_known_bad Proceed, log Proceed, log Proceed, log
unknown Low privilege: warn and log Block anything not already in Ask a person before first
Shell/network/secrets: ask the lockfile or approved list connection
Why the split for unknown on a laptop? Because privilege matters more than novelty. An unknown skill that only formats Markdown is a small bet. An unknown skill that runs shell commands, or an MCP server that holds your tokens, is a large one. The same census found that shell-capable skills account for at least 43.5% of installs, so "ask on high privilege" is not a rare branch.
Why block unknown in CI? A pipeline should install what a person already approved and pinned. New artifacts belong in a pull request, not a build.
Warn budgets: how to avoid drowning people
Warnings only work if people read them. Splunk's 2025 survey of 2,058 security leaders found that 59% have too many alerts and 55% deal with too many false positives (Cisco newsroom, 20 May 2025). An agent that warns on every unknown install will add to that pile within a week.
A warn budget is a cap on how many unknown-state warnings one person sees in a day. When the cap is reached, the next unknown does not produce another warning. It goes to a review queue instead, and the install waits or proceeds according to its privilege class. The effect is that warnings stay rare enough to read, and the overflow becomes work for a reviewer rather than noise for a developer.
A worked example
Illustrative example: a team's agents install 100 new artifacts in a week. Suppose 90 are unknown, 9 are no known bad, and 1 is known bad. The numbers are round on purpose.
- Two states, block anything not proven clean. 91 blocks. Developers turn the control off by Wednesday.
- Two states, allow anything not proven bad. 1 block, 90 unexamined installs, and no record that they were unexamined.
- Three states with a privilege split. 1 block. Of the 90 unknowns, say 60 are low privilege: logged, with a warning up to each person's budget. The other 30 ask a person. The 9 no-known-bad installs proceed and are logged.
The third row still asks for 30 decisions. That is the honest cost of a large unknown pile. But every one of those 30 is a high-privilege artifact nobody has checked, which is exactly where a person's attention belongs.
A sample policy file
The format below is illustrative and not tied to any tool. It shows the decisions a real policy has to encode:
# agent-artifact-policy.yaml (illustrative format)
states:
known_bad:
laptop: block
ci: block
gateway: block
no_known_bad:
laptop: allow_and_log
ci: allow_and_log
gateway: allow_and_log
expires_after_days: 30 # re-check; new versions reset to unknown
unknown:
laptop:
low_privilege: warn_and_log
high_privilege: ask # shell, network, secrets, MCP servers
ci: block_unless_pinned
gateway: ask
conflicting_verdicts: unknown
warn_budget_per_person_per_day: 3
overflow: review_queue
Mapping the states to OSV data
If your bad news comes from OSV-format records, the mapping is short:
- known_bad: an OSV record, often with a
MAL-identifier, whose affected versions include this version and which has nowithdrawntimestamp. - A withdrawn record: the artifact drops back to whatever your own check history says. Withdrawal means the report was wrong, not that someone checked the artifact.
- no_known_bad: not expressible in OSV. Store it beside your data: checker, date, exact version or hash.
- unknown: the default when neither exists.
Where this simple model stops working
Known-bad lists lag. In the March 2026 axios compromise, the malware advisory was published at 03:15:49 UTC on 31 March (OSV, GHSA-fw8c-xr5c-95f9), close to three hours after the first bad version reached the registry at 00:21 UTC (npm registry). During those hours, the artifact was unknown, not known bad. The three states do not shrink that gap. Pair them with controls that act on unknown, such as a release-age delay or the privilege split above.
No-known-bad also ages. A check is a snapshot of one build on one day.
Decision checklist
- Can your tools tell "checked, nothing found" apart from "never checked"? If not, start recording check history.
- Does a new version reset to unknown?
- Are conflicting verdicts treated as unknown?
- Do unknown artifacts with shell, network or secret access ask a person?
- Does CI block anything not pinned or approved?
- Is there a warn budget, and where does the overflow go?
- What share of installs land in each state each week? Track it; it is the number that tells you whether the policy is livable.
The threat.cafe counter uses the same three answers, known bad, no known bad and unknown, if you want to see the vocabulary applied to real 2025 and 2026 artifacts.
Sources
- The Agent Skill Security Census, 2026-08-12 edition — Skillselion, accessed 15 October 2026
- Global State of Security report reveals critical need for connected security operations — Cisco Newsroom, 20 May 2025
- ClawHub and VirusTotal partnership — OpenClaw, 7 February 2026
- Open Source Vulnerability format — OpenSSF, accessed 15 October 2026
- First malicious MCP server found stealing emails in rogue postmark-mcp package — The Hacker News, 29 September 2025
- GHSA-fw8c-xr5c-95f9: Malicious code in axios — OSV, published 31 March 2026
- axios package metadata — npm registry, retrieved 15 October 2026