@preventive/triage 1.0.0-alpha.5 → 1.0.0-alpha.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-APACHE +202 -0
- package/README.md +16 -0
- package/api/reap.ts +17 -0
- package/cli.js +6 -0
- package/client/dependency-paths.d.ts +3 -0
- package/client/dependency-paths.js +36 -0
- package/client/finding-link.js +305 -0
- package/client/linked-findings.d.ts +1 -0
- package/client/linked-findings.js +115 -0
- package/common/bundle-commit.d.ts +1 -0
- package/common/bundle-commit.js +4 -0
- package/common/bundle-compare-diff.d.ts +3 -0
- package/common/bundle-compare-diff.js +357 -0
- package/common/bundle-compare-inputs.d.ts +2 -0
- package/common/bundle-compare-inputs.js +65 -0
- package/common/bundle-compare-versions.js +172 -0
- package/common/bundle-comparison.d.ts +8 -0
- package/common/bundle-comparison.js +62 -0
- package/common/bundle-metadata.d.ts +15 -0
- package/common/bundle-metadata.js +226 -0
- package/common/bundle-pkg-of.d.ts +1 -0
- package/common/bundle-pkg-of.js +90 -0
- package/common/bundle-reasons.d.ts +2 -0
- package/common/bundle-reasons.js +21 -0
- package/common/bundle-source-links.d.ts +6 -0
- package/common/bundle-source-links.js +216 -0
- package/common/bundle-sourcemap.d.ts +10 -0
- package/common/bundle-sourcemap.js +100 -0
- package/common/bundle-sources.d.ts +7 -0
- package/common/bundle-sources.js +333 -0
- package/common/bundle-stats.js +41 -0
- package/common/bundle-tabs.js +1 -0
- package/common/code-language.js +65 -0
- package/common/default-scan-models.ts +31 -0
- package/common/dependency-reviews.d.ts +18 -0
- package/common/dependency-reviews.js +64 -0
- package/common/finding-duplicates.js +58 -0
- package/common/finding-filters.js +274 -0
- package/common/finding-id.js +47 -0
- package/common/github-issue-labels.d.ts +1 -0
- package/common/github-issue-labels.js +11 -0
- package/common/github-pr.ts +56 -0
- package/common/gzip.js +59 -0
- package/common/line-diff.d.ts +8 -0
- package/common/line-diff.js +57 -0
- package/common/linked-workspace-groups.js +63 -0
- package/common/managed/agent-tasks.ts +292 -0
- package/common/managed/comments.ts +34 -0
- package/common/managed/finding-detail.d.ts +3 -0
- package/common/managed/finding-detail.js +66 -0
- package/common/managed/github-agents.ts +114 -0
- package/common/managed/github-logins.ts +49 -0
- package/common/managed/npm-packages.d.ts +7 -0
- package/common/managed/npm-packages.js +51 -0
- package/common/managed/permissions.ts +31 -0
- package/common/managed/report-content.ts +72 -0
- package/common/managed/report-filter.ts +109 -0
- package/common/managed/repository-alias.ts +65 -0
- package/common/managed/roles.ts +35 -0
- package/common/managed/routes.d.ts +2 -0
- package/common/managed/routes.js +359 -0
- package/common/managed/scan-models.ts +6 -0
- package/common/managed/team-app.d.ts +6 -0
- package/common/managed/team-app.js +47 -0
- package/common/managed/triage.ts +83 -0
- package/common/managed/upload-seal.ts +126 -0
- package/common/pretty-print.d.ts +5 -0
- package/common/pretty-print.js +24 -0
- package/common/revalidation-conflicts.js +48 -0
- package/common/revalidation-input-groups.js +56 -0
- package/common/save-error-reason.ts +20 -7
- package/common/scan-server.ts +13 -0
- package/common/security-links.d.ts +5 -0
- package/common/security-links.js +33 -0
- package/common/server-info.ts +46 -0
- package/common/utf8.d.ts +3 -0
- package/common/utf8.js +45 -0
- package/common/workspace-app.js +39 -0
- package/common/workspace-groups.js +176 -0
- package/out/activity.js +4 -0
- package/out/brotli-fallback.js +3 -3
- package/out/chunk-2K6UN3PC.js +3 -0
- package/out/chunk-2XUEZHIP.js +28 -0
- package/out/chunk-2ZDZWLFY.js +1 -0
- package/out/chunk-4HI2MSAV.js +17 -0
- package/out/chunk-6LNQTKAV.js +52 -0
- package/out/chunk-7BKKYVWR.js +7 -0
- package/out/chunk-7C7DWL7I.js +1 -0
- package/out/chunk-7JBSSRD7.js +3 -0
- package/out/chunk-7VAWINQF.js +6 -0
- package/out/chunk-C4Z6ZBXV.js +10 -0
- package/out/chunk-FMXWXDR4.js +36 -0
- package/out/chunk-GDPCLSOS.js +2 -0
- package/out/chunk-GO7FT4OD.js +1 -0
- package/out/chunk-HT2SSA3V.js +1 -0
- package/out/chunk-IPAH4LKF.js +232 -0
- package/out/chunk-IYPY47MC.js +1 -0
- package/out/chunk-IZ7POWI3.js +18 -0
- package/out/chunk-JCIIBLKR.js +1 -0
- package/out/chunk-KOGNQDSJ.js +1 -0
- package/out/chunk-NRPC74AM.js +1 -0
- package/out/chunk-OOJM4CTU.js +1 -0
- package/out/chunk-PBZPYIG7.js +1 -0
- package/out/chunk-PNHBZGDD.js +1 -0
- package/out/chunk-PWFUOLZK.js +17 -0
- package/out/chunk-PXK7EU4V.js +1 -0
- package/out/chunk-QB4CBOX2.js +1 -0
- package/out/chunk-R3NZFXVR.js +1 -0
- package/out/chunk-R5O6FAW4.js +2 -0
- package/out/chunk-SXV2T5C4.js +80 -0
- package/out/chunk-TQJDYHVE.js +2 -0
- package/out/chunk-TUII34K2.js +1 -0
- package/out/chunk-VDRXHIHN.js +3 -0
- package/out/chunk-VFWMQ3LG.js +2 -0
- package/out/chunk-VH4XMZIW.js +2 -0
- package/out/chunk-WCPJDAYA.js +10 -0
- package/out/chunk-WFYLMF6Z.js +10 -0
- package/out/chunk-WRAJVD35.js +1 -0
- package/out/chunk-WYLQWYLA.js +1 -0
- package/out/client-managed-import.js +4 -0
- package/out/client-managed.js +33 -0
- package/out/client-sync.js +11 -17
- package/out/compare.js +35 -0
- package/out/dialogs.js +55 -0
- package/out/github-issue-authorized.html +3 -0
- package/out/github-issue-authorized.js +1 -0
- package/out/graph.js +17 -4
- package/out/index.html +90 -8
- package/out/prism.js +14 -10
- package/out/scan.js +2 -0
- package/out/stasis.svg +20 -0
- package/out/terminal.js +366 -39
- package/out/view.css +1 -1
- package/out/view.js +19 -144
- package/package.json +364 -59
- package/risk/actions/findings.js +161 -0
- package/risk/actions/resolve.js +219 -0
- package/risk/actions/scripts/commands.js +182 -0
- package/risk/actions/scripts/grade.js +113 -0
- package/risk/actions/scripts/packages.js +123 -0
- package/risk/actions/scripts/shell.js +169 -0
- package/risk/actions/uses.js +76 -0
- package/risk/actions/workflow.js +110 -0
- package/risk/files/characters.js +196 -0
- package/risk/files/hosts.js +205 -0
- package/risk/files/readability.js +177 -0
- package/risk/files/runs-code.js +615 -0
- package/risk/files/script.js +118 -0
- package/risk/files/stamps.js +47 -0
- package/risk/index.d.ts +254 -0
- package/risk/index.js +11 -0
- package/risk/npm/assess.js +285 -0
- package/risk/npm/combined.js +68 -0
- package/risk/npm/compare.js +257 -0
- package/risk/npm/dependencies.js +172 -0
- package/risk/npm/diff.js +79 -0
- package/risk/npm/downloads.js +84 -0
- package/risk/npm/files.js +445 -0
- package/risk/npm/held.js +63 -0
- package/risk/npm/install-scripts.js +34 -0
- package/risk/npm/malware.js +36 -0
- package/risk/npm/manifest.js +65 -0
- package/risk/npm/new-dependency.js +60 -0
- package/risk/npm/old-version.js +108 -0
- package/risk/npm/registry.js +388 -0
- package/risk/npm/release.js +85 -0
- package/risk/npm/score.js +59 -0
- package/risk/npm/specs.js +124 -0
- package/risk/npm/tarball.js +96 -0
- package/server-common/database-config.ts +16 -0
- package/server-common/initialize.ts +18 -0
- package/server-common/npm-advisories.ts +101 -0
- package/{server → server-common}/origin.ts +5 -5
- package/server-common/reap.ts +48 -0
- package/server-common/scan-config.ts +19 -0
- package/server-common/standalone.ts +29 -0
- package/server-common/storage-crypto.ts +182 -0
- package/server-common/storage-log.ts +38 -0
- package/server-common/vercel-blob.ts +103 -0
- package/server-e2e/app.ts +487 -0
- package/{server → server-e2e}/bus-receiver.ts +2 -1
- package/{server → server-e2e}/cli.js +9 -4
- package/{server → server-e2e}/config.ts +50 -42
- package/{server → server-e2e}/db-neon.ts +2 -2
- package/{server → server-e2e}/db-revision-sql.ts +1 -1
- package/{server → server-e2e}/db-stmt.ts +2 -2
- package/{server → server-e2e}/db.ts +7 -7
- package/{server → server-e2e}/http.ts +44 -13
- package/{server → server-e2e}/hub.ts +40 -9
- package/server-e2e/index.ts +17 -0
- package/server-e2e/lifecycle.ts +95 -0
- package/{server → server-e2e}/neon-driver.ts +2 -2
- package/{server → server-e2e}/npm-proxy.ts +12 -145
- package/{server → server-e2e}/objstore/blob-vercel.ts +10 -114
- package/{server → server-e2e}/objstore/blob.ts +1 -1
- package/server-e2e/objstore/fetch-mint-guard.ts +74 -0
- package/{server → server-e2e}/objstore/handlers.ts +9 -8
- package/{server → server-e2e}/objstore/init.ts +19 -27
- package/{server → server-e2e}/objstore/reaper.ts +1 -1
- package/server-e2e/objstore/rest-deny.ts +28 -0
- package/server-e2e/objstore/rest-mint.ts +224 -0
- package/{server → server-e2e}/objstore/rest.ts +3 -3
- package/{server → server-e2e}/objstore/store-neon.ts +6 -10
- package/{server → server-e2e}/objstore/store.ts +7 -7
- package/{server → server-e2e}/objstore/tokens.ts +2 -2
- package/{server → server-e2e}/pubsub.ts +12 -9
- package/{server → server-e2e}/sign.ts +4 -4
- package/{server → server-e2e}/sse-server.ts +60 -33
- package/{server → server-e2e}/static.ts +31 -21
- package/{server → server-e2e}/sync-handlers.ts +64 -30
- package/{server → server-e2e}/ws-server.ts +20 -9
- package/server-managed/activity.ts +258 -0
- package/server-managed/agent-merges.ts +109 -0
- package/server-managed/app-agents.ts +23 -0
- package/server-managed/avatar-store.ts +13 -0
- package/server-managed/blob-store.ts +17 -0
- package/server-managed/brotli.ts +10 -0
- package/server-managed/bundle-advisories.ts +120 -0
- package/server-managed/bundle-advisory-inventory.ts +77 -0
- package/server-managed/bundle-build-diagnostics.d.ts +10 -0
- package/server-managed/bundle-build-diagnostics.js +23 -0
- package/server-managed/bundle-build-leases.ts +41 -0
- package/server-managed/bundle-build-worker.js +115 -0
- package/server-managed/bundle-build.ts +200 -0
- package/server-managed/bundle-cache.ts +211 -0
- package/server-managed/bundle-catalog.ts +29 -0
- package/server-managed/bundle-commits.ts +140 -0
- package/server-managed/bundle-store.ts +24 -0
- package/server-managed/bundle-summary-cache.ts +130 -0
- package/server-managed/bundle.ts +119 -0
- package/server-managed/cache-storage.ts +20 -0
- package/server-managed/cli.js +21 -0
- package/server-managed/combined.ts +47 -0
- package/server-managed/comments.ts +151 -0
- package/server-managed/commit-coauthors.ts +106 -0
- package/server-managed/commit-lockfiles.ts +76 -0
- package/server-managed/comparison.ts +52 -0
- package/server-managed/config.ts +164 -0
- package/server-managed/content-access.ts +15 -0
- package/server-managed/crypto.ts +25 -0
- package/server-managed/db-methods.ts +1923 -0
- package/server-managed/db-neon.ts +468 -0
- package/server-managed/db-schema.ts +238 -0
- package/server-managed/db-table-names.ts +22 -0
- package/server-managed/db.ts +143 -0
- package/server-managed/dependabot-access.ts +60 -0
- package/server-managed/dependabot-alerts.ts +185 -0
- package/server-managed/dependency-review-comments.ts +98 -0
- package/server-managed/dependency-reviews.ts +364 -0
- package/server-managed/github-accounts.ts +60 -0
- package/server-managed/github-actions.ts +71 -0
- package/server-managed/github-app.ts +376 -0
- package/server-managed/github-errors.ts +70 -0
- package/server-managed/github-graphql.ts +39 -0
- package/server-managed/github-issue-links.ts +140 -0
- package/server-managed/github-issue-oauth.ts +47 -0
- package/server-managed/github-issues.ts +152 -0
- package/server-managed/github-link-oauth.ts +69 -0
- package/server-managed/github-links.ts +204 -0
- package/server-managed/github-metadata.ts +213 -0
- package/server-managed/github-oauth.ts +238 -0
- package/server-managed/github-pulls.ts +227 -0
- package/server-managed/github-requests.ts +136 -0
- package/server-managed/github-users.ts +30 -0
- package/server-managed/http-response.ts +76 -0
- package/server-managed/http.ts +5503 -0
- package/server-managed/import-triage.ts +51 -0
- package/server-managed/index.ts +192 -0
- package/server-managed/kept-briefly.ts +37 -0
- package/server-managed/kept.ts +28 -0
- package/server-managed/link-reports.ts +162 -0
- package/server-managed/listed-activity.ts +39 -0
- package/server-managed/locked-packages.ts +152 -0
- package/server-managed/lockfile-scope.ts +49 -0
- package/server-managed/lru.ts +30 -0
- package/server-managed/managed-issues.ts +78 -0
- package/server-managed/management-catalog.ts +45 -0
- package/server-managed/management.ts +99 -0
- package/server-managed/npm-delta-worker.js +23 -0
- package/server-managed/npm-delta.ts +194 -0
- package/server-managed/npm-insights.ts +449 -0
- package/server-managed/npm-kept.ts +225 -0
- package/server-managed/npm-loads.ts +264 -0
- package/server-managed/npm-manifest.ts +115 -0
- package/server-managed/npm-packages.ts +454 -0
- package/server-managed/npm-patch.ts +325 -0
- package/server-managed/npm-provenance.ts +123 -0
- package/server-managed/npm-risk.ts +285 -0
- package/server-managed/object-storage-disk.ts +148 -0
- package/server-managed/object-storage-vercel.ts +67 -0
- package/server-managed/object-storage.ts +75 -0
- package/server-managed/package-entry-points.ts +51 -0
- package/server-managed/pretty-print.ts +434 -0
- package/server-managed/public-workspace.ts +238 -0
- package/server-managed/pull-comment-reviews.ts +161 -0
- package/server-managed/pull-dependencies.ts +351 -0
- package/server-managed/pull-dependency-reviews.ts +334 -0
- package/server-managed/pull-reviews.ts +205 -0
- package/server-managed/queue.ts +39 -0
- package/server-managed/release-commits.ts +84 -0
- package/server-managed/rename-diff-worker.js +26 -0
- package/server-managed/rename-diff.ts +279 -0
- package/server-managed/repo-path.ts +21 -0
- package/server-managed/report-migration.ts +35 -0
- package/server-managed/report-query.ts +10 -0
- package/server-managed/report-response.ts +16 -0
- package/server-managed/report-sources.ts +178 -0
- package/server-managed/report-store.ts +85 -0
- package/server-managed/repository-actions.ts +218 -0
- package/server-managed/repository-agents.ts +448 -0
- package/server-managed/repository-aliases.ts +91 -0
- package/server-managed/repository-browser.ts +294 -0
- package/server-managed/repository-changes.ts +284 -0
- package/server-managed/repository-code.ts +215 -0
- package/server-managed/repository-dependency-reviews.ts +166 -0
- package/server-managed/repository-discovery.ts +82 -0
- package/server-managed/repository-history.ts +432 -0
- package/server-managed/repository-issues.ts +195 -0
- package/server-managed/repository-policy.ts +27 -0
- package/server-managed/repository-pulls.ts +212 -0
- package/server-managed/repository-pulse.ts +460 -0
- package/server-managed/repository-risk-assess.ts +105 -0
- package/server-managed/repository-risk-audit.ts +79 -0
- package/server-managed/repository-risk-read.ts +170 -0
- package/server-managed/repository-risk.ts +491 -0
- package/server-managed/repository-squashes.ts +168 -0
- package/server-managed/request-timing.ts +63 -0
- package/server-managed/reviewed-dependencies.ts +149 -0
- package/server-managed/revisions.ts +35 -0
- package/server-managed/scan-downloads.ts +87 -0
- package/server-managed/session.ts +132 -0
- package/server-managed/slugs.ts +38 -0
- package/server-managed/solidity-entry-points.ts +71 -0
- package/server-managed/sql-postgres.ts +34 -0
- package/server-managed/sql.ts +88 -0
- package/server-managed/static.ts +28 -0
- package/server-managed/storage-command.ts +16 -0
- package/server-managed/storage-db.ts +183 -0
- package/server-managed/storage-encryption.ts +290 -0
- package/server-managed/storage-maintenance.ts +259 -0
- package/server-managed/storage-payload.ts +121 -0
- package/server-managed/storage-stores.ts +91 -0
- package/server-managed/storage.ts +82 -0
- package/server-managed/team-app.ts +134 -0
- package/server-managed/team-catalog.ts +7 -0
- package/server-managed/team-feed.ts +180 -0
- package/server-managed/team-npm-scopes.ts +106 -0
- package/server-managed/team-reports.ts +319 -0
- package/server-managed/triage-response.ts +16 -0
- package/server-managed/type-only-worker.js +19 -0
- package/server-managed/type-only.ts +105 -0
- package/server-managed/uploads.ts +106 -0
- package/server-managed/upstream-cache.ts +243 -0
- package/server-managed/view-as.ts +58 -0
- package/server-managed/workspace-shares.ts +169 -0
- package/server.ts +70 -0
- package/server/index.ts +0 -480
- package/server/lifecycle.ts +0 -208
- /package/{LICENSE → LICENSE-MIT} +0 -0
- /package/{server → server-e2e}/auth.ts +0 -0
- /package/{server → server-e2e}/config.example.json +0 -0
- /package/{server → server-e2e}/objstore/blob-fs.ts +0 -0
- /package/{server → server-e2e}/objstore/fs.ts +0 -0
- /package/{server → server-e2e}/objstore/sign.ts +0 -0
- /package/{server → server-e2e}/peer.ts +0 -0
- /package/{server → server-e2e}/sse-session.ts +0 -0
- /package/{server → server-e2e}/util.ts +0 -0
- /package/{server → server-e2e}/validation.ts +0 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// How a script's text is read, for risk's readers of a file
|
|
2
|
+
// (readability.js, runs-code.js, hosts.js): JavaScript's and CSS's strings,
|
|
3
|
+
// regular expressions and comments, set apart from their code, what of their
|
|
4
|
+
// blanks a minifier drops, which files are scripts node runs, and each
|
|
5
|
+
// offset's line.
|
|
6
|
+
|
|
7
|
+
// Code minified into lines shorter than NPM_LONG_LINE: outside its strings and
|
|
8
|
+
// comments (`/* @__PURE__ */`), its lines average more than anyone writes and
|
|
9
|
+
// next to none of its spaces are ones a minifier drops. Told only in what
|
|
10
|
+
// minifiers write, as GitHub Linguist tells minified files only in JavaScript
|
|
11
|
+
// and CSS, each by its strings and comments (matched in one pass, so that
|
|
12
|
+
// neither starts inside the other, a comment with the spaces around it) and
|
|
13
|
+
// the spaces it can do without.
|
|
14
|
+
export const MINIFIED_AVERAGE = 110
|
|
15
|
+
const MINIFIED_SPACES = .01
|
|
16
|
+
// What a regular expression set aside holds.
|
|
17
|
+
const REGEX = '\uE000'
|
|
18
|
+
const JS = {
|
|
19
|
+
// A hashbang, the file's first line (`#!/usr/bin/env node`), a comment,
|
|
20
|
+
// after a byte order mark too, which node's ES module loader drops first.
|
|
21
|
+
// A string's or template's escape may be a line continuation (`\` before a
|
|
22
|
+
// line break, CRLF's whole).
|
|
23
|
+
// Linear on any text: a regular expression's context looked back on only
|
|
24
|
+
// before a `/`, a comment's leading blanks taken only from where they
|
|
25
|
+
// start, and what is left open read to where it would end, a string or a
|
|
26
|
+
// regular expression its line's end, a template or a comment the text's,
|
|
27
|
+
// rather than tried again from each later quote or slash.
|
|
28
|
+
// A regular expression first where a value starts (after `=>`, `...`, an operator or a keyword, not a property: `x.default/2`, `this.#in/2`), so a quote in it (`/["']/`) starts no string.
|
|
29
|
+
stringOrComment: /((?=\/)(?<=(?:^|\.\.\.|[(,=:[!&|?{};>+\-*/%^<~]|(?<![\p{ID_Continue}$.#])(?:await|case|default|delete|do|else|extends|in|instanceof|new|of|return|throw|typeof|void|yield))[ \t]*)\/(?![/*])(?:[^/\\[\n]|\\.|\[(?:[^\]\\\n]|\\.)*(?:\]|(?=\\?$)))+(?:\/[a-z]*|(?=\\?$))|"(?:[^"\\\n]|\\(?:\r\n|[\s\S]))*(?:"|$)|'(?:[^'\\\n]|\\(?:\r\n|[\s\S]))*(?:'|$)|`(?:[^`\\]|\\(?:\r\n|[\s\S]))*(?:`|(?![\s\S])))|(?<![ \t])[ \t]*(?:\/\*[\s\S]*?(?:\*\/|(?![\s\S]))|\/\/.*|(?<![\s\S])\uFEFF?#!.*)[ \t]*/gmu,
|
|
30
|
+
// Beside punctuation (`a, b`, `x = 1`), not between two words, as
|
|
31
|
+
// JavaScript tells a word's characters (`return a`, `var π`, `var \u03c0`),
|
|
32
|
+
droppable: /(?<![\p{ID_Continue}$\\\u200C\u200D])[ \t]+|[ \t]+(?![\p{ID_Continue}$\\\u200C\u200D])/gu,
|
|
33
|
+
// nor between two `+`, two `-` or two `/` (`a+ +b` is no `a++b`, `a/ /b/`
|
|
34
|
+
// no comment), nor after a regular expression before a word (`/a/ in b`).
|
|
35
|
+
needed: (code, index, run) => ('+-/'.includes(code[index - 1]) && code[index + run.length] === code[index - 1])
|
|
36
|
+
|| (code[index - 2] === REGEX && /[\p{ID_Continue}$\\\u200C\u200D]/u.test(code[index + run.length])),
|
|
37
|
+
}
|
|
38
|
+
const CSS = {
|
|
39
|
+
// No `//` comments, so `url(https://…)` is code.
|
|
40
|
+
stringOrComment: /("(?:[^"\\\n]|\\.)*"|'(?:[^'\\\n]|\\.)*')|[ \t]*\/\*[\s\S]*?\*\/[ \t]*/gu,
|
|
41
|
+
// Beside braces, `;`, `,`, `>`, parentheses, after `:` (`a { color: red }`)
|
|
42
|
+
// and beside a selector's `+` or `~` (`.a + .b`), not those a selector or a
|
|
43
|
+
// value needs (`.a .b`, `1px solid #fff`, `a :hover`),
|
|
44
|
+
droppable: /(?<=[{};,:>(])[ \t]+|[ \t]+(?=[{};,>)!])|(?<=[+~])[ \t]+|[ \t]+(?=[+~])/gu,
|
|
45
|
+
// nor beside `+` or `~` in parentheses (`calc(1px + var(--x))`) or in a
|
|
46
|
+
// custom property's value, kept for a `calc()` to come (`--gap:1px + 2px`).
|
|
47
|
+
needed: (code, index, run, depth) => /[+~]/u.test(code[index - 1] + code[index + run.length])
|
|
48
|
+
&& (depth > 0 || /^\s*--[^:]*:/u.test(code.slice(Math.max(...['{', ';', '}'].map(end => code.lastIndexOf(end, index))) + 1, index))),
|
|
49
|
+
}
|
|
50
|
+
// JavaScript's strings and regular expressions (the first group) and its
|
|
51
|
+
// comments, for a reader that sets them aside (runs-code.js, hosts.js).
|
|
52
|
+
export const JS_STRING_OR_COMMENT = JS.stringOrComment
|
|
53
|
+
// A stylesheet's by its name, else JavaScript's for a script by its name, or
|
|
54
|
+
// for any other where node runs it as one (`script`).
|
|
55
|
+
export const minifiable = (path, script = false) => /\.css$/iu.test(path) ? CSS : script || /\.[cm]?js$/iu.test(path) ? JS : null
|
|
56
|
+
// How much of a text is read for how its lines are minified: their average
|
|
57
|
+
// is told by as much of them, and a text of millions of lines is read no
|
|
58
|
+
// further.
|
|
59
|
+
const MINIFIED_READ = 4 * 1024 * 1024
|
|
60
|
+
// Its code's lines' average length where they are minified into short ones,
|
|
61
|
+
// else 0, told by its first MINIFIED_READ characters.
|
|
62
|
+
export function minifiedAverage(whole, { stringOrComment, droppable, needed }) {
|
|
63
|
+
const text = whole.length > MINIFIED_READ ? whole.slice(0, whole.lastIndexOf('\n', MINIFIED_READ) + 1 || MINIFIED_READ) : whole
|
|
64
|
+
// Its lines of code alone, as long as what is on them: a comment set aside
|
|
65
|
+
// leaves nothing but its line breaks, a string or template `""` and its, a
|
|
66
|
+
// regular expression `/REGEX/`, so the code either side stays apart.
|
|
67
|
+
const lines = text.replaceAll(stringOrComment, (match, string) => (string === undefined ? '' : string[0] === '/' ? `/${REGEX}/` : '""') + match.replaceAll(/[^\n]/gu, ''))
|
|
68
|
+
.replaceAll(/^[ \t]+/gmu, '')
|
|
69
|
+
.split('\n').filter(line => line.trim() !== '')
|
|
70
|
+
const code = lines.join('\n'), length = code.length - (lines.length - 1)
|
|
71
|
+
// Counted by character: a run aligning `=` is as many spaces as it is wide.
|
|
72
|
+
let depth = 0, dropped = 0, scanned = 0
|
|
73
|
+
for (const { 0: run, index } of code.matchAll(droppable)) {
|
|
74
|
+
for (; scanned < index; scanned++) depth = Math.max(0, depth + (code[scanned] === '(' ? 1 : code[scanned] === ')' ? -1 : 0))
|
|
75
|
+
if (!needed(code, index, run, depth)) dropped += run.length
|
|
76
|
+
}
|
|
77
|
+
return lines.length > 0 && length > MINIFIED_AVERAGE * lines.length && dropped < MINIFIED_SPACES * length ? Math.round(length / lines.length) : 0
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// JavaScript or TypeScript (a declaration file too, which node runs as any
|
|
81
|
+
// other), or a script run by node by its hashbang (`bin/cli`, with no
|
|
82
|
+
// extension), a byte order mark before it or not, as node runs one after it
|
|
83
|
+
// as an ES module (in a `"type": "module"` package).
|
|
84
|
+
const SCRIPT = /\.[cm]?[jt]sx?$/iu
|
|
85
|
+
const NODE_HASHBANG = /^\uFEFF?#!.*\bnode\b/u
|
|
86
|
+
// Whether a file (its path and text) is a script, as SCRIPT and NODE_HASHBANG
|
|
87
|
+
// tell, or as node runs it whatever its name (`script`, npm/files.js
|
|
88
|
+
// npmLoadedScripts).
|
|
89
|
+
export const npmIsScript = (path, text, script = false) => typeof text === 'string' && (script || SCRIPT.test(path) || NODE_HASHBANG.test(text))
|
|
90
|
+
// How many places a file is told doing a thing, the first ones, at most
|
|
91
|
+
// (runs-code.js, hosts.js): a file doing it on millions of lines is told by
|
|
92
|
+
// its first, and what it holds of them kept to a bound however many there
|
|
93
|
+
// are.
|
|
94
|
+
export const NPM_MAX_FOUND = 100
|
|
95
|
+
// Every how many line breaks one is kept where lineOf counts from.
|
|
96
|
+
const LINE_MARK = 1024
|
|
97
|
+
// Each offset in a text as its line: one more than the line breaks before it,
|
|
98
|
+
// counted on from the nearest of every LINE_MARKth, which alone are kept.
|
|
99
|
+
export function lineOf(text) {
|
|
100
|
+
let marks = null
|
|
101
|
+
return offset => {
|
|
102
|
+
if (!marks) {
|
|
103
|
+
marks = []
|
|
104
|
+
for (let at = text.indexOf('\n'), count = 0; at !== -1; at = text.indexOf('\n', at + 1), count++) if (count % LINE_MARK === 0) marks.push(at)
|
|
105
|
+
}
|
|
106
|
+
let high = marks.length, low = 0
|
|
107
|
+
while (low < high) {
|
|
108
|
+
const middle = (low + high) >> 1
|
|
109
|
+
if (marks[middle] < offset) low = middle + 1
|
|
110
|
+
else high = middle
|
|
111
|
+
}
|
|
112
|
+
if (low === 0) return 1
|
|
113
|
+
let breaks = (low - 1) * LINE_MARK + 1
|
|
114
|
+
for (let at = text.indexOf('\n', marks[low - 1] + 1); at !== -1 && at < offset; at = text.indexOf('\n', at + 1)) breaks++
|
|
115
|
+
return breaks + 1
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// A file's stamps: what risk reads of one file (the readers beside this), and
|
|
2
|
+
// what of it calls for a look, as a list of files tags it and orders it by:
|
|
3
|
+
// each `{ name, severity }`, its tag's text and how severe it is (SEVERITIES).
|
|
4
|
+
import { READABILITY, npmFileReadability, npmLabelMark, npmLargeCode, npmReadabilityLabels, npmTaggedCategory } from './readability.js'
|
|
5
|
+
import { npmExfiltration, npmHostSeverity, npmHostTags, npmHosts } from './hosts.js'
|
|
6
|
+
import { npmRunsCode, npmRunsCodeFlags } from './runs-code.js'
|
|
7
|
+
|
|
8
|
+
// How severe a stamp or a finding is, the most first: `critical` red,
|
|
9
|
+
// `high` a warning's orange, `moderate` yellow, `low`, and a `notice`, under
|
|
10
|
+
// a low one.
|
|
11
|
+
export const SEVERITIES = ['critical', 'high', 'moderate', 'low', 'notice']
|
|
12
|
+
|
|
13
|
+
// A label's mark (readability.js READABILITY) as a severity: a warning's
|
|
14
|
+
// orange, or a notice.
|
|
15
|
+
const severityOf = mark => mark === 'warn' ? 'high' : 'notice'
|
|
16
|
+
|
|
17
|
+
// A file's stamps, from what was read of it: what its code does beyond
|
|
18
|
+
// itself (runs-code.js npmRunsCodeFlags), a warning's or, for the whole
|
|
19
|
+
// environment read out and publishing, critical; the services it names
|
|
20
|
+
// (hosts.js), a stamp a tag, at the tag's severity (Exfiltration critical,
|
|
21
|
+
// Remote high, IP lookup moderate); a large code file, a notice; an
|
|
22
|
+
// obfuscator's fingerprint, a warning's; and its control characters, long
|
|
23
|
+
// lines and category, by their marks, but for what reads as most files do
|
|
24
|
+
// (UTF-8, ASCII) and a source map.
|
|
25
|
+
function npmStampsOf({ path, bytes, readability, runsCode, exfiltration, script }) {
|
|
26
|
+
const category = npmTaggedCategory(readability)
|
|
27
|
+
const listed = category !== 'ascii' && category !== 'map' && READABILITY.get(category).mark
|
|
28
|
+
return [...npmRunsCodeFlags(runsCode),
|
|
29
|
+
...npmHostTags(exfiltration).map(([tag, services]) => ({ name: tag, severity: npmHostSeverity(tag, services) })),
|
|
30
|
+
...npmLargeCode(path, bytes, script) ? [{ name: 'Large', severity: 'notice' }] : [],
|
|
31
|
+
...readability.obfuscation ? [{ name: 'Obfuscated', severity: 'high' }] : [],
|
|
32
|
+
...npmReadabilityLabels(readability).filter(label => label === 'controls' || label === 'long')
|
|
33
|
+
.map(label => ({ name: READABILITY.get(label).tag, severity: severityOf(npmLabelMark(readability, label)) })),
|
|
34
|
+
...listed ? [{ name: READABILITY.get(category).tag, severity: severityOf(listed) }] : []]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Everything risk reads of a file (`path`, its `text`, null for one that
|
|
38
|
+
// isn't, and its size in `bytes`): how it reads (npmFileReadability), what
|
|
39
|
+
// its code does beyond itself (npmRunsCode), the services it names under the
|
|
40
|
+
// hosts' tags (npmExfiltration) and the hosts its code names (npmHosts), and its
|
|
41
|
+
// `stamps` (npmStampsOf); read as a script where node runs it as one whatever
|
|
42
|
+
// its name (`script`, npm/files.js npmLoadedScripts).
|
|
43
|
+
export function npmFileRisk(path, text, bytes, script = false) {
|
|
44
|
+
const readability = npmFileReadability(path, text, script)
|
|
45
|
+
const exfiltration = npmExfiltration(path, text, script), runsCode = npmRunsCode(path, text, script)
|
|
46
|
+
return { readability, runsCode, exfiltration, hosts: npmHosts(path, text, script), stamps: npmStampsOf({ path, bytes, readability, runsCode, exfiltration, script }) }
|
|
47
|
+
}
|
package/risk/index.d.ts
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
// Hand-written against index.js; a change to either belongs with the other.
|
|
2
|
+
import type { CacheStore } from '@preventive/upstream/npm.js'
|
|
3
|
+
|
|
4
|
+
// How severe a stamp or a finding is, the most first: `critical` red, `high`
|
|
5
|
+
// a warning's orange, `moderate` yellow, `low`, and a `notice`.
|
|
6
|
+
export type Severity = 'critical' | 'high' | 'moderate' | 'low' | 'notice'
|
|
7
|
+
|
|
8
|
+
// The severities, the most severe first.
|
|
9
|
+
export const SEVERITIES: readonly Severity[]
|
|
10
|
+
|
|
11
|
+
// How old a version must be to be trusted unless said: two weeks, in ms.
|
|
12
|
+
export const DEFAULT_MINIMUM_RELEASE_AGE: number
|
|
13
|
+
|
|
14
|
+
// npm has no such package or version (`package-not-found`,
|
|
15
|
+
// `version-not-found`), a tarball unpacks past risk's bounds
|
|
16
|
+
// (`package-too-large`), npm asked to be asked later (`upstream-busy`, a 429,
|
|
17
|
+
// for a caller to wait on and ask again), or npm couldn't be asked
|
|
18
|
+
// (`upstream-unavailable`), answered past them (`upstream-too-large`) or
|
|
19
|
+
// answered what can't be read (`upstream-invalid`). `message` tells which
|
|
20
|
+
// request and why.
|
|
21
|
+
export class NpmRiskError extends Error {
|
|
22
|
+
code: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface AssessNpmOptions {
|
|
26
|
+
// The version to compare with; true for the one of the package's versions
|
|
27
|
+
// most likely free of what an attack injects, as risk picks it by npm's
|
|
28
|
+
// document (risk/npm/old-version.js), none where none is below it; without
|
|
29
|
+
// one, everything of the version is new.
|
|
30
|
+
oldVersion?: string | true | null
|
|
31
|
+
// Compare all files with an empty package, for an initial dependency review.
|
|
32
|
+
fromEmpty?: boolean
|
|
33
|
+
// Younger than this, in ms, a version is `too-new`; 0 for none, as a
|
|
34
|
+
// caller's own scopes take. Two weeks unless given.
|
|
35
|
+
minimumReleaseAge?: number
|
|
36
|
+
// Whether the package is flagged as few download it (`popularity`); false
|
|
37
|
+
// for none, as a caller's own scopes take, its downloads then not asked.
|
|
38
|
+
// True unless given.
|
|
39
|
+
popularity?: boolean
|
|
40
|
+
// Where what is read is kept, by type (risk/npm/registry.js and assess.js
|
|
41
|
+
// name each): `npm/tarballs`, `risk/npm/versions`, `risk/npm/packages`,
|
|
42
|
+
// `risk/npm/old-versions`, `risk/npm/public`, `risk/npm/downloads`,
|
|
43
|
+
// `risk/npm/advisories` and `risk/npm/assessments`. One that reads records
|
|
44
|
+
// of any types at once (`readEach`, each null where none is kept) is read
|
|
45
|
+
// so where risk reads several together.
|
|
46
|
+
cache?: (CacheStore & { readEach?(entries: [type: string, key: string][]): Promise<unknown[]> }) | false
|
|
47
|
+
// Asks for a package's whole document in risk's stead, as the managed
|
|
48
|
+
// server does within its bounds: null where npm has none for this asker.
|
|
49
|
+
// `authorized` whether it may be asked with the caller's npm token: the
|
|
50
|
+
// package assessed, not its dependencies.
|
|
51
|
+
packument?: (name: string, options: { authorized: boolean; signal: AbortSignal | undefined }) => Promise<Record<string, unknown> | null>
|
|
52
|
+
// Reads a version's tarball, gzipped, in place of upstream's getTarball, as
|
|
53
|
+
// the managed server does within its bounds: `version` the one assessed or
|
|
54
|
+
// `oldVersion`, that one only where its files could change what is found.
|
|
55
|
+
// What it throws is thrown as it is.
|
|
56
|
+
tarball?: (name: string, version: string, options: { signal: AbortSignal | undefined }) => Promise<Uint8Array>
|
|
57
|
+
now?: number
|
|
58
|
+
signal?: AbortSignal
|
|
59
|
+
// Whether npm's downloads are asked for: the package's popularity, and its
|
|
60
|
+
// new dependencies' tiers and ages. True unless given.
|
|
61
|
+
downloads?: boolean
|
|
62
|
+
// Whether its new dependencies' tiers and ages are asked for, a request or
|
|
63
|
+
// two of npm each, where `downloads` is. True unless given.
|
|
64
|
+
dependencies?: boolean
|
|
65
|
+
// Whether npm's advisories of the version are asked for, an advisory of
|
|
66
|
+
// malware naming it a `malware` finding, as its package taken down by npm
|
|
67
|
+
// is. True unless given.
|
|
68
|
+
advisories?: boolean
|
|
69
|
+
// Whether OSV's records of malware in the version are asked for too, where
|
|
70
|
+
// `advisories` are: false for a private package, whose name OSV is never
|
|
71
|
+
// to be sent. True unless given.
|
|
72
|
+
osv?: boolean
|
|
73
|
+
// Whether a package is the caller's own, as its own scopes take: a new
|
|
74
|
+
// dependency on one is told no tier nor age, nor is npm asked of it. None
|
|
75
|
+
// unless given.
|
|
76
|
+
owned?: (name: string) => boolean | Promise<boolean>
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// What calls for a look, by `id`, with what it found beside.
|
|
80
|
+
export interface Finding {
|
|
81
|
+
id: string
|
|
82
|
+
severity: Severity
|
|
83
|
+
[found: string]: unknown
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// A stamp on a file, as a list of files tags it.
|
|
87
|
+
export interface Stamp {
|
|
88
|
+
name: string
|
|
89
|
+
severity: Severity
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface FileRisk {
|
|
93
|
+
stamps: Stamp[]
|
|
94
|
+
readability: Record<string, unknown>
|
|
95
|
+
runsCode: Record<string, number[]> | null
|
|
96
|
+
exfiltration: Record<string, number[]> | null
|
|
97
|
+
hosts: Record<string, number> | null
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface DependencyRisk {
|
|
101
|
+
key: string
|
|
102
|
+
name: string
|
|
103
|
+
kind: 'peer' | 'optional' | null
|
|
104
|
+
range?: string
|
|
105
|
+
from?: string
|
|
106
|
+
to?: string
|
|
107
|
+
opens: string | null
|
|
108
|
+
flags: { check: string; label: string; tooltip: string }[]
|
|
109
|
+
tier?: number | null
|
|
110
|
+
level?: string
|
|
111
|
+
// Its last whole month's downloads, by what its tier goes by: none where
|
|
112
|
+
// npm counts none of them.
|
|
113
|
+
month?: { total: number; from: string }
|
|
114
|
+
// Whether npm counts none of its downloads, as of a package published
|
|
115
|
+
// the day before; unpopular all the same.
|
|
116
|
+
uncounted?: true
|
|
117
|
+
created?: string
|
|
118
|
+
gap?: number
|
|
119
|
+
// For one nothing imports, the version its spec installs (registry.js
|
|
120
|
+
// npmPublicFacts): its package's latest beside it, when it was published,
|
|
121
|
+
// whether it has install scripts, and whether that was since the version
|
|
122
|
+
// compared with (`new`).
|
|
123
|
+
installs?: { version: string; latest: string | null; published: string | null; scripts: boolean; new: boolean }
|
|
124
|
+
// Where its package was looked up and npm has none of it for anyone.
|
|
125
|
+
missing?: true
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// A version's risk as one number (risk/npm/score.js): what its findings call
|
|
129
|
+
// for (`raised`, each it counts), each by its severity, malware all of it,
|
|
130
|
+
// lowered by its exposure (`lowered`): how long it has been out (`days`)
|
|
131
|
+
// among how many download its package (`tier`, its rank, null past the last
|
|
132
|
+
// or where unknown), `by` the share taken off. Its `level` is named as the
|
|
133
|
+
// findings' severities are: from 75 critical, 50 high, 25 moderate, else low.
|
|
134
|
+
export interface RiskScore {
|
|
135
|
+
score: number
|
|
136
|
+
level: 'critical' | 'high' | 'moderate' | 'low'
|
|
137
|
+
raised: { id: string; severity: Severity }[]
|
|
138
|
+
lowered?: { days: number; tier: number | null; by: number }
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface NpmAssessment {
|
|
142
|
+
name: string
|
|
143
|
+
version: string
|
|
144
|
+
// The version compared with, as given or as risk picked it; null for none.
|
|
145
|
+
oldVersion: string | null
|
|
146
|
+
published: string | null
|
|
147
|
+
// A version npm removed, as it removes every one it finds malware in, told
|
|
148
|
+
// of by its `malware` finding alone, with no files nor dependencies.
|
|
149
|
+
removed?: true
|
|
150
|
+
findings: Finding[]
|
|
151
|
+
files: Record<string, FileRisk>
|
|
152
|
+
// Against `oldVersion`, each it holds too, flagged against none (`held`).
|
|
153
|
+
dependencies: { added: DependencyRisk[]; changed: DependencyRisk[]; held?: DependencyRisk[] }
|
|
154
|
+
score: RiskScore
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function assessNpm(name: string, version: string, options?: AssessNpmOptions): Promise<NpmAssessment>
|
|
158
|
+
|
|
159
|
+
// Readies, at once, the downloads assessNpm asks of each of these packages
|
|
160
|
+
// that can be, kept in `cache` as it keeps them, so that their assessments
|
|
161
|
+
// ask npm none: those kept within a week, and unscoped ones, asked of npm 128
|
|
162
|
+
// at a time. `ready` is told each once its downloads are kept; the rest (scoped
|
|
163
|
+
// ones, which npm answers only one by one) are left for npmReadyDownload.
|
|
164
|
+
// npm asking to be asked later is thrown as an NpmRiskError
|
|
165
|
+
// (`upstream-busy`), those readied by then told.
|
|
166
|
+
// A cache that reads and writes many at once too (`readMany`, `writeMany`)
|
|
167
|
+
// is read once and written once a lookup.
|
|
168
|
+
export function npmReadyDownloads(names: string[], ready: (name: string) => void, options: { cache: CacheStore & {
|
|
169
|
+
readMany?(type: string, keys: string[]): Promise<Map<string, unknown>>
|
|
170
|
+
writeMany?(type: string, entries: [key: string, value: unknown][]): Promise<void>
|
|
171
|
+
}; signal?: AbortSignal; now?: number }): Promise<void>
|
|
172
|
+
|
|
173
|
+
// Readies the downloads assessNpm asks of a package, asked of npm on their
|
|
174
|
+
// own where they aren't kept; npm asking to be asked later thrown as an
|
|
175
|
+
// NpmRiskError (`upstream-busy`).
|
|
176
|
+
export function npmReadyDownload(name: string, options: { cache: CacheStore; signal?: AbortSignal; now?: number }): Promise<void>
|
|
177
|
+
|
|
178
|
+
// Whether an advisory is of malware rather than a vulnerability: OSV's of a
|
|
179
|
+
// malicious package (`MAL-…`), or one such a record names (its `aliases`),
|
|
180
|
+
// CWE-506, embedded malicious code, whatever its title, or a title naming
|
|
181
|
+
// malware.
|
|
182
|
+
export function npmMalwareAdvisory(advisory: { id?: string | undefined; aliases?: readonly string[] | undefined; cwe?: readonly string[] | undefined; title?: string | undefined }): boolean
|
|
183
|
+
|
|
184
|
+
export function npmFileRisk(path: string, text: string | null, bytes?: number, script?: boolean): unknown
|
|
185
|
+
|
|
186
|
+
// GitHub Actions (actions/), a workflow GitHub can't run thrown as
|
|
187
|
+
// @preventive/lockfile's YamlError. A finding of a workflow's, its `line` from 1; of a reference's own code,
|
|
188
|
+
// with the `file` it is in.
|
|
189
|
+
export interface ActionsFinding extends Finding {
|
|
190
|
+
line?: number | null
|
|
191
|
+
file?: string
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// What a `uses:` names: an action's or a reusable workflow's, by its `key`,
|
|
195
|
+
// or the repository's own.
|
|
196
|
+
export type ActionUses = { kind: 'action' | 'workflow'; uses: string; repo: string; path: string; ref: string; pin: 'sha' | 'short-sha' | 'ref' | 'expression'; comment: string | null; key?: string; line?: number | null }
|
|
197
|
+
export type Uses = ActionUses | { kind: 'local'; uses: string; path: string; self?: true; job?: true; line?: number | null }
|
|
198
|
+
|
|
199
|
+
export interface ScanOptions {
|
|
200
|
+
// Whose repository it is, as an unpinned `uses:` of its owner's is yellow.
|
|
201
|
+
owner?: string | null
|
|
202
|
+
// Its lockfiles' paths, the packages each locks, as npx runs those, by
|
|
203
|
+
// name and by `name@version`, and those only devDependencies need.
|
|
204
|
+
lockfiles?: { path: string; names: ReadonlySet<string>; dev?: ReadonlySet<string> }[]
|
|
205
|
+
// Its own actions' metadata by their directories, and its workflows by
|
|
206
|
+
// their paths: for where its actions install its packages, else each
|
|
207
|
+
// counts as installing them anywhere; and for the inputs its actions and
|
|
208
|
+
// reusable workflows write into their scripts, else each of a reusable
|
|
209
|
+
// workflow's counts as one.
|
|
210
|
+
actions?: ReadonlyMap<string, string> | null
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export type WorkflowScan = { uses: Uses[]; findings: ActionsFinding[] } | { error: 'workflow-unreadable'; detail: string }
|
|
214
|
+
|
|
215
|
+
export function scanWorkflow(kind: 'workflow' | 'action', text: string, options?: ScanOptions): WorkflowScan
|
|
216
|
+
// The actions of the repository's own a workflow or an action uses, by
|
|
217
|
+
// their directories, and a Docker action's Dockerfile, from its own.
|
|
218
|
+
export function ownFilesOf(kind: 'workflow' | 'action', text: string): { actions: string[]; dockerfile: string | null }
|
|
219
|
+
// A Dockerfile's findings, each on its line.
|
|
220
|
+
export function dockerfileFindings(text: string): ActionsFinding[]
|
|
221
|
+
// A reference by its key, as a scan names it; null for none.
|
|
222
|
+
export function usesOfKey(key: string): ActionUses | null
|
|
223
|
+
|
|
224
|
+
// GitHub as the asker can read it; null for none.
|
|
225
|
+
export interface ActionsSource {
|
|
226
|
+
// Its name now, where it moved, and the repository it forks.
|
|
227
|
+
repo(name: string): Promise<{ fullName: string; defaultBranch: string; fork?: string | null; archived?: boolean; private?: boolean } | null>
|
|
228
|
+
// Every tag's commit; null where it has too many to list.
|
|
229
|
+
tags(name: string): Promise<{ tag: string; oid: string }[] | null>
|
|
230
|
+
tag(name: string, tag: string): Promise<string | null>
|
|
231
|
+
branch(name: string, branch: string): Promise<string | null>
|
|
232
|
+
// Its branches, and whether those are all.
|
|
233
|
+
branches(name: string): Promise<{ branches: { branch: string; oid: string }[]; complete: boolean }>
|
|
234
|
+
// Whether `sha` is `base` or in its history; null for no such commit. Of two
|
|
235
|
+
// commits, it holds for good.
|
|
236
|
+
contains(name: string, base: string, sha: string): Promise<boolean | null>
|
|
237
|
+
file(name: string, path: string, commit: string): Promise<string | null>
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// A reference resolved: its repository as GitHub has it now, its ref's
|
|
241
|
+
// commit, what the ref is, the tags on the commit, and the keys of the
|
|
242
|
+
// references its code makes; null for none.
|
|
243
|
+
export interface ResolvedAction extends Pick<ActionUses, 'kind' | 'repo' | 'path' | 'ref'> {
|
|
244
|
+
key: string
|
|
245
|
+
repository: { fullName: string; private: boolean } | null
|
|
246
|
+
commit: string | null
|
|
247
|
+
at: 'sha' | 'tag' | 'branch' | null
|
|
248
|
+
tags: string[]
|
|
249
|
+
findings: ActionsFinding[]
|
|
250
|
+
uses: string[]
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export function resolveAction(uses: ActionUses, source: ActionsSource, options?: { owner?: string | null }): Promise<ResolvedAction>
|
|
254
|
+
export function keptSource(source: ActionsSource): ActionsSource
|
package/risk/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// What calls for a look at a package version, or a repository's GitHub
|
|
2
|
+
// Actions, for a reviewer: risk's heuristics, apart from any view of them.
|
|
3
|
+
// See README.md.
|
|
4
|
+
export { assessNpm } from './npm/assess.js'
|
|
5
|
+
export { npmMalwareAdvisory } from './npm/malware.js'
|
|
6
|
+
export { DEFAULT_MINIMUM_RELEASE_AGE } from './npm/release.js'
|
|
7
|
+
export { NpmRiskError, npmReadyDownload, npmReadyDownloads } from './npm/registry.js'
|
|
8
|
+
export { SEVERITIES, npmFileRisk } from './files/stamps.js'
|
|
9
|
+
export { ownFilesOf, scanWorkflow } from './actions/findings.js'
|
|
10
|
+
export { dockerfileFindings, keptSource, resolveAction } from './actions/resolve.js'
|
|
11
|
+
export { usesOfKey } from './actions/uses.js'
|