A pre-execution trust gate for AI-suggested software resources.
Quick start · How it works · Policy · Threat model · Contributing
AI coding agents can invent plausible package names, repository URLs, skills, and actions. An attacker can register those names and wait for an agent to fetch and execute them. FirstSeen inserts a deterministic checkpoint before that happens.
- uses: Abhinav0905/firstseen@v0.1.0
with:
path: '.'
format: sarif
output: firstseen.sarifVERDICT RESOURCE SCORE SIGNAL
─────── ───────────────────────────────── ───── ────────
■ BLOCK github-action:actions/checkout@v4 55 FS004
● PASS npm:lodash@4.17.21 100 verified
FirstSeen asks more than “does it exist?” It checks whether a resource is old enough, whether it existed before a chosen trust boundary, whether the requested version or ref exists, and whether executable references are immutable.
Registry metadata is a review signal, not proof that software is safe. FirstSeen complements—not replaces—malware analysis, vulnerability scanning, signatures, code review, and sandboxing.
The 2026 HalluSquatting research demonstrated that hallucinated resource identifiers can be predictable and transferable across models, with reported hallucination rates up to 85% in repository cloning scenarios and 100% in some skill-installation scenarios. The authors demonstrated remote tool execution and remote code execution against production agent applications.
This extends an already measured software-supply-chain problem: a USENIX Security 2025 Distinguished Paper generated 576,000 code samples and found average package-hallucination rates of at least 5.2% for commercial models and 21.7% for open-source models, including 205,474 unique nonexistent package names.
FirstSeen turns that research into a small, composable control developers can run locally, in an agent toolchain, or at the pull-request boundary.
- Temporal provenance.
knownBeforeflags a resource that appeared after a model, prompt, or review boundary—when simple “exists now” checks can be defeated by squatting. - Pre-execution. Scan an AI response, README, agent instruction, shell script, manifest, workflow, or explicit resource before install or execution.
- Cross-ecosystem. npm, PyPI, crates.io, Go modules, GitHub repositories, GitHub Actions, and Docker Hub images share one policy and report format.
- Immutable-reference checks. Block mutable GitHub Action refs; optionally require container digests.
- CI-native evidence. Terminal, JSON, Markdown, standalone HTML, and SARIF 2.1.0 output.
- Local-first. No account, API key, telemetry, uploaded source, or LLM call. Registry responses are cached locally for six hours.
- Embeddable. Use the CLI or import the typed TypeScript API.
Requires Node.js 20 or newer.
Install the current release from GitHub Marketplace:
- uses: Abhinav0905/firstseen@v0.1.0
with:
path: '.'
format: sarif
output: firstseen.sarif
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}git clone https://github.com/Abhinav0905/firstseen.git
cd firstseen
npm ci
npm run build
# Scan a repository
node dist/cli.js scan /path/to/repository
# Check references before running an AI-generated command
node dist/cli.js check npm:express@5.1.0 pypi:requests==2.32.4
# Pipe an agent response into the scanner
pbpaste | node dist/cli.js scan -
# Add policy and GitHub workflow files
node dist/cli.js initThe npm distribution is intentionally not advertised until trusted publishing is configured and the package is live on the registry.
Exit code 0 means no finding met the configured failure threshold, 1 means policy
failed, and 2 means the CLI itself could not run.
flowchart LR
A["Code, config, docs, or agent output"] --> B["Deterministic reference extraction"]
B --> C["Canonical registry lookup"]
C --> D["Temporal + immutability policy"]
D --> E["PASS"]
D --> F["REVIEW"]
D --> G["BLOCK"]
E --> H["Terminal / JSON / Markdown / HTML / SARIF"]
F --> H
G --> H
- Extract software references and their file/line locations without executing the input.
- Query the canonical registry with bounded timeouts and retries, or use cached evidence offline.
- Evaluate existence, age, the
knownBeforeboundary, version/ref resolution, archive state, and pinning rules. - Emit a stable report for people, automation, or GitHub code scanning.
See Architecture for component and extension details.
| Resource | Examples detected | Evidence source |
|---|---|---|
| npm | package.json, npm install, npx, pnpm, Yarn |
npm registry |
| PyPI | requirements files, pyproject.toml, pip, uv, Poetry |
PyPI JSON API |
| crates.io | Cargo.toml, cargo add |
crates.io API |
| Go | go.mod |
Go module proxy |
| GitHub | repository URLs and explicit checks | GitHub API |
| GitHub Actions | uses: owner/repo@ref |
GitHub API + commit resolution |
| Containers | Dockerfile FROM and explicit checks |
Docker Hub API |
The extractor scans common source, configuration, shell, and documentation formats. Files larger than 2 MB, symlinks, binary formats, generated output, and ignored paths are skipped.
.firstseen.yml is deliberately small:
version: 1
policy:
minimumAgeDays: 30
# Optional: a model cutoff, session start, or review boundary.
knownBefore: '2026-07-01T00:00:00Z'
requirePinnedActions: true
requirePinnedContainers: false
minimumGitHubStars: 0
onUnverifiable: review # pass | review | block
failOn: high # info | low | medium | high | critical
allow:
- 'npm:@my-company/*'
ignore:
- '**/node_modules/**'
- '**/fixtures/**'knownBefore is the core HalluSquatting control. If an AI response was generated on July
1 and a referenced repository was created on July 3, “the repository exists” is not
enough; FirstSeen emits FS006 and blocks it.
Temporal rules apply only when the canonical provider exposes a reliable creation
timestamp. The current Go module proxy provider verifies module and version existence but
does not expose project creation time, so FS002 and FS006 are not evaluated for Go
modules.
Allow rules are exact or * wildcard resource IDs. Keep them narrow and review them like
executable policy. See Rules for every signal and remediation.
Use this repository as a composite action:
- uses: Abhinav0905/firstseen@v0.1.0
with:
path: '.'
format: sarif
output: firstseen.sarif
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}Or build the CLI from source and upload SARIF to GitHub code scanning.
node dist/cli.js init creates a full workflow you can edit.
node dist/cli.js scan . --format json --output firstseen.json
node dist/cli.js scan . --format markdown --output firstseen.md
node dist/cli.js scan . --format html --output firstseen.html
node dist/cli.js scan . --format sarif --output firstseen.sarif
node dist/cli.js scan . --offlineThe HTML format is a single portable file with no scripts, remote assets, or tracking. SARIF findings include stable rule IDs and physical source locations.
import {
createRegistryProviders,
defaultPolicy,
parseExplicitReference,
scanResources,
} from 'firstseen';
const report = await scanResources(
[parseExplicitReference('npm:lodash@4.17.21')],
defaultPolicy,
createRegistryProviders(),
{ cwd: process.cwd() },
);All public report, policy, resource, evidence, and provider types are exported.
FirstSeen does not determine whether an existing package is benign, whether an old account was compromised, or whether a pinned artifact contains malware. Resource age and popularity can help triage; neither is a security guarantee. Read the threat model before using FirstSeen as a required control.
- Spira et al., Beware of Agentic Botnets: Scalable Untargeted Promptware Attacks via Universal and Transferable Adversarial HalluSquatting, 2026.
- Spracklen et al., We Have a Package for You! A Comprehensive Analysis of Package Hallucinations by Code Generating LLMs, USENIX Security 2025 Distinguished Paper.
- OWASP, MCP Security Cheat Sheet, for related agent supply-chain, tool-poisoning, and least-privilege risks.
FirstSeen is an independent open-source implementation and is not affiliated with the authors or organizations above.
Good first contributions include new fixture cases, parsers for additional manifests, registry providers, and research-backed policy rules. Start with CONTRIBUTING.md and the roadmap.
Please report suspected vulnerabilities privately according to SECURITY.md.
Apache-2.0 © 2026 Kumar Abhinav. See LICENSE.