Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 13 additions & 112 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 13 additions & 10 deletions packages/w3c-issuer/src/did-web/wellKnown/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,17 +134,20 @@ export const nextKeyId = (wellKnown: DidWellKnownDocument): number => {
// Filter for all key id
const keyIds = wellKnown?.verificationMethod?.map((s) => s?.id) ?? [];

// strip the key id to get the number
const keyIdNumbers = keyIds.map((s) => {
const parts = s?.split('#');
if (!parts) return 0;
return parts?.[parts.length - 1]?.split('keys-')?.[1];
});
// strip the key id to get the number (only for keys that follow 'keys-{number}' pattern)
const keyIdNumbers = keyIds
.map((s) => {
const parts = s?.split('#');
if (!parts || parts.length < 2) return null;
const fragment = parts[parts.length - 1];
// Only process if it follows the 'keys-' pattern
if (!fragment?.includes('keys-')) return null;
return fragment.split('keys-')[1];
})
.filter((s) => s !== null && s !== undefined); // Remove null/undefined values

// filter out the non-numeric values using Number and convert to number
const keyIdNumbersFiltered = keyIdNumbers
.filter((s) => !Number.isInteger(s))
.map((s) => Number(s));
// filter out the non-numeric values and convert to number
const keyIdNumbersFiltered = keyIdNumbers.filter((s) => !isNaN(Number(s))).map((s) => Number(s));

// get the max number
if (keyIdNumbersFiltered.length === 0) return 1;
Expand Down
13 changes: 12 additions & 1 deletion packages/w3c-issuer/src/did-web/wellKnown/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,18 @@ export const issueDID = async (didInput: IssuedDIDOption): Promise<IssuedDID> =>

const keyId = nextKeyId(wellKnownDid);

const generatedKeyPair = await generateKeyPair(didInput);
// Check if user provided public key data
const hasModernPublicKey = didInput.publicKeyMultibase;
const hasLegacyPublicKey = didInput.publicKeyBase58;
const userProvidedKeys = hasModernPublicKey || hasLegacyPublicKey;

// Validate that type is provided when keys are provided
if (userProvidedKeys && !didInput.type) {
throw new Error('Key pair type must be provided when supplying existing keys');
}

// Only generate if user didn't provide complete key pair
const generatedKeyPair = userProvidedKeys ? { ...didInput } : await generateKeyPair(didInput);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check type definitions and usage of generatedKeyPair

echo "=== Finding IssuedDIDOption type ==="
ast-grep --pattern 'type IssuedDIDOption = {
  $$$
}'

ast-grep --pattern 'interface IssuedDIDOption {
  $$$
}'

echo -e "\n=== Finding GeneratedKeyPair type ==="
ast-grep --pattern 'type GeneratedKeyPair = {
  $$$
}'

ast-grep --pattern 'interface GeneratedKeyPair {
  $$$
}'

echo -e "\n=== Finding all property accesses on generatedKeyPair ==="
rg -n 'generatedKeyPair\.' packages/w3c-issuer/src/did-web/wellKnown/index.ts | head -20

Repository: TrustVC/w3c

Length of output: 445


🏁 Script executed:

#!/bin/bash
# Search for type definitions in related files

echo "=== Searching for IssuedDIDOption definition ==="
rg -n "IssuedDIDOption" packages/w3c-issuer/src/did-web/wellKnown/ | head -10

echo -e "\n=== Searching for GeneratedKeyPair definition ==="
rg -n "GeneratedKeyPair" packages/w3c-issuer/src/did-web/wellKnown/ | head -10

echo -e "\n=== Full context of line 44 and surrounding code ==="
sed -n '40,75p' packages/w3c-issuer/src/did-web/wellKnown/index.ts

echo -e "\n=== Check imports at top of file ==="
head -30 packages/w3c-issuer/src/did-web/wellKnown/index.ts

Repository: TrustVC/w3c

Length of output: 3715


