New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@sigstore/sign

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sigstore/sign - npm Package Compare versions

Comparing version
4.0.1
to
4.1.0
+18
dist/config.d.ts
import { SigningConfig } from '@sigstore/protobuf-specs';
import { BundleBuilder } from './bundler/base';
import { IdentityProvider } from './identity';
import type { MakeFetchHappenOptions } from 'make-fetch-happen';
type Retry = MakeFetchHappenOptions['retry'];
type BundleType = 'messageSignature' | 'dsseEnvelope';
type FetchOptions = {
retry?: Retry;
timeout?: number | undefined;
};
type Options = {
signingConfig: SigningConfig;
identityProvider: IdentityProvider;
bundleType: BundleType;
fetchOptions?: FetchOptions;
};
export declare function bundleBuilderFromSigningConfig(options: Options): BundleBuilder;
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.bundleBuilderFromSigningConfig = bundleBuilderFromSigningConfig;
/*
Copyright 2025 The Sigstore Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const protobuf_specs_1 = require("@sigstore/protobuf-specs");
const dsse_1 = require("./bundler/dsse");
const message_1 = require("./bundler/message");
const signer_1 = require("./signer");
const witness_1 = require("./witness");
const MAX_CA_API_VERSION = 1;
const MAX_TLOG_API_VERSION = 2;
const MAX_TSA_API_VERSION = 1;
const DEFAULT_TIMEOUT = 5000;
const DEFAULT_REKORV2_TIMEOUT = 20000;
const DEFAULT_RETRY = { retries: 2 };
// Creates a BundleBuilder based on the provided SigningConfig
function bundleBuilderFromSigningConfig(options) {
const { signingConfig, identityProvider, bundleType } = options;
const fetchOptions = options.fetchOptions || {
timeout: DEFAULT_TIMEOUT,
retry: DEFAULT_RETRY,
};
const signer = fulcioSignerFromConfig(signingConfig, identityProvider, fetchOptions);
const witnesses = witnessesFromConfig(signingConfig, fetchOptions);
switch (bundleType) {
case 'messageSignature':
return new message_1.MessageSignatureBundleBuilder({ signer, witnesses });
case 'dsseEnvelope':
return new dsse_1.DSSEBundleBuilder({ signer, witnesses });
}
}
function fulcioSignerFromConfig(signingConfig, identityProvider, fetchOptions) {
const service = certAuthorityService(signingConfig);
return new signer_1.FulcioSigner({
fulcioBaseURL: service.url,
identityProvider: identityProvider,
timeout: fetchOptions.timeout,
retry: fetchOptions.retry,
});
}
function witnessesFromConfig(signingConfig, fetchOptions) {
const witnesses = [];
if (signingConfig.rekorTlogConfig) {
if (signingConfig.rekorTlogConfig.selector !== protobuf_specs_1.ServiceSelector.ANY) {
throw new Error('Unsupported Rekor TLog selector in signing configuration');
}
const tlog = tlogService(signingConfig);
witnesses.push(new witness_1.RekorWitness({
rekorBaseURL: tlog.url,
majorApiVersion: tlog.majorApiVersion,
retry: fetchOptions.retry,
timeout:
// Ensure Rekor V2 has at least a 20 second timeout
tlog.majorApiVersion === 1
? fetchOptions.timeout
: Math.min(fetchOptions.timeout ||
/* istanbul ignore next */ DEFAULT_TIMEOUT, DEFAULT_REKORV2_TIMEOUT),
}));
}
if (signingConfig.tsaConfig) {
if (signingConfig.tsaConfig.selector !== protobuf_specs_1.ServiceSelector.ANY) {
throw new Error('Unsupported TSA selector in signing configuration');
}
const tsa = tsaService(signingConfig);
witnesses.push(new witness_1.TSAWitness({
tsaBaseURL: tsa.url,
retry: fetchOptions.retry,
timeout: fetchOptions.timeout,
}));
}
return witnesses;
}
// Returns the first valid CA service from the signing configuration
function certAuthorityService(signingConfig) {
const compatibleCAs = filterServicesByMaxAPIVersion(signingConfig.caUrls, MAX_CA_API_VERSION);
const sortedCAs = sortServicesByStartDate(compatibleCAs);
if (sortedCAs.length === 0) {
throw new Error('No valid CA services found in signing configuration');
}
return sortedCAs[0];
}
// Returns the first valid TLog service from the signing configuration
function tlogService(signingConfig) {
const compatibleTLogs = filterServicesByMaxAPIVersion(signingConfig.rekorTlogUrls, MAX_TLOG_API_VERSION);
const sortedTLogs = sortServicesByStartDate(compatibleTLogs);
if (sortedTLogs.length === 0) {
throw new Error('No valid TLogs found in signing configuration');
}
return sortedTLogs[0];
}
// Returns the first valid TSA service from the signing configuration
function tsaService(signingConfig) {
const compatibleTSAs = filterServicesByMaxAPIVersion(signingConfig.tsaUrls, MAX_TSA_API_VERSION);
const sortedTSAs = sortServicesByStartDate(compatibleTSAs);
if (sortedTSAs.length === 0) {
throw new Error('No valid TSAs found in signing configuration');
}
return sortedTSAs[0];
}
// Returns the services sorted by start date (most recent first), filtering out
// any services that have an end date in the past
function sortServicesByStartDate(services) {
const now = new Date();
// Filter out any services that have an end date in the past
const validServices = services.filter((service) => {
// If there's no end date, the service is still valid
if (!service.validFor?.end) {
return true;
}
// Keep services whose end date is in the future or present
return service.validFor.end >= now;
});
return validServices.sort((a, b) => {
/* istanbul ignore next */
const aStart = a.validFor?.start?.getTime() ?? 0;
/* istanbul ignore next */
const bStart = b.validFor?.start?.getTime() ?? 0;
// Sort descending (most recent first)
return bStart - aStart;
});
}
// Returns a filtered list of services whose major API version is less than or
// equal to the specified version
function filterServicesByMaxAPIVersion(services, apiVersion) {
// Filter out any services with a major API version greater than the specified version
return services.filter((service) => {
return service.majorApiVersion <= apiVersion;
});
}
import { TransparencyLogEntry } from '@sigstore/protobuf-specs';
import { CreateEntryRequest } from '@sigstore/protobuf-specs/rekor/v2';
import type { FetchOptions } from '../types/fetch';
export type RekorOptions = {
baseURL: string;
} & FetchOptions;
/**
* Rekor API client.
*/
export declare class RekorV2 {
private options;
constructor(options: RekorOptions);
createEntry(proposedEntry: CreateEntryRequest): Promise<TransparencyLogEntry>;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RekorV2 = void 0;
/*
Copyright 2025 The Sigstore Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const fetch_1 = require("./fetch");
const protobuf_specs_1 = require("@sigstore/protobuf-specs");
const v2_1 = require("@sigstore/protobuf-specs/rekor/v2");
/**
* Rekor API client.
*/
class RekorV2 {
options;
constructor(options) {
this.options = options;
}
async createEntry(proposedEntry) {
const { baseURL, timeout, retry } = this.options;
const url = `${baseURL}/api/v2/log/entries`;
const response = await (0, fetch_1.fetchWithRetry)(url, {
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify(v2_1.CreateEntryRequest.toJSON(proposedEntry)),
timeout,
retry,
});
return response.json().then((data) => protobuf_specs_1.TransparencyLogEntry.fromJSON(data));
}
}
exports.RekorV2 = RekorV2;
+2
-0

@@ -9,2 +9,4 @@ "use strict";

class BaseBundleBuilder {
signer;
witnesses;
constructor(options) {

@@ -11,0 +13,0 @@ this.signer = options.signer;

@@ -24,2 +24,3 @@ "use strict";

class DSSEBundleBuilder extends base_1.BaseBundleBuilder {
certificateChain;
constructor(options) {

@@ -26,0 +27,0 @@ super(options);

@@ -22,2 +22,4 @@ "use strict";

class InternalError extends Error {
code;
cause;
constructor({ code, message, cause, }) {

@@ -24,0 +26,0 @@ super(message);

@@ -20,2 +20,4 @@ "use strict";

class HTTPError extends Error {
statusCode;
location;
constructor({ status, message, location, }) {

@@ -22,0 +24,0 @@ super(`(${status}) ${message}`);

@@ -24,2 +24,3 @@ "use strict";

class Fulcio {
options;
constructor(options) {

@@ -26,0 +27,0 @@ this.options = options;

@@ -24,2 +24,3 @@ "use strict";

class Rekor {
options;
constructor(options) {

@@ -26,0 +27,0 @@ this.options = options;

@@ -21,2 +21,3 @@ "use strict";

class TimestampAuthority {
options;
constructor(options) {

@@ -27,3 +28,8 @@ this.options = options;

const { baseURL, timeout, retry } = this.options;
const url = `${baseURL}/api/v1/timestamp`;
// Account for the fact that the TSA URL may already include the full
// path if the client was initalized from a `SigningConfig` service entry
// (which always uses the full URL).
const url = new URL(baseURL).pathname === '/'
? `${baseURL}/api/v1/timestamp`
: baseURL;
const response = await (0, fetch_1.fetchWithRetry)(url, {

@@ -30,0 +36,0 @@ headers: {

@@ -31,2 +31,3 @@ "use strict";

class CIContextProvider {
audience;
/* istanbul ignore next */

@@ -33,0 +34,0 @@ constructor(audience = 'sigstore') {

export type { Bundle } from '@sigstore/bundle';
export { DSSEBundleBuilder, MessageSignatureBundleBuilder } from './bundler';
export type { Artifact, BundleBuilder, BundleBuilderOptions } from './bundler';
export { bundleBuilderFromSigningConfig } from './config';
export { InternalError } from './error';

@@ -5,0 +6,0 @@ export { CIContextProvider } from './identity';

+3
-1
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TSAWitness = exports.RekorWitness = exports.DEFAULT_REKOR_URL = exports.FulcioSigner = exports.DEFAULT_FULCIO_URL = exports.CIContextProvider = exports.InternalError = exports.MessageSignatureBundleBuilder = exports.DSSEBundleBuilder = void 0;
exports.TSAWitness = exports.RekorWitness = exports.DEFAULT_REKOR_URL = exports.FulcioSigner = exports.DEFAULT_FULCIO_URL = exports.CIContextProvider = exports.InternalError = exports.bundleBuilderFromSigningConfig = exports.MessageSignatureBundleBuilder = exports.DSSEBundleBuilder = void 0;
var bundler_1 = require("./bundler");
Object.defineProperty(exports, "DSSEBundleBuilder", { enumerable: true, get: function () { return bundler_1.DSSEBundleBuilder; } });
Object.defineProperty(exports, "MessageSignatureBundleBuilder", { enumerable: true, get: function () { return bundler_1.MessageSignatureBundleBuilder; } });
var config_1 = require("./config");
Object.defineProperty(exports, "bundleBuilderFromSigningConfig", { enumerable: true, get: function () { return config_1.bundleBuilderFromSigningConfig; } });
var error_1 = require("./error");

@@ -8,0 +10,0 @@ Object.defineProperty(exports, "InternalError", { enumerable: true, get: function () { return error_1.InternalError; } });

@@ -22,2 +22,3 @@ "use strict";

class CAClient {
fulcio;
constructor(options) {

@@ -24,0 +25,0 @@ this.fulcio = new fulcio_1.Fulcio({

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -22,3 +19,3 @@ exports.EphemeralSigner = void 0;

*/
const crypto_1 = __importDefault(require("crypto"));
const crypto_1 = require("crypto");
const EC_KEYPAIR_TYPE = 'ec';

@@ -30,4 +27,5 @@ const P256_CURVE = 'P-256';

class EphemeralSigner {
keypair;
constructor() {
this.keypair = crypto_1.default.generateKeyPairSync(EC_KEYPAIR_TYPE, {
this.keypair = (0, crypto_1.generateKeyPairSync)(EC_KEYPAIR_TYPE, {
namedCurve: P256_CURVE,

@@ -37,3 +35,3 @@ });

async sign(data) {
const signature = crypto_1.default.sign(null, data, this.keypair.privateKey);
const signature = (0, crypto_1.sign)('sha256', data, this.keypair.privateKey);
const publicKey = this.keypair.publicKey

@@ -40,0 +38,0 @@ .export({ format: 'pem', type: 'spki' })

@@ -29,2 +29,5 @@ "use strict";

class FulcioSigner {
ca;
identityProvider;
keyHolder;
constructor(options) {

@@ -31,0 +34,0 @@ this.ca = new ca_1.CAClient({

@@ -0,1 +1,3 @@

import type { TransparencyLogEntry } from '@sigstore/bundle';
import type { CreateEntryRequest } from '@sigstore/protobuf-specs/rekor/v2';
import type { Entry, ProposedEntry } from '../../external/rekor';

@@ -17,1 +19,12 @@ import type { FetchOptions } from '../../types/fetch';

}
export interface TLogV2 {
createEntry: (createEntryRequest: CreateEntryRequest) => Promise<TransparencyLogEntry>;
}
export type TLogV2ClientOptions = {
rekorBaseURL: string;
} & FetchOptions;
export declare class TLogV2Client implements TLogV2 {
private rekor;
constructor(options: TLogV2ClientOptions);
createEntry(createEntryRequest: CreateEntryRequest): Promise<TransparencyLogEntry>;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TLogClient = void 0;
exports.TLogV2Client = exports.TLogClient = void 0;
/*
Copyright 2023 The Sigstore Authors.
Copyright 2025 The Sigstore Authors.

@@ -22,3 +22,6 @@ Licensed under the Apache License, Version 2.0 (the "License");

const rekor_1 = require("../../external/rekor");
const rekor_v2_1 = require("../../external/rekor-v2");
class TLogClient {
rekor;
fetchOnConflict;
constructor(options) {

@@ -63,1 +66,29 @@ this.fetchOnConflict = options.fetchOnConflict ?? false;

}
class TLogV2Client {
rekor;
constructor(options) {
this.rekor = new rekor_v2_1.RekorV2({
baseURL: options.rekorBaseURL,
retry: options.retry,
timeout: options.timeout,
});
}
async createEntry(createEntryRequest) {
let entry;
try {
entry = await this.rekor.createEntry(createEntryRequest);
}
catch (err) {
(0, error_1.internalError)(err, 'TLOG_CREATE_ENTRY_ERROR', 'error creating tlog entry');
}
if (entry.logId === undefined || entry.kindVersion === undefined) {
(0, error_1.internalError)(new Error('invalid tlog entry'), 'TLOG_CREATE_ENTRY_ERROR', 'error creating tlog entry');
}
return {
...entry,
logId: entry.logId,
kindVersion: entry.kindVersion,
};
}
}
exports.TLogV2Client = TLogV2Client;

@@ -0,3 +1,5 @@

import type { CreateEntryRequest } from '@sigstore/protobuf-specs/rekor/v2';
import type { ProposedEntry } from '../../external/rekor';
import type { SignatureBundle } from '../witness';
export declare function toProposedEntry(content: SignatureBundle, publicKey: string, entryType?: 'dsse' | 'intoto'): ProposedEntry;
export declare function toCreateEntryRequest(content: SignatureBundle, publicKey: string): CreateEntryRequest;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.toProposedEntry = toProposedEntry;
exports.toCreateEntryRequest = toCreateEntryRequest;
/*
Copyright 2023 The Sigstore Authors.
Copyright 2025 The Sigstore Authors.

@@ -20,2 +21,3 @@ Licensed under the Apache License, Version 2.0 (the "License");

const bundle_1 = require("@sigstore/bundle");
const protobuf_specs_1 = require("@sigstore/protobuf-specs");
const util_1 = require("../../util");

@@ -142,1 +144,56 @@ const SHA256_ALGORITHM = 'sha256';

}
function toCreateEntryRequest(content, publicKey) {
switch (content.$case) {
case 'dsseEnvelope':
return toCreateEntryRequestDSSE(content.dsseEnvelope, publicKey);
case 'messageSignature':
return toCreateEntryRequestMessageSignature(content.messageSignature, publicKey);
}
}
function toCreateEntryRequestDSSE(envelope, publicKey) {
return {
spec: {
$case: 'dsseRequestV002',
dsseRequestV002: {
envelope: envelope,
verifiers: [
{
// TODO: We need to add support of passing the key details in the
// signature bundle. For now we're hardcoding the key details here.
keyDetails: protobuf_specs_1.PublicKeyDetails.PKIX_ECDSA_P256_SHA_256,
verifier: {
$case: 'x509Certificate',
x509Certificate: {
rawBytes: util_1.pem.toDER(publicKey),
},
},
},
],
},
},
};
}
function toCreateEntryRequestMessageSignature(messageSignature, publicKey) {
return {
spec: {
$case: 'hashedRekordRequestV002',
hashedRekordRequestV002: {
digest: messageSignature.messageDigest.digest,
signature: {
content: messageSignature.signature,
verifier: {
// TODO: We need to add support of passing the key details in the
// signature bundle. For now we're hardcoding the key details here.
keyDetails: protobuf_specs_1.PublicKeyDetails.PKIX_ECDSA_P256_SHA_256,
verifier: {
$case: 'x509Certificate',
x509Certificate: {
rawBytes: util_1.pem.toDER(publicKey),
},
},
},
},
},
},
};
}

@@ -10,6 +10,9 @@ import { TLogClientOptions } from './client';

entryType?: 'dsse' | 'intoto';
majorApiVersion?: number;
};
export declare class RekorWitness implements Witness {
private tlog;
private tlogV1;
private tlogV2;
private entryType?;
private majorApiVersion;
constructor(options: RekorWitnessOptions);

@@ -16,0 +19,0 @@ testify(content: SignatureBundle, publicKey: string): Promise<TransparencyLogEntries>;

@@ -5,3 +5,3 @@ "use strict";

/*
Copyright 2023 The Sigstore Authors.
Copyright 2025 The Sigstore Authors.

@@ -25,13 +25,30 @@ Licensed under the Apache License, Version 2.0 (the "License");

class RekorWitness {
tlogV1;
tlogV2;
entryType;
majorApiVersion;
constructor(options) {
this.entryType = options.entryType;
this.tlog = new client_1.TLogClient({
this.majorApiVersion = options.majorApiVersion || 1;
this.tlogV1 = new client_1.TLogClient({
...options,
rekorBaseURL: options.rekorBaseURL || /* istanbul ignore next */ exports.DEFAULT_REKOR_URL,
});
this.tlogV2 = new client_1.TLogV2Client({
...options,
rekorBaseURL: options.rekorBaseURL || /* istanbul ignore next */ exports.DEFAULT_REKOR_URL,
});
}
async testify(content, publicKey) {
const proposedEntry = (0, entry_1.toProposedEntry)(content, publicKey, this.entryType);
const entry = await this.tlog.createEntry(proposedEntry);
return toTransparencyLogEntry(entry);
let tlogEntry;
if (this.majorApiVersion === 2) {
const request = (0, entry_1.toCreateEntryRequest)(content, publicKey);
tlogEntry = await this.tlogV2.createEntry(request);
}
else {
const proposedEntry = (0, entry_1.toProposedEntry)(content, publicKey, this.entryType);
const entry = await this.tlogV1.createEntry(proposedEntry);
tlogEntry = toTransparencyLogEntry(entry);
}
return { tlogEntries: [tlogEntry] };
}

@@ -65,5 +82,3 @@ }

};
return {
tlogEntries: [tlogEntry],
};
return tlogEntry;
}

@@ -70,0 +85,0 @@ function inclusionPromise(promise) {

@@ -24,2 +24,3 @@ "use strict";

class TSAClient {
tsa;
constructor(options) {

@@ -26,0 +27,0 @@ this.tsa = new tsa_1.TimestampAuthority({

@@ -21,2 +21,3 @@ "use strict";

class TSAWitness {
tsa;
constructor(options) {

@@ -23,0 +24,0 @@ this.tsa = new client_1.TSAClient({

{
"name": "@sigstore/sign",
"version": "4.0.1",
"version": "4.1.0",
"description": "Sigstore signing library",

@@ -37,6 +37,6 @@ "main": "dist/index.js",

"@sigstore/bundle": "^4.0.0",
"@sigstore/core": "^3.0.0",
"@sigstore/core": "^3.1.0",
"@sigstore/protobuf-specs": "^0.5.0",
"make-fetch-happen": "^15.0.2",
"proc-log": "^5.0.0",
"make-fetch-happen": "^15.0.3",
"proc-log": "^6.1.0",
"promise-retry": "^2.0.1"

@@ -43,0 +43,0 @@ },