Skip to content

Evidence ​

Securock stores evidence on each artifact in securock.lock. Reading those states correctly is how you decide whether a package is trusted under policy, merely unchecked, or actively failing a rule.

trusted still means “passed the active policy,” not “proven safe.” See the Trust model for the full matrix.

Provenance, signature, and chain states ​

StateMeaning
unknownLookup skipped or failed.
missingLookup succeeded and found nothing.
presentRegistry returned provenance, signatures, or a trust chain. Not cryptographically verified.
verifiedCryptographic verification succeeded and the subject digest matches the lockfile.

Provenance, signature, and chain use these states. npm evidence can reach verified when registry keys / Sigstore roots are available and the locked digest binds to the signed artifact.

How to read them:

  • unknown — do not treat as clean. Offline mode and private registries leave many axes here.
  • missing — Securock looked and found no attestation or signature.
  • present — material exists but was not cryptographically verified (or verification did not bind the digest).
  • verified — crypto check succeeded and matches the lockfile digest.

require_provenance: true accepts present or verified. To require cryptographic verification, set minimum: verified under policy (or use --profile strict). See Policy.

Vulnerability and malicious states ​

StateMeaning
unknownOSV was not queried (offline, private registry, or error).
checkedOSV was queried. Vulns use items; malware uses reports (MAL-*).

Malicious package reports are not vulnerabilities. A package with no CVEs can still be malware. The default policy denies both.

Default policy treats unknown as unknown trust, not trusted.

Capability, behavior, and ownership ​

Capability, behavior, and ownership use the same unknown / checked states. Depth depends on the ecosystem.

npm family (npm / pnpm / Yarn / Bun / Deno npm) ​

Securock records:

  • install scripts and native-code hints from the registry
  • publisher and maintainers
  • network, filesystem, environment, and shell indicators from published package sources
  • finer-grained hosts, paths, commands, and env vars as behavior
  • source → build → artifact fields from provenance attestations as chain (source, commit, ref, builder, workflow, predicate type)

Capability detection uses install-script and native-build metadata, then a deterministic scan of published JS/TS sources. It is not a full behavioral sandbox and may under-report obfuscated code.

Provenance verification for npm only accepts SLSA predicate types (https://slsa.dev/provenance/v0.1, v0.2, and v1). Policy can further limit accepted sources, builders, workflows, refs, and predicate types via allow_* lists under rules.provenance; those lists require a verified trust chain.

PyPI (uv / Poetry / PDM) ​

Securock queries the Integrity API, reconstructs each PEP 740 attestation into a Sigstore bundle, and re-verifies it against the public-good trust root (signer identity, artifact filename and digest, DSSE signature, transparency log). A successful check records provenance/signature verified with Trusted Publisher and certificate identity on the chain; otherwise attestations remain present.

Other ecosystems ​

Digest comes from the language lockfile. OSV runs when public-only can prove a public origin. Provenance, signature, capability, behavior, ownership, and chain usually stay unknown.

Release health ​

Health describes the release itself rather than who published it. It is recorded for npm-family packages and PyPI:

FieldSource
releasedPublish day (YYYY-MM-DD). npm: the package document; PyPI: file upload
deprecatedThe maintainers' deprecation message, or yanked and its reason on PyPI
licenseDeclared license, preferably an SPDX expression

health is omitted from the lockfile when the registry did not answer (offline, private registry, unsupported ecosystem), so absence means "not checked", never "healthy". For npm, the release day comes from the package document. For packages whose document exceeds the 2 MiB response limit, which is typical of those with very long histories (react, typescript, webpack), it comes from one small deps.dev lookup instead, and only for packages from the public npm registry. If that fails too, released is omitted.

Health is informational: a change in released or license is not trust drift. It affects trust only through the policy rule health.

securock audit turns health into findings, and adds a name check that needs no registry:

FindingSeverityWhen
deprecated-packagemediumThe release is deprecated or yanked
stale-releaselowThe release is more than two years old
typosquat-suspectlownpm or PyPI name within one edit of a popular package
recent-releasehighNewer than --min-release-age (off unless you set it)

typosquat-suspect compares each name against a built-in list of popular packages (separator variants such as lo-dash, or one typo, swap, or missing letter). Scoped npm names are skipped. It is a signal to look at, not proof: a real package can have a name close to a popular one, so it is a low finding and the built-in lists of about 400 popular names per ecosystem are kept to names that exist. Use securock accept to record that you checked, or list the name under typosquat_allow in the policy if you deny typosquats.

Release cooldown ​

A freshly published malicious version is usually caught within days, so waiting a little before adopting a release removes most of that risk. securock audit --min-release-age 7d reports every npm and PyPI release published more recently than that as a high finding (recent-release), so it fails --fail-on high by default. The age is a day count (7d) or a duration (72h).

It is a report-time check, not a policy rule, on purpose: whether a release is "too new" changes as time passes, and trust status in the lockfile must not. The registry gives only the release day, so a release counts from the start of that day. A release whose date is unknown (offline, or a registry that does not answer) cannot be judged: it is not flagged as recent, but audit reports it as an info finding, release-date-unknown, so that silence is not mistaken for "old enough".

Offline and private registries ​

--offline leaves remote evidence unknown. Private registries are not queried in the default public-only network mode. Details: Privacy.

Next steps ​

  • Policy — require floors and allowlists
  • Ecosystems — where each evidence axis is collected
  • Trust model — trusted / untrusted / unknown

Released under the Apache-2.0 License. Pre-1.0: all lockfile resolvers are stable.