🏁 Script executed:

#!/bin/bash
echo "=== Full types.ts file ==="
cat -n packages/w3c-issuer/src/did-web/wellKnown/types.ts

echo -e "\n=== Search for generateKeyPair function and its return type ==="
rg -n "generateKeyPair" packages/w3c-issuer/src/did-web/keyPair/ -A 10 | head -50

Repository: TrustVC/w3c

Length of output: 8302


🏁 Script executed:

#!/bin/bash
echo "=== Search for GeneratedKeyPair type definition ==="
rg -n "type GeneratedKeyPair" packages/w3c-issuer/src/

echo -e "\n=== Search for GenerateKeyPairOptions ==="
rg -n "type GenerateKeyPairOptions" packages/w3c-issuer/src/

echo -e "\n=== Full keyPair/index.ts to see function and types ==="
head -80 packages/w3c-issuer/src/did-web/keyPair/index.ts

Repository: TrustVC/w3c

Length of output: 3574


🏁 Script executed:

#!/bin/bash
echo "=== Checking lib/types.ts for type definitions ==="
rg -n "type BaseKeyPair|type GeneratedKeyPair|type GenerateKeyPairOptions|type DidWebGeneratedKeyPair|type DidWebGenerateKeyPairOptions" packages/w3c-issuer/src/lib/types.ts -A 5

Repository: TrustVC/w3c

Length of output: 387


🏁 Script executed:

#!/bin/bash
echo "=== Checking for DidWebGenerateKeyPairOptions and DidWebGeneratedKeyPair ==="
rg -n "type DidWebGenerateKeyPairOptions|type DidWebGeneratedKeyPair|interface DidWebGenerateKeyPairOptions|interface DidWebGeneratedKeyPair" packages/w3c-issuer/src/ -A 15

Repository: TrustVC/w3c

Length of output: 1775


🏁 Script executed:

#!/bin/bash
echo "=== Check what happens with keyPairs after creation ==="
sed -n '44,85p' packages/w3c-issuer/src/did-web/wellKnown/index.ts

echo -e "\n=== Check how generateWellKnownDid uses the newKeyPair ==="
rg -n "generateWellKnownDid" packages/w3c-issuer/src/did-web/wellKnown/generate.ts -A 30 | head -50

Repository: TrustVC/w3c

Length of output: 2525


🏁 Script executed:

#!/bin/bash
echo "=== Full generateKeyPair function to see validation logic ==="
sed -n '49,130p' packages/w3c-issuer/src/did-web/keyPair/index.ts

Repository: TrustVC/w3c

Length of output: 2023


Add validation for user-provided keys to match generateKeyPair behavior.

When userProvidedKeys is true, the code bypasses generateKeyPair entirely, skipping critical validations: type validation, seed parsing, and key matching. Users could provide invalid or malformed keys (invalid base58/multibase, mismatched key pairs, unsupported types) that would be inserted into the DID document without any checks. The optional chaining on key properties prevents crashes but doesn't prevent malformed data from being stored.

Consider adding validation to user-provided keys that mirrors the checks in generateKeyPair, particularly seed parsing for BLS/BBS-2023 types and key matching when both seed and key material are provided.

🤖 Prompt for AI Agents
In packages/w3c-issuer/src/did-web/wellKnown/index.ts around line 44, when
userProvidedKeys is true the code skips generateKeyPair and thus skips important
validations (key type checks, seed parsing for BLS/BBS-2023, base58/multibase
format checks, and ensuring provided seed matches provided public/private key
material). Mirror the generateKeyPair validation path for user-provided keys:
validate the key type is supported, parse/validate seed for BLS/BBS-2023
formats, verify public/private keys are valid multibase/base58 and that if both
seed and key material are provided they correspond (derive and compare), and
throw or return a clear error on any mismatch or malformed input so malformed
keys are rejected before being inserted into the DID document.


let keyPairs: PrivateKeyPair;

Expand Down