forked from bluesky-social/atproto
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lexicon-level identifier validation helpers and test cases (bluesky-s…
…ocial#576) * hardening: permissive tests for handles * identifers: permissive tests for NSIDs * identifiers: add DID validation * identifiers: wrong about domain syntax (duh, 4chan.com) In short, labels can start with digits except for the final TLD part. I think that is all for "DNS domains as hostnames which are actually used in the real world", though there might be other modern things. Underscores are obviously allowed in DNS for things like SRV records, but I don't think as "regular hostnames". Not sure we want this for NSIDs, so not updating that code or tests yet. * identifiers: ATURI test corner cases * identifiers: remove TODOs (moved to formalism doc) * identifiers: small comment typos and corrections * move around & integrate indentifier hardneing * fixed up some tests --------- Co-authored-by: dholms <[email protected]>
- Loading branch information
Showing
36 changed files
with
992 additions
and
320 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Human-readable constraints: | ||
// - valid W3C DID (https://www.w3.org/TR/did-core/#did-syntax) | ||
// - entire URI is ASCII: [a-zA-Z0-9._:%-] | ||
// - always starts "did:" (lower-case) | ||
// - method name is one or more lower-case letters, followed by ":" | ||
// - remaining identifier can have any of the above chars, but can not end in ":" | ||
// - it seems that a bunch of ":" can be included, and don't need spaces between | ||
// - "%" is used only for "percent encoding" and must be followed by two hex characters (and thus can't end in "%") | ||
// - query ("?") and fragment ("#") stuff is defined for "DID URIs", but not as part of identifier itself | ||
// - "The current specification does not take a position on the maximum length of a DID" | ||
// - in current atproto, only allowing did:plc and did:web. But not *forcing* this at lexico layer | ||
// - hard length limit of 8KBytes | ||
// - not going to validate "percent encoding" here | ||
export const ensureValidDid = (did: string): void => { | ||
// check that all chars are boring ASCII | ||
if (!/^[a-zA-Z0-9._:%-]*$/.test(did)) { | ||
throw new Error( | ||
'Disallowed characters in DID (ASCII letters, digits, and a couple other characters only)', | ||
) | ||
} | ||
|
||
const parts = did.split(':') | ||
if (parts.length < 3) { | ||
throw new Error('DID requires prefix, method, and method-specific content') | ||
} | ||
|
||
if (parts[0] != 'did') { | ||
throw new Error('DID requires "did:" prefix') | ||
} | ||
|
||
if (!/^[a-z]+$/.test(parts[1])) { | ||
throw new Error('DID method must be lower-case letters') | ||
} | ||
|
||
if (did.endsWith(':') || did.endsWith('%')) { | ||
throw new Error('DID can not end with ":" or "%"') | ||
} | ||
|
||
if (did.length > 8 * 1024) { | ||
throw new Error('DID is far too long') | ||
} | ||
} | ||
|
||
export const ensureValidDidRegex = (did: string): void => { | ||
// simple regex to enforce most constraints via just regex and length. | ||
// hand wrote this regex based on above constraints | ||
if (!/^did:[a-z]+:[a-zA-Z0-9._:%-]*[a-zA-Z0-9._-]$/.test(did)) { | ||
throw new Error("DID didn't validate via regex") | ||
} | ||
|
||
if (did.length > 8 * 1024) { | ||
throw new Error('DID is far too long') | ||
} | ||
} |
Oops, something went wrong.