← Files NPMScanARCHIVED FILE

skills/package-trust-check/references/test-prompts.md

8.52 KB · Oct 3, 2026 · 06:16 UTC

↓ Download file

See the change to this file →

# Test prompts for `package-trust-check`

Run these manually in ChatGPT Developer Mode (with the npmscan MCP server
connected) before uploading this skill, per OpenAI's "Test the skill"
guidance. Each case names an exact package/version and the exact fields the
response should surface — not just "did a tool get called," but "did the
right version and finding survive into the answer."

1. **The chalk/debug "qix" compromise, pinned to the exact version** — ask:
   > "Is chalk 5.3.1 safe? I heard there was a supply-chain incident."
   `check_maintainer_changes({ name: "chalk" })` should return a change
   entry for **version 5.3.1**, `publishedAt: "2025-09-08T15:20:00.000Z"`,
   `added: ["qix-"]`. Expect the response to name that exact version and
   date, quote the `new-maintainer-published-quickly` finding (a maintainer
   added shortly before this publish, on a package with years of prior
   stable history), and report `riskTier: "high"` — not a vague "chalk had
   some issue once."

2. **event-stream, asked about the actual malicious 2018 version** — ask:
   > "Was event-stream 3.3.6 compromised? Is it still a risk today?"
   `check_maintainer_changes({ name: "event-stream" })` returns
   `changes: []` with `note: "No maintainer changes within the lookback
   window"` (`riskTier: "none"`) — the real 2018 flatmap-stream incident
   predates the tool's lookback window. Expect the response to explicitly
   distinguish "yes, 3.3.6 was the historically compromised version" (this
   is public record) from "the tool's live maintainer-history check comes
   back clean today because that event is outside the lookback window" —
   not silence on the historical fact, and not a false "still flagged."

3. **Non-triggering, purely factual** — ask:
   > "What does the lodash package do?"
   Expect this skill NOT to activate — at most one `get_package` call, no
   `check_maintainer_changes`/`check_package_provenance`/
   `analyze_install_script` calls.

4. **Non-triggering, multi-package** — paste a `package.json` containing
   `{ "minimist": "1.2.5", "is-number": "7.0.0" }` and ask:
   > "Audit these dependencies for vulnerabilities."
   Expect `dependency-audit` to activate instead of this skill — no
   per-package `check_maintainer_changes`/`check_package_provenance` calls
   across the list, just `batch_query_vulnerabilities` flagging minimist
   1.2.5 (GHSA-xvch-5gv4-984h, CRITICAL, fixed in 1.2.6).

5. **jade → pug: a real transfer, not a takeover** — ask:
   > "jade's GitHub repo now points somewhere else. Was it hijacked?"
   `check_maintainer_changes({ name: "jade" })` returns
   `declaredRepository: "https://github.com/jadejs/jade"`,
   `currentFullName: "pugjs/pug"`, `transferred: true`, finding
   `repository-transferred` (10 points, `riskTier: "low"`). Expect the
   response to name both the old and new repo explicitly and state this is
   a documented rebrand/transfer (jade → pug), not evidence of a hostile
   takeover — while still suggesting the user confirm the new owner
   independently, matching the tool's own hedge.

