← NPMScanCONTENT HISTORY

Update to NPMScan

Snapshot Sep 30, 2026 · 22:58 UTC · version 2.0.0

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "name": "package-trust-check",
  "description": "Investigate whether one specific npm package is trustworthy — maintainer/ownership takeover signals, publish-provenance mismatches, and risky install scripts. Use when the user asks if a single named package is safe, compromised, hijacked, suspicious, or \"can I trust this\" — not for auditing a full package.json/lockfile (see dependency-audit) and not for a plain factual question like \"what does X do.\"",
  "included_files": [
    {
      "relative_path": "agents/openai.yaml",
      "size_in_bytes": 270
    },
    {
      "relative_path": "references/test-prompts.md",
      "size_in_bytes": 6156
    }
  ],
  "skill_md_contents": "---\nname: package-trust-check\ndescription: Investigate whether one specific npm package is trustworthy — maintainer/ownership takeover signals, publish-provenance mismatches, and risky install scripts. Use when the user asks if a single named package is safe, compromised, hijacked, suspicious, or \"can I trust this\" — not for auditing a full package.json/lockfile (see dependency-audit) and not for a plain factual question like \"what does X do.\"\n---\n\n# Package trust check\n\nUse this skill when the user names **one specific package** (optionally a\nversion) and asks a trust question about it — \"is X safe to use,\" \"was X\ncompromised,\" \"should I be worried about X,\" \"check X's maintainers.\" This\nis a deep, single-package investigation: it runs checks dependency-audit\ndeliberately skips for every package in a batch because they're too\nexpensive to run at scale.\n\nIf the user instead pastes a `package.json`/lockfile/dependency list or asks\nto audit multiple packages, use the `dependency-audit` skill instead — don't\nrun this skill's checks across a whole inventory. If the question is purely\nfactual with no trust/safety angle (\"what does lodash do,\" \"what's the\nlatest version of express\"), just answer directly with `get_package` — don't\ninvoke the full investigation for that.\n\n## Steps\n\n1. Baseline with `get_package` (or `get_package_version` if the user gave an\n   exact version). Pull `deprecated`, `maintenanceSummary`,\n   `possibleTyposquatOf`, `isLatestVersionVulnerable`/`highestSeverity`,\n   `downloadTrend`, and days-since-last-publish. This alone answers a good\n   chunk of \"should I trust this\" and grounds the deeper checks that follow —\n   don't skip straight to the maintainer/provenance tools without it.\n2. Call `check_maintainer_changes({ name })`. It reconstructs maintainer\n   add/remove history from the npm packument and flags:\n   - a maintainer added recently who then published shortly after (the\n     account-takeover pattern behind the Sept 2025 chalk/debug \"qix\"\n     compromise and ua-parser-js),\n   - a full sudden replacement of the maintainer list,\n   - a long-standing maintainer quietly dropped,\n   - a maintainer-list change on npm not yet tied to any release — flag this\n     as the *more* urgent case, since access changed hands but nothing has\n     shipped with it yet, so there's no version to warn the user off of.\n   Also reports GitHub repository transfer/archival — a transfer isn't\n   automatically hostile (e.g. jade → pug was a documented rename), say so\n   rather than treating every transfer as a red flag.\n3. Call `check_package_provenance({ name, version })`. Three checks in one\n   call: does the Sigstore build attestation's source repo/commit match\n   `package.json`'s declared repository; is this version missing provenance\n   while its npm-scope or maintainer peers consistently publish with it (a\n   real anomaly, not just \"no provenance\" — plenty of legitimate packages\n   predate the feature entirely, which this tool already accounts for via\n   the peer baseline); and does the tarball's actual install scripts/\n   dependencies match what's committed at the attested source commit — a\n   script or dependency on npm that was never committed in source is the\n   stolen-npm-token publish pattern. This is structural verification, not a\n   cryptographic re-check of the Sigstore bundle — say so if the user asks\n   how deep it goes.\n4. If `get_package`/`get_package_version` in step 1 showed\n   `hasLifecycleScripts`/a `preinstall`/`postinstall`/`prepare` entry, follow\n   up with `analyze_install_script({ name, version })`. It fetches the\n   published tarball and statically scans the script — and the files it\n   references — against npmscan's red-flags rubric (child_process,\n   network calls, `.ssh`/`.aws`/`.npmrc`/`*TOKEN`/`*KEY` access,\n   obfuscation, remote binaries off untrusted hosts, exfil endpoints,\n   eval-on-decoded-content), returning a `totalScore`/`riskTier`. A nonzero\n   score isn't automatically malicious — a legitimate binary download (e.g.\n   `cypress`) scores nonzero too — so report the actual `findings`, not just\n   the score.\n5. If the combined picture ends up genuinely concerning (a maintainer-\n   takeover pattern, a provenance mismatch, a `possibleTyposquatOf` hit, or a\n   critical install-script finding), offer — don't force —\n   `suggest_alternative({ name, reason })` with `reason` set to whichever of\n   `\"vulnerable\"`/`\"abandoned\"`/`\"typosquat\"`/`\"general\"` best fits, so the\n   user has a next step instead of just a warning.\n6. Produce one findings report, most-concerning signal first:\n   - State the verdict per check plainly (e.g. \"no maintainer-change red\n     flags in the lookback window,\" not silence-as-clean).\n   - Every finding from `check_maintainer_changes`/`check_package_provenance`\n     is a hedged signal meant to prompt verification, not proof — say\n     \"worth verifying independently,\" matching the tools' own language,\n     especially for anything below their `high`/`critical` tiers.\n   - Include the `npmscanUrl` so the user can read the full write-up.\n   - If nothing turned up anything but a low/none `riskTier` and no maintainer\n     or provenance findings, say so plainly — this skill exists to give\n     confident \"looks clean\" answers as often as it flags real risk.\n\n## Do not\n\n- Do not run this skill's checks across every package in a list — that's\n  `dependency-audit`'s job, and `check_maintainer_changes`/\n  `check_package_provenance` are deliberately reserved there for\n  already-flagged packages only, not a full inventory.\n- Do not treat a missing `provenance` field, a repository transfer, or a\n  single maintainer addition as confirmed compromise on its own — report\n  what the tool actually flagged (or didn't) and let the `riskTier`/points\n  speak, don't editorialize past it.\n- Do not skip `get_package` and jump straight to the deep checks — the\n  baseline (deprecated, popularity/maintenance tiers, typosquat) is cheap\n  and often already answers the question.\n- Do not invent a replacement package name yourself — let\n  `suggest_alternative` return its own `whySuggested`/`nonPackageAlternatives`\n  rather than guessing.\n- Do not silently skip `analyze_install_script` when lifecycle scripts exist\n  just because `check_maintainer_changes`/`check_package_provenance` came\n  back clean — a legitimate maintainer can still ship a genuinely risky\n  script, and vice versa; report all applicable signals, not just whichever\n  ran first.\n\n## Tools used\n\n`get_package`, `get_package_version`, `check_maintainer_changes`,\n`check_package_provenance`, `analyze_install_script`, `suggest_alternative`\n— see `agents/openai.yaml` for the MCP server dependency, and\n`references/test-prompts.md` for the test cases to run in ChatGPT Developer\nMode before submitting.\n"
}

SHA-256: 4e523827d515f82190f02bf0df5a18b006f9856961847afc619da127639dd1a6