protect-mcp 0.6.2 → 0.6.3

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/dist/cli.mjs CHANGED
@@ -145,8 +145,8 @@ async function handleInit(argv) {
145
145
  let keypair;
146
146
  {
147
147
  const { randomBytes } = await import("crypto");
148
- const { ed25519 } = await import("./ed25519-DZMMNNVE.mjs");
149
- const { bytesToHex } = await import("./utils-6AYZFE5A.mjs");
148
+ const { ed25519 } = await import("@noble/curves/ed25519");
149
+ const { bytesToHex } = await import("@noble/hashes/utils");
150
150
  const privateKey = randomBytes(32);
151
151
  const publicKey = ed25519.getPublicKey(privateKey);
152
152
  keypair = {
@@ -765,8 +765,8 @@ ${bold("protect-mcp quickstart")}
765
765
  const { randomBytes } = await import("crypto");
766
766
  let keypair;
767
767
  try {
768
- const { ed25519 } = await import("./ed25519-DZMMNNVE.mjs");
769
- const { bytesToHex } = await import("./utils-6AYZFE5A.mjs");
768
+ const { ed25519 } = await import("@noble/curves/ed25519");
769
+ const { bytesToHex } = await import("@noble/hashes/utils");
770
770
  const privateKey = randomBytes(32);
771
771
  const publicKey = ed25519.getPublicKey(privateKey);
772
772
  keypair = {
@@ -1111,8 +1111,8 @@ ${bold("protect-mcp init-hooks")}
1111
1111
  if (!existsSync(keysDir)) mkdirSync(keysDir, { recursive: true });
1112
1112
  const { randomBytes: rb } = await import("crypto");
1113
1113
  try {
1114
- const { ed25519 } = await import("./ed25519-DZMMNNVE.mjs");
1115
- const { bytesToHex } = await import("./utils-6AYZFE5A.mjs");
1114
+ const { ed25519 } = await import("@noble/curves/ed25519");
1115
+ const { bytesToHex } = await import("@noble/hashes/utils");
1116
1116
  const privateKey = rb(32);
1117
1117
  const publicKey = ed25519.getPublicKey(privateKey);
1118
1118
  writeFileSync(keyPath, JSON.stringify({
package/dist/index.d.mts CHANGED
@@ -2019,6 +2019,29 @@ interface ApprovalResult {
2019
2019
  contextHash: string;
2020
2020
  /** Timestamp of approval */
2021
2021
  approvedAt: string;
2022
+ /** On failure, a machine-readable reason (e.g. 'invalid_signature'). */
2023
+ reason?: string;
2024
+ }
2025
+ /**
2026
+ * The registered credential public key, extracted from the COSE_Key at
2027
+ * registration. ES256 keys are an uncompressed P-256 point; EdDSA keys are a
2028
+ * 32-byte Ed25519 public key.
2029
+ */
2030
+ interface CredentialPublicKey {
2031
+ /** COSE algorithm: -7 = ES256 (P-256 / ECDSA), -8 = EdDSA (Ed25519). */
2032
+ alg: -7 | -8;
2033
+ /** Public key, hex. ES256: 65-byte uncompressed point (0x04 || x || y). EdDSA: 32-byte key. */
2034
+ publicKeyHex: string;
2035
+ }
2036
+ interface VerifyAssertionOptions {
2037
+ /** Allowed origin(s) the assertion must come from, e.g. 'https://app.scopeblind.com'. Defaults to https://<rpId>. */
2038
+ expectedOrigin?: string | string[];
2039
+ /** Require the UV (user-verified / biometric or PIN) flag. Default true. */
2040
+ requireUserVerification?: boolean;
2041
+ /** The signCount stored from the previous assertion; a non-increasing counter signals a cloned authenticator. */
2042
+ prevSignCount?: number;
2043
+ /** Override 'now' (ms) for testing. */
2044
+ now?: number;
2022
2045
  }
2023
2046
  /**
2024
2047
  * Create a WebAuthn challenge for approving a tool call.
@@ -2055,17 +2078,22 @@ declare function toCredentialRequestOptions(challenge: ApprovalChallenge, allowC
2055
2078
  };
2056
2079
  };
2057
2080
  /**
2058
- * Verify a WebAuthn assertion from the client.
2059
- *
2060
- * This is a simplified verification that checks the structure
2061
- * and extracts the authenticator data. For production use with
2062
- * full signature verification, use the @simplewebauthn/server package.
2063
- *
2064
- * @param challenge - The original challenge
2065
- * @param assertion - The assertion from navigator.credentials.get()
2066
- * @returns ApprovalResult with verification details
2067
- */
2068
- declare function verifyApprovalAssertion(challenge: ApprovalChallenge, assertion: ApprovalAssertion): ApprovalResult;
2081
+ * Verify a WebAuthn assertion: full, fail-closed verification of a passkey or
2082
+ * security-key co-sign. This proves a SPECIFIC human authorized a SPECIFIC
2083
+ * action with a hardware-held key the host operator cannot exfiltrate. It
2084
+ * checks, in order: challenge freshness; clientDataJSON type, challenge, and
2085
+ * origin; the rpIdHash; the UP (and, by default, UV) flags; the authenticator
2086
+ * signature over authenticatorData || SHA-256(clientDataJSON) using the
2087
+ * registered credential public key (ES256 or EdDSA); and signCount monotonicity
2088
+ * (clone detection) when a previous count is supplied. Any failure returns
2089
+ * valid:false with a reason; nothing is trusted on a partial check.
2090
+ *
2091
+ * @param challenge - the original challenge
2092
+ * @param assertion - the assertion from navigator.credentials.get()
2093
+ * @param credentialPublicKey - the registered public key for assertion.credentialId
2094
+ * @param opts - origin / UV / signCount / clock options
2095
+ */
2096
+ declare function verifyApprovalAssertion(challenge: ApprovalChallenge, assertion: ApprovalAssertion, credentialPublicKey?: CredentialPublicKey, opts?: VerifyAssertionOptions): ApprovalResult;
2069
2097
  /**
2070
2098
  * Create the approval receipt payload for embedding in an Acta receipt.
2071
2099
  *
package/dist/index.d.ts CHANGED
@@ -2019,6 +2019,29 @@ interface ApprovalResult {
2019
2019
  contextHash: string;
2020
2020
  /** Timestamp of approval */
2021
2021
  approvedAt: string;
2022
+ /** On failure, a machine-readable reason (e.g. 'invalid_signature'). */
2023
+ reason?: string;
2024
+ }
2025
+ /**
2026
+ * The registered credential public key, extracted from the COSE_Key at
2027
+ * registration. ES256 keys are an uncompressed P-256 point; EdDSA keys are a
2028
+ * 32-byte Ed25519 public key.
2029
+ */
2030
+ interface CredentialPublicKey {
2031
+ /** COSE algorithm: -7 = ES256 (P-256 / ECDSA), -8 = EdDSA (Ed25519). */
2032
+ alg: -7 | -8;
2033
+ /** Public key, hex. ES256: 65-byte uncompressed point (0x04 || x || y). EdDSA: 32-byte key. */
2034
+ publicKeyHex: string;
2035
+ }
2036
+ interface VerifyAssertionOptions {
2037
+ /** Allowed origin(s) the assertion must come from, e.g. 'https://app.scopeblind.com'. Defaults to https://<rpId>. */
2038
+ expectedOrigin?: string | string[];
2039
+ /** Require the UV (user-verified / biometric or PIN) flag. Default true. */
2040
+ requireUserVerification?: boolean;
2041
+ /** The signCount stored from the previous assertion; a non-increasing counter signals a cloned authenticator. */
2042
+ prevSignCount?: number;
2043
+ /** Override 'now' (ms) for testing. */
2044
+ now?: number;
2022
2045
  }
2023
2046
  /**
2024
2047
  * Create a WebAuthn challenge for approving a tool call.
@@ -2055,17 +2078,22 @@ declare function toCredentialRequestOptions(challenge: ApprovalChallenge, allowC
2055
2078
  };
2056
2079
  };
2057
2080
  /**
2058
- * Verify a WebAuthn assertion from the client.
2059
- *
2060
- * This is a simplified verification that checks the structure
2061
- * and extracts the authenticator data. For production use with
2062
- * full signature verification, use the @simplewebauthn/server package.
2063
- *
2064
- * @param challenge - The original challenge
2065
- * @param assertion - The assertion from navigator.credentials.get()
2066
- * @returns ApprovalResult with verification details
2067
- */
2068
- declare function verifyApprovalAssertion(challenge: ApprovalChallenge, assertion: ApprovalAssertion): ApprovalResult;
2081
+ * Verify a WebAuthn assertion: full, fail-closed verification of a passkey or
2082
+ * security-key co-sign. This proves a SPECIFIC human authorized a SPECIFIC
2083
+ * action with a hardware-held key the host operator cannot exfiltrate. It
2084
+ * checks, in order: challenge freshness; clientDataJSON type, challenge, and
2085
+ * origin; the rpIdHash; the UP (and, by default, UV) flags; the authenticator
2086
+ * signature over authenticatorData || SHA-256(clientDataJSON) using the
2087
+ * registered credential public key (ES256 or EdDSA); and signCount monotonicity
2088
+ * (clone detection) when a previous count is supplied. Any failure returns
2089
+ * valid:false with a reason; nothing is trusted on a partial check.
2090
+ *
2091
+ * @param challenge - the original challenge
2092
+ * @param assertion - the assertion from navigator.credentials.get()
2093
+ * @param credentialPublicKey - the registered public key for assertion.credentialId
2094
+ * @param opts - origin / UV / signCount / clock options
2095
+ */
2096
+ declare function verifyApprovalAssertion(challenge: ApprovalChallenge, assertion: ApprovalAssertion, credentialPublicKey?: CredentialPublicKey, opts?: VerifyAssertionOptions): ApprovalResult;
2069
2097
  /**
2070
2098
  * Create the approval receipt payload for embedding in an Acta receipt.
2071
2099
  *