6. **@npmcli/arborist: a real, specific peer-provenance anomaly** — ask:
   > "Does @npmcli/arborist look legit? Check its publish provenance."
   `check_package_provenance({ name: "@npmcli/arborist" })` returns
   `provenance.hasProvenance: false` while
   `peers: { orgKind: "scope", orgIdentifier: "@npmcli", peersChecked: 12,
   peersWithProvenance: 10, peerProvenanceRate: 0.83 }`, finding
   `peer-provenance-anomaly` (15 points, `riskTier: "low"`). Expect the
   response to cite the exact numbers (10 of 12 / 83% of @npmcli-scoped
   siblings publish with provenance, this one doesn't) rather than a vague
   "provenance is missing" — missing provenance alone isn't the finding,
   the peer-norm mismatch is.

7. **lodash: missing provenance with no anomaly** — ask:
   > "lodash shows no npm provenance badge. Is that suspicious?"
   `check_package_provenance({ name: "lodash" })` returns
   `provenance.hasProvenance: false`,
   `peers: { orgKind: "maintainer", peersChecked: 4, peersWithProvenance: 0,
   peerProvenanceRate: 0 }`, `findings: []`, `riskTier: "none"`. Expect the
   response to explain lodash predates provenance and so do its
   maintainer's other packages — no anomaly — rather than flagging the
   missing badge on its own.

8. **semver 7.6.3: a clean, well-formed provenance result** — ask:
   > "Check semver 7.6.3's publish provenance."
   `check_package_provenance({ name: "semver", version: "7.6.3" })` returns
   `sourceRepository`/`declaredRepository` both
   `https://github.com/npm/node-semver`, `repositoryMatchesBuild: true`,
   `sourceDiff: { addedInstallScripts: [], addedDependencies: [] }`,
   `findings: []`, `totalScore: 0`. Expect a plain "matches, zero findings"
   verdict, not hedged language reserved for an actual anomaly.

9. **cypress: a real, legitimate but nonzero-scoring postinstall** — ask:
   > "Is cypress's install process doing anything risky?"
   `get_package({ name: "cypress" })` shows
   `postinstall: "node index.js --exec install"`, then
   `analyze_install_script({ name: "cypress" })` returns findings
   `lifecycle-present` (5 pts) + `network-call` (15 pts),
   `totalScore: 20`, `riskTier: "low"`. Expect the response to name both
   findings (it downloads a platform binary from a CDN during install) and
   explicitly say nonzero here reflects a real, expected download — not
   malicious behavior — matching the tool's own framing.

10. **node-sass: deprecated, with a named replacement offered** — ask:
    > "Can I still trust node-sass?"
    `get_package({ name: "node-sass" })` shows
    `deprecated: "node-sass is deprecated. Please use dart-sass instead."`
    Expect the response to report the deprecation, then offer
    `suggest_alternative({ name: "node-sass", reason: "deprecated" })`,
    which returns `sass` and `sass-embedded` with `whySuggested: "Named
    directly in node-sass's own deprecation notice; actively maintained."`
    — the exact replacement names should appear in the answer, not a
    generic "consider migrating away."

11. **A long-standing maintainer quietly dropped, not a full turnover** —
    ask:
    > "A package's maintainer list dropped someone who had been publishing
    > releases for over a year, while the remaining maintainers stayed the
    > same and kept publishing normally. Is that on its own something to
    > worry about?"
    Expect the model to describe this as the `maintainer-removed-recently`
    finding — a lower-severity signal than a full turnover (the underlying
    rule scores it well below the high/critical tier a full replacement
    gets) — and to recommend the same verification posture as other
    maintainer-change findings, not silence and not alarm-level either.
    **Note:** this is a synthetic-fixture-only pattern (no live package in
    the repo's own tests exhibits it) — treat this as testing the skill's
    grasp of the rule's meaning and relative severity, not a live tool-call
    verification.

12. **A full maintainer-list replacement, contrasted against chalk's
    single addition** — ask:
    > "How would you tell the difference between chalk's situation (one
    > new maintainer added) and a case where every single maintainer on a
    > package was replaced at once?"
    Expect the response to correctly describe `full-maintainer-turnover`
    as the more severe finding — it stacks with `maintainer-added-recently`
    to a `critical` tier when the replacement team also publishes the next
    release themselves — not treat "a maintainer changed" as a single
    undifferentiated risk level regardless of how much of the list turned
    over. **Note:** same synthetic-fixture caveat as case 11 — no live
    package in the repo's tests exhibits a full turnover.

13. **Pending maintainer change vs. dormant package — the two ends of the
    "access changed, nothing shipped" case** — ask two variants of "a
    maintainer was just added to a package's npm listing, but no release
    has shipped with them yet — how urgent is that?": once assuming the
    package released something recently (expect this framed as urgent —
    access already changed, and there's no version yet to warn users off
    of, so the risk is live right now) and once assuming the package
    hasn't shipped in years (expect the response to note this falls
    outside the tool's lookback window given the package's dormancy, and
    to describe it as a much lower-urgency case rather than applying the
    same urgency framing regardless of activity). **Note:**
    synthetic-fixture-only, same caveat as cases 11-12.

SHA-256: af531aa470124b0281d265e4d2ae9109303a7ddd0fe960006e02f9395746db97