@xemahq/biome-supply-chain 0.1.2 → 0.2.0

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/README.md CHANGED
@@ -22,6 +22,7 @@ import {
22
22
  ensureCosignAvailable,
23
23
  verifyCosignSignature,
24
24
  verifyCosignBlob,
25
+ CosignTrustAnchorKind,
25
26
  SignatureVerdict,
26
27
  CosignVerifyOutcome,
27
28
  } from '@xemahq/biome-supply-chain';
@@ -35,20 +36,41 @@ await verifyCosignSignature({
35
36
  oidcIssuer: 'https://token.actions.githubusercontent.com',
36
37
  });
37
38
 
38
- // Detached blob (caller owns artifact/bundle files on disk)
39
- const { outcome, matchedIdentity } = await verifyCosignBlob({
39
+ // Detached blob (caller owns artifact/bundle/public-key files on disk).
40
+ // A trust anchor is EITHER a keyless certificate-identity pattern OR a NAMED
41
+ // public key; both kinds share one list and one result shape, and the anchors
42
+ // are tried in order until one verifies.
43
+ const { outcome, matchedAnchor } = await verifyCosignBlob({
40
44
  artifactPath: '/tmp/remoteEntry.js',
41
45
  bundlePath: '/tmp/remoteEntry.js.bundle',
42
- trustedIdentityRegexps: ['^https://github.com/xema-dev/.*$'],
46
+ anchors: [
47
+ {
48
+ kind: CosignTrustAnchorKind.KeylessIdentity,
49
+ name: '^https://github.com/xema-dev/.*$', // the name IS the regexp
50
+ },
51
+ {
52
+ kind: CosignTrustAnchorKind.PublicKey,
53
+ name: 'release-2026',
54
+ publicKeyPath: '/etc/cosign/release.pub',
55
+ },
56
+ ],
57
+ // Optional: pin the Sigstore trusted root so KEYLESS anchors verify with
58
+ // `--offline --trusted-root` (air-gap capable). A missing, unreadable or
59
+ // digest-mismatched root THROWS `CosignTrustedRootError` before cosign is
60
+ // spawned — it never falls back to cosign's online default.
61
+ trustedRoot: { path: '/etc/sigstore/trusted-root.json', sha256: '<64 hex>' },
43
62
  });
44
63
  if (outcome === CosignVerifyOutcome.Verified) {
45
- // matchedIdentity is the regexp that verified
64
+ // matchedAnchor is { kind, name } — WHICH anchor vouched for the bytes
46
65
  }
47
66
  ```
48
67
 
68
+ An empty `anchors` list resolves to `Failed` without spawning cosign, and a
69
+ failed verification is a neutral outcome rather than a throw.
70
+
49
71
  Artifact resolution (resolving an OCI ref, or fetching + writing a blob to a
50
- temp file) stays with each consumer; this package owns only the cosign exec and
51
- the verdict enums.
72
+ temp file) stays with each consumer; this package owns only the cosign exec,
73
+ the trust-anchor vocabulary and the verdict enums.
52
74
 
53
75
  ## License
54
76
 
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './lib/verdicts';
2
+ export * from './lib/trust-anchors';
2
3
  export * from './lib/cosign-exec';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -15,5 +15,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./lib/verdicts"), exports);
18
+ __exportStar(require("./lib/trust-anchors"), exports);
18
19
  __exportStar(require("./lib/cosign-exec"), exports);
19
20
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA+B;AAC/B,oDAAkC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA+B;AAC/B,sDAAoC;AACpC,oDAAkC"}
@@ -1,3 +1,4 @@
1
+ import { type CosignBlobTrustAnchor, type CosignMatchedAnchor, type CosignPinnedTrustedRoot } from './trust-anchors';
1
2
  import { CosignVerifyOutcome } from './verdicts';
2
3
  export declare function ensureCosignAvailable(bin?: string): Promise<void>;
3
4
  export interface VerifyCosignSignatureInput {
@@ -20,13 +21,14 @@ export declare function verifyCosignAttestation(input: VerifyCosignAttestationIn
20
21
  export interface VerifyCosignBlobInput {
21
22
  readonly artifactPath: string;
22
23
  readonly bundlePath: string;
23
- readonly trustedIdentityRegexps: readonly string[];
24
+ readonly anchors: readonly CosignBlobTrustAnchor[];
24
25
  readonly oidcIssuer?: string | undefined;
26
+ readonly trustedRoot?: CosignPinnedTrustedRoot | undefined;
25
27
  readonly bin?: string | undefined;
26
28
  }
27
29
  export interface VerifyCosignBlobResult {
28
30
  readonly outcome: CosignVerifyOutcome;
29
- readonly matchedIdentity?: string | undefined;
31
+ readonly matchedAnchor?: CosignMatchedAnchor | undefined;
30
32
  }
31
33
  export declare function verifyCosignBlob(input: VerifyCosignBlobInput): Promise<VerifyCosignBlobResult>;
32
34
  //# sourceMappingURL=cosign-exec.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cosign-exec.d.ts","sourceRoot":"","sources":["../../src/lib/cosign-exec.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAoCjD,wBAAsB,qBAAqB,CACzC,GAAG,GAAE,MAA2B,GAC/B,OAAO,CAAC,IAAI,CAAC,CAYf;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEzC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAOD,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAMD,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,4BAA4B,GAClC,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED,MAAM,WAAW,qBAAqB;IAEpC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAE9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,QAAQ,CAAC,sBAAsB,EAAE,SAAS,MAAM,EAAE,CAAC;IACnD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IAEtC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/C;AASD,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,sBAAsB,CAAC,CAuBjC"}
1
+ {"version":3,"file":"cosign-exec.d.ts","sourceRoot":"","sources":["../../src/lib/cosign-exec.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC7B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAoCjD,wBAAsB,qBAAqB,CACzC,GAAG,GAAE,MAA2B,GAC/B,OAAO,CAAC,IAAI,CAAC,CAYf;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEzC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAOD,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAMD,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,4BAA4B,GAClC,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED,MAAM,WAAW,qBAAqB;IAEpC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAE9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAO5B,QAAQ,CAAC,OAAO,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAKnD,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAWzC,QAAQ,CAAC,WAAW,CAAC,EAAE,uBAAuB,GAAG,SAAS,CAAC;IAC3D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IAOtC,QAAQ,CAAC,aAAa,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;CAC1D;AA8DD,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,sBAAsB,CAAC,CAoBjC"}
@@ -5,6 +5,7 @@ exports.verifyCosignSignature = verifyCosignSignature;
5
5
  exports.verifyCosignAttestation = verifyCosignAttestation;
6
6
  exports.verifyCosignBlob = verifyCosignBlob;
7
7
  const node_child_process_1 = require("node:child_process");
8
+ const trust_anchors_1 = require("./trust-anchors");
8
9
  const verdicts_1 = require("./verdicts");
9
10
  const DEFAULT_COSIGN_BIN = 'cosign';
10
11
  function runCosign(bin, args) {
@@ -80,26 +81,38 @@ async function verifyCosignAttestation(input) {
80
81
  throw new Error(`${bin} verify-attestation failed (code=${code}): ${stderr.slice(-200)}`);
81
82
  }
82
83
  }
84
+ function buildBlobVerifyArgs(anchor, input) {
85
+ const args = ['verify-blob'];
86
+ if (anchor.kind === trust_anchors_1.CosignTrustAnchorKind.PublicKey) {
87
+ args.push('--key', anchor.publicKeyPath, '--bundle', input.bundlePath, '--insecure-ignore-tlog');
88
+ args.push(input.artifactPath);
89
+ return args;
90
+ }
91
+ args.push('--bundle', input.bundlePath, '--certificate-identity-regexp', anchor.name);
92
+ if (input.oidcIssuer) {
93
+ args.push('--certificate-oidc-issuer', input.oidcIssuer);
94
+ }
95
+ if (input.trustedRoot) {
96
+ args.push('--offline', '--trusted-root', input.trustedRoot.path);
97
+ }
98
+ args.push(input.artifactPath);
99
+ return args;
100
+ }
83
101
  async function verifyCosignBlob(input) {
84
102
  const bin = input.bin ?? DEFAULT_COSIGN_BIN;
85
- if (input.trustedIdentityRegexps.length === 0) {
103
+ if (input.anchors.length === 0) {
86
104
  return { outcome: verdicts_1.CosignVerifyOutcome.Failed };
87
105
  }
88
- for (const identity of input.trustedIdentityRegexps) {
89
- const args = [
90
- 'verify-blob',
91
- '--bundle',
92
- input.bundlePath,
93
- '--certificate-identity-regexp',
94
- identity,
95
- ];
96
- if (input.oidcIssuer) {
97
- args.push('--certificate-oidc-issuer', input.oidcIssuer);
98
- }
99
- args.push(input.artifactPath);
100
- const { code } = await runCosign(bin, args);
106
+ if (input.trustedRoot) {
107
+ (0, trust_anchors_1.assertPinnedTrustedRoot)(input.trustedRoot);
108
+ }
109
+ for (const anchor of input.anchors) {
110
+ const { code } = await runCosign(bin, buildBlobVerifyArgs(anchor, input));
101
111
  if (code === 0) {
102
- return { outcome: verdicts_1.CosignVerifyOutcome.Verified, matchedIdentity: identity };
112
+ return {
113
+ outcome: verdicts_1.CosignVerifyOutcome.Verified,
114
+ matchedAnchor: { kind: anchor.kind, name: anchor.name },
115
+ };
103
116
  }
104
117
  }
105
118
  return { outcome: verdicts_1.CosignVerifyOutcome.Failed };
@@ -1 +1 @@
1
- {"version":3,"file":"cosign-exec.js","sourceRoot":"","sources":["../../src/lib/cosign-exec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cosign-exec.js","sourceRoot":"","sources":["../../src/lib/cosign-exec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ export declare enum CosignTrustAnchorKind {
2
+ KeylessIdentity = "keyless-identity",
3
+ PublicKey = "public-key"
4
+ }
5
+ export interface CosignKeylessIdentityAnchor {
6
+ readonly kind: CosignTrustAnchorKind.KeylessIdentity;
7
+ readonly name: string;
8
+ }
9
+ export interface CosignPublicKeyAnchor {
10
+ readonly kind: CosignTrustAnchorKind.PublicKey;
11
+ readonly name: string;
12
+ readonly publicKeyPath: string;
13
+ }
14
+ export type CosignBlobTrustAnchor = CosignKeylessIdentityAnchor | CosignPublicKeyAnchor;
15
+ export interface CosignMatchedAnchor {
16
+ readonly kind: CosignTrustAnchorKind;
17
+ readonly name: string;
18
+ }
19
+ export interface CosignPinnedTrustedRoot {
20
+ readonly path: string;
21
+ readonly sha256: string;
22
+ }
23
+ export declare class CosignTrustedRootError extends Error {
24
+ constructor(message: string);
25
+ }
26
+ export declare function assertPinnedTrustedRoot(root: CosignPinnedTrustedRoot): void;
27
+ //# sourceMappingURL=trust-anchors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-anchors.d.ts","sourceRoot":"","sources":["../../src/lib/trust-anchors.ts"],"names":[],"mappings":"AAiBA,oBAAY,qBAAqB;IAC/B,eAAe,qBAAqB;IACpC,SAAS,eAAe;CACzB;AAQD,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC,eAAe,CAAC;IACrD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAQD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC,SAAS,CAAC;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAGD,MAAM,MAAM,qBAAqB,GAC7B,2BAA2B,GAC3B,qBAAqB,CAAC;AAQ1B,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAcD,MAAM,WAAW,uBAAuB;IAEtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAUD,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,OAAO,EAAE,MAAM;CAI5B;AAuBD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,uBAAuB,GAAG,IAAI,CA0C3E"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CosignTrustedRootError = exports.CosignTrustAnchorKind = void 0;
4
+ exports.assertPinnedTrustedRoot = assertPinnedTrustedRoot;
5
+ const node_crypto_1 = require("node:crypto");
6
+ const node_fs_1 = require("node:fs");
7
+ var CosignTrustAnchorKind;
8
+ (function (CosignTrustAnchorKind) {
9
+ CosignTrustAnchorKind["KeylessIdentity"] = "keyless-identity";
10
+ CosignTrustAnchorKind["PublicKey"] = "public-key";
11
+ })(CosignTrustAnchorKind || (exports.CosignTrustAnchorKind = CosignTrustAnchorKind = {}));
12
+ class CosignTrustedRootError extends Error {
13
+ constructor(message) {
14
+ super(message);
15
+ this.name = 'CosignTrustedRootError';
16
+ }
17
+ }
18
+ exports.CosignTrustedRootError = CosignTrustedRootError;
19
+ const SHA256_HEX = /^[a-f0-9]{64}$/u;
20
+ const SIGSTORE_TRUSTED_ROOT_MEDIA_TYPE = 'application/vnd.dev.sigstore.trustedroot+json;version=0.1';
21
+ const MAX_TRUSTED_ROOT_BYTES = 8 * 1024 * 1024;
22
+ function assertPinnedTrustedRoot(root) {
23
+ if (!SHA256_HEX.test(root.sha256)) {
24
+ throw new CosignTrustedRootError(`pinned Sigstore trusted-root digest '${root.sha256}' is not a lowercase-hex sha256`);
25
+ }
26
+ let bytes;
27
+ try {
28
+ bytes = (0, node_fs_1.readFileSync)(root.path);
29
+ }
30
+ catch (cause) {
31
+ throw new CosignTrustedRootError(`pinned Sigstore trusted root '${root.path}' could not be read: ` +
32
+ `${cause instanceof Error ? cause.message : String(cause)}`);
33
+ }
34
+ if (bytes.byteLength > MAX_TRUSTED_ROOT_BYTES) {
35
+ throw new CosignTrustedRootError(`pinned Sigstore trusted root '${root.path}' is ${bytes.byteLength} bytes, over the ${MAX_TRUSTED_ROOT_BYTES}-byte ceiling`);
36
+ }
37
+ const actual = (0, node_crypto_1.createHash)('sha256').update(bytes).digest('hex');
38
+ if (actual !== root.sha256) {
39
+ throw new CosignTrustedRootError(`pinned Sigstore trusted-root digest mismatch for '${root.path}': expected ${root.sha256}, got ${actual}`);
40
+ }
41
+ let document;
42
+ try {
43
+ document = JSON.parse(bytes.toString('utf8'));
44
+ }
45
+ catch (cause) {
46
+ throw new CosignTrustedRootError(`pinned Sigstore trusted root '${root.path}' is not valid JSON: ` +
47
+ `${cause instanceof Error ? cause.message : String(cause)}`);
48
+ }
49
+ const mediaType = document?.mediaType;
50
+ if (mediaType !== SIGSTORE_TRUSTED_ROOT_MEDIA_TYPE) {
51
+ throw new CosignTrustedRootError(`pinned Sigstore trusted root '${root.path}' declares mediaType ` +
52
+ `'${String(mediaType)}' — expected '${SIGSTORE_TRUSTED_ROOT_MEDIA_TYPE}'`);
53
+ }
54
+ }
55
+ //# sourceMappingURL=trust-anchors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-anchors.js","sourceRoot":"","sources":["../../src/lib/trust-anchors.ts"],"names":[],"mappings":";;;AAoHA,0DA0CC;AA9JD,6CAAyC;AACzC,qCAAuC;AAgBvC,IAAY,qBAGX;AAHD,WAAY,qBAAqB;IAC/B,6DAAoC,CAAA;IACpC,iDAAwB,CAAA;AAC1B,CAAC,EAHW,qBAAqB,qCAArB,qBAAqB,QAGhC;AAoED,MAAa,sBAAuB,SAAQ,KAAK;IAC/C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AALD,wDAKC;AAGD,MAAM,UAAU,GAAG,iBAAiB,CAAC;AAOrC,MAAM,gCAAgC,GACpC,2DAA2D,CAAC;AAG9D,MAAM,sBAAsB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAS/C,SAAgB,uBAAuB,CAAC,IAA6B;IACnE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,sBAAsB,CAC9B,wCAAwC,IAAI,CAAC,MAAM,iCAAiC,CACrF,CAAC;IACJ,CAAC;IACD,IAAI,KAAa,CAAC;IAClB,IAAI,CAAC;QACH,KAAK,GAAG,IAAA,sBAAY,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,sBAAsB,CAC9B,iCAAiC,IAAI,CAAC,IAAI,uBAAuB;YAC/D,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAC9D,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,GAAG,sBAAsB,EAAE,CAAC;QAC9C,MAAM,IAAI,sBAAsB,CAC9B,iCAAiC,IAAI,CAAC,IAAI,QAAQ,KAAK,CAAC,UAAU,oBAAoB,sBAAsB,eAAe,CAC5H,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAChE,IAAI,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,sBAAsB,CAC9B,qDAAqD,IAAI,CAAC,IAAI,eAAe,IAAI,CAAC,MAAM,SAAS,MAAM,EAAE,CAC1G,CAAC;IACJ,CAAC;IACD,IAAI,QAAiB,CAAC;IACtB,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,sBAAsB,CAC9B,iCAAiC,IAAI,CAAC,IAAI,uBAAuB;YAC/D,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAC9D,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GAAI,QAA2C,EAAE,SAAS,CAAC;IAC1E,IAAI,SAAS,KAAK,gCAAgC,EAAE,CAAC;QACnD,MAAM,IAAI,sBAAsB,CAC9B,iCAAiC,IAAI,CAAC,IAAI,uBAAuB;YAC/D,IAAI,MAAM,CAAC,SAAS,CAAC,iBAAiB,gCAAgC,GAAG,CAC5E,CAAC;IACJ,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xemahq/biome-supply-chain",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Shared cosign supply-chain verification for Xema biomes: the single cosign CLI exec + the signature/provenance verdict enums used by biome-fetcher-api (OCI bundle verification) and xema-store-api. Node-builtins only.",
5
5
  "license": "LicenseRef-Xema-BSL-1.1",
6
6
  "author": "Neuralchowder Inc. <developer@xema.dev> (https://xema.dev)",
@@ -29,8 +29,7 @@
29
29
  "main": "./dist/index.js",
30
30
  "types": "./dist/index.d.ts",
31
31
  "files": [
32
- "dist",
33
- "src"
32
+ "dist"
34
33
  ],
35
34
  "devDependencies": {
36
35
  "@types/node": "25.2.3",
package/src/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from './lib/verdicts';
2
- export * from './lib/cosign-exec';
@@ -1,188 +0,0 @@
1
- import { spawn } from 'node:child_process';
2
-
3
- import { CosignVerifyOutcome } from './verdicts';
4
-
5
- /** Default cosign binary name (overridable per call). */
6
- const DEFAULT_COSIGN_BIN = 'cosign';
7
-
8
- interface CosignRunResult {
9
- readonly code: number;
10
- readonly stderr: string;
11
- }
12
-
13
- /**
14
- * The single canonical cosign invocation. Spawns the binary, captures stderr,
15
- * and resolves with the exit code (never rejects on a non-zero exit — the
16
- * caller decides whether a non-zero code is an error or a "failed" verdict).
17
- * Rejects only when the process cannot be spawned at all.
18
- */
19
- function runCosign(
20
- bin: string,
21
- args: readonly string[],
22
- ): Promise<CosignRunResult> {
23
- return new Promise((resolve, reject) => {
24
- const child = spawn(bin, [...args], {
25
- stdio: ['ignore', 'pipe', 'pipe'],
26
- });
27
- let stderr = '';
28
- child.stderr?.on('data', (chunk: Buffer) => {
29
- stderr += chunk.toString();
30
- });
31
- child.on('error', reject);
32
- child.on('close', (code) => {
33
- resolve({ code: code ?? 1, stderr });
34
- });
35
- });
36
- }
37
-
38
- /** Throws if the cosign CLI is not available on PATH. */
39
- export async function ensureCosignAvailable(
40
- bin: string = DEFAULT_COSIGN_BIN,
41
- ): Promise<void> {
42
- try {
43
- const { code, stderr } = await runCosign(bin, ['version']);
44
- if (code !== 0) {
45
- throw new Error(`\`${bin} version\` exited ${code}: ${stderr.slice(-200)}`);
46
- }
47
- } catch (cause) {
48
- throw new Error(
49
- `cosign CLI is not on PATH — install from https://github.com/sigstore/cosign ` +
50
- `(${cause instanceof Error ? cause.message : String(cause)})`,
51
- );
52
- }
53
- }
54
-
55
- export interface VerifyCosignSignatureInput {
56
- readonly ociRef: string;
57
- /** Exact keyless certificate-identity URIs (any one may match). */
58
- readonly trustedIdentities: readonly string[];
59
- readonly oidcIssuer?: string | undefined;
60
- /** Keyed verification: path to the public key (mutually exclusive w/ keyless). */
61
- readonly keyPath?: string | undefined;
62
- readonly bin?: string | undefined;
63
- }
64
-
65
- /**
66
- * Verify a signature on an OCI ref (keyless identity allowlist OR keyed).
67
- * Throws on non-verification; resolves on success. Mirrors the fetcher's
68
- * former inline behaviour.
69
- */
70
- export async function verifyCosignSignature(
71
- input: VerifyCosignSignatureInput,
72
- ): Promise<void> {
73
- const bin = input.bin ?? DEFAULT_COSIGN_BIN;
74
- const args: string[] = ['verify'];
75
- if (input.keyPath) {
76
- args.push('--key', input.keyPath);
77
- } else {
78
- if (input.trustedIdentities.length === 0) {
79
- throw new Error(
80
- 'verifyCosignSignature: keyless mode requires at least one trusted identity',
81
- );
82
- }
83
- for (const id of input.trustedIdentities) {
84
- args.push('--certificate-identity', id);
85
- }
86
- if (input.oidcIssuer) {
87
- args.push('--certificate-oidc-issuer', input.oidcIssuer);
88
- }
89
- }
90
- args.push(input.ociRef);
91
- const { code, stderr } = await runCosign(bin, args);
92
- if (code !== 0) {
93
- throw new Error(`${bin} verify failed (code=${code}): ${stderr.slice(-200)}`);
94
- }
95
- }
96
-
97
- export interface VerifyCosignAttestationInput {
98
- readonly ociRef: string;
99
- readonly predicateType: string;
100
- readonly trustedIdentities: readonly string[];
101
- readonly oidcIssuer?: string | undefined;
102
- readonly keyPath?: string | undefined;
103
- readonly bin?: string | undefined;
104
- }
105
-
106
- /**
107
- * Verify an in-toto/SLSA attestation on an OCI ref. Throws on
108
- * non-verification; resolves on success.
109
- */
110
- export async function verifyCosignAttestation(
111
- input: VerifyCosignAttestationInput,
112
- ): Promise<void> {
113
- const bin = input.bin ?? DEFAULT_COSIGN_BIN;
114
- const args: string[] = ['verify-attestation', '--type', input.predicateType];
115
- if (input.keyPath) {
116
- args.push('--key', input.keyPath);
117
- } else {
118
- if (input.trustedIdentities.length === 0) {
119
- throw new Error(
120
- 'verifyCosignAttestation: keyless mode requires at least one trusted identity',
121
- );
122
- }
123
- for (const id of input.trustedIdentities) {
124
- args.push('--certificate-identity', id);
125
- }
126
- if (input.oidcIssuer) {
127
- args.push('--certificate-oidc-issuer', input.oidcIssuer);
128
- }
129
- }
130
- args.push(input.ociRef);
131
- const { code, stderr } = await runCosign(bin, args);
132
- if (code !== 0) {
133
- throw new Error(
134
- `${bin} verify-attestation failed (code=${code}): ${stderr.slice(-200)}`,
135
- );
136
- }
137
- }
138
-
139
- export interface VerifyCosignBlobInput {
140
- /** Path to the artifact bytes on disk (caller owns fetch/temp-file lifecycle). */
141
- readonly artifactPath: string;
142
- /** Path to the detached signature bundle on disk. */
143
- readonly bundlePath: string;
144
- /** Keyless certificate-identity REGEXPS (any one may match). */
145
- readonly trustedIdentityRegexps: readonly string[];
146
- readonly oidcIssuer?: string | undefined;
147
- readonly bin?: string | undefined;
148
- }
149
-
150
- export interface VerifyCosignBlobResult {
151
- readonly outcome: CosignVerifyOutcome;
152
- /** The identity regexp that matched, when Verified. */
153
- readonly matchedIdentity?: string | undefined;
154
- }
155
-
156
- /**
157
- * Verify a detached signature over a blob (`cosign verify-blob --bundle`).
158
- * Tries each trusted identity regexp; the first that verifies wins. Returns a
159
- * neutral {@link CosignVerifyOutcome} (never throws on a failed verification —
160
- * an empty trust list or all-mismatch resolves to `Failed`). The caller owns
161
- * artifact/bundle materialisation on disk.
162
- */
163
- export async function verifyCosignBlob(
164
- input: VerifyCosignBlobInput,
165
- ): Promise<VerifyCosignBlobResult> {
166
- const bin = input.bin ?? DEFAULT_COSIGN_BIN;
167
- if (input.trustedIdentityRegexps.length === 0) {
168
- return { outcome: CosignVerifyOutcome.Failed };
169
- }
170
- for (const identity of input.trustedIdentityRegexps) {
171
- const args: string[] = [
172
- 'verify-blob',
173
- '--bundle',
174
- input.bundlePath,
175
- '--certificate-identity-regexp',
176
- identity,
177
- ];
178
- if (input.oidcIssuer) {
179
- args.push('--certificate-oidc-issuer', input.oidcIssuer);
180
- }
181
- args.push(input.artifactPath);
182
- const { code } = await runCosign(bin, args);
183
- if (code === 0) {
184
- return { outcome: CosignVerifyOutcome.Verified, matchedIdentity: identity };
185
- }
186
- }
187
- return { outcome: CosignVerifyOutcome.Failed };
188
- }
@@ -1,57 +0,0 @@
1
- /**
2
- * Shared cosign supply-chain verdict vocabulary.
3
- *
4
- * This is the single source of truth for the lowercase verdict/error enums
5
- * that `biome-fetcher-api` (OCI bundle verification) previously duplicated
6
- * locally. They are value-identical to that former copy, so adopting this
7
- * package is a pure de-duplication with no wire/behaviour change.
8
- *
9
- * (`@xemahq/biome-package` was a second consumer until 2026-08-01, when it was
10
- * deleted: it emitted a 4-layer OCI artifact whose layers carry no
11
- * `org.opencontainers.image.title`, so the fetcher's `oras pull` skipped every
12
- * one of them and materialised nothing. `xema biome publish` is now the single
13
- * biome packager.)
14
- *
15
- * NOTE: `xema-store-api` keeps its OWN UPPERCASE `SignatureVerdict` /
16
- * `ProvenanceVerdict` (persisted + OpenAPI + cross-service event wire); it
17
- * consumes only the cosign EXEC + {@link CosignVerifyOutcome} from this
18
- * package, mapping the neutral outcome to its own wire enum.
19
- */
20
-
21
- /** Signature verification verdict. */
22
- export enum SignatureVerdict {
23
- Valid = 'valid',
24
- Invalid = 'invalid',
25
- Unsigned = 'unsigned',
26
- }
27
-
28
- /** SLSA attestation / provenance verdict. */
29
- export enum ProvenanceVerdict {
30
- Valid = 'valid',
31
- Invalid = 'invalid',
32
- Missing = 'missing',
33
- }
34
-
35
- /** Stable, typed reasons a cosign verification may reject an artifact. */
36
- export enum CosignErrorCode {
37
- SignatureMissing = 'BIOME_SIGNATURE_MISSING',
38
- SignatureInvalid = 'BIOME_SIGNATURE_INVALID',
39
- IdentityNotTrusted = 'BIOME_SIGNATURE_IDENTITY_NOT_TRUSTED',
40
- ProvenanceMissing = 'BIOME_PROVENANCE_MISSING',
41
- ProvenanceInvalid = 'BIOME_PROVENANCE_INVALID',
42
- CosignUnavailable = 'BIOME_COSIGN_UNAVAILABLE',
43
- }
44
-
45
- /**
46
- * Casing-neutral internal outcome of a detached-blob verification. The blob
47
- * path (store) maps this to its own UPPERCASE wire verdict; it deliberately
48
- * does not leak the wire casing into the shared exec layer.
49
- */
50
- export enum CosignVerifyOutcome {
51
- Verified = 'verified',
52
- Failed = 'failed',
53
- }
54
-
55
- /** Canonical SLSA provenance predicate type. */
56
- export const SLSA_PROVENANCE_PREDICATE_TYPE =
57
- 'https://slsa.dev/provenance/v1' as const;