diff --git a/.changeset/happy-beers-notice.md b/.changeset/happy-beers-notice.md new file mode 100644 index 00000000000..5fcd52b41e9 --- /dev/null +++ b/.changeset/happy-beers-notice.md @@ -0,0 +1,5 @@ +--- +"@atproto/pds": patch +--- + +Improve email validation logic diff --git a/.changeset/soft-tigers-taste.md b/.changeset/soft-tigers-taste.md new file mode 100644 index 00000000000..e63338fd23b --- /dev/null +++ b/.changeset/soft-tigers-taste.md @@ -0,0 +1,5 @@ +--- +"@atproto/pds": patch +--- + +Update list of forbidden domain names in email addresses diff --git a/packages/pds/package.json b/packages/pds/package.json index bdbb4944e42..6389c219722 100644 --- a/packages/pds/package.json +++ b/packages/pds/package.json @@ -43,11 +43,12 @@ "@atproto/xrpc": "workspace:^", "@atproto/xrpc-server": "workspace:^", "@did-plc/lib": "^0.0.4", + "@hapi/address": "^5.1.1", "better-sqlite3": "^10.0.0", "bytes": "^3.1.2", "compression": "^1.7.4", "cors": "^2.8.5", - "disposable-email": "^0.2.3", + "disposable-email-domains-js": "^1.5.0", "express": "^4.17.2", "express-async-errors": "^3.1.1", "file-type": "^16.5.4", @@ -78,7 +79,6 @@ "@atproto/pds-entryway": "npm:@atproto/pds@0.3.0-entryway.3", "@did-plc/server": "^0.0.1", "@types/cors": "^2.8.12", - "@types/disposable-email": "^0.2.0", "@types/express": "^4.17.13", "@types/express-serve-static-core": "^4.17.36", "@types/nodemailer": "^6.4.6", diff --git a/packages/pds/src/api/com/atproto/server/createAccount.ts b/packages/pds/src/api/com/atproto/server/createAccount.ts index 4d6fd499852..f82f72343c7 100644 --- a/packages/pds/src/api/com/atproto/server/createAccount.ts +++ b/packages/pds/src/api/com/atproto/server/createAccount.ts @@ -3,7 +3,9 @@ import { AtprotoData, ensureAtpDocument } from '@atproto/identity' import { AuthRequiredError, InvalidRequestError } from '@atproto/xrpc-server' import { ExportableKeypair, Keypair, Secp256k1Keypair } from '@atproto/crypto' import * as plc from '@did-plc/lib' -import disposable from 'disposable-email' +import { isEmailValid } from '@hapi/address' +import { isDisposableEmail } from 'disposable-email-domains-js' + import { baseNormalizeAndValidate, normalizeAndValidateHandle, @@ -175,7 +177,7 @@ const validateInputsForLocalPds = async ( if (!email) { throw new InvalidRequestError('Email is required') - } else if (!disposable.validate(email)) { + } else if (!isEmailValid(email) || isDisposableEmail(email)) { throw new InvalidRequestError( 'This email address is not supported, please use a different email.', ) diff --git a/packages/pds/src/api/com/atproto/server/updateEmail.ts b/packages/pds/src/api/com/atproto/server/updateEmail.ts index f6bc781be3e..838089f17ac 100644 --- a/packages/pds/src/api/com/atproto/server/updateEmail.ts +++ b/packages/pds/src/api/com/atproto/server/updateEmail.ts @@ -1,7 +1,8 @@ import assert from 'node:assert' import { InvalidRequestError } from '@atproto/xrpc-server' -import disposable from 'disposable-email' +import { isEmailValid } from '@hapi/address' +import { isDisposableEmail } from 'disposable-email-domains-js' import { UserAlreadyExistsError } from '../../../../account-manager/helpers/account' import AppContext from '../../../../context' @@ -14,7 +15,7 @@ export default function (server: Server, ctx: AppContext) { handler: async ({ auth, input }) => { const did = auth.credentials.did const { token, email } = input.body - if (!disposable.validate(email)) { + if (!isEmailValid(email) || isDisposableEmail(email)) { throw new InvalidRequestError( 'This email address is not supported, please use a different email.', ) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 49eb3f9b7fe..424882fc84c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1262,6 +1262,9 @@ importers: '@did-plc/lib': specifier: ^0.0.4 version: 0.0.4 + '@hapi/address': + specifier: ^5.1.1 + version: 5.1.1 better-sqlite3: specifier: ^10.0.0 version: 10.0.0 @@ -1274,9 +1277,9 @@ importers: cors: specifier: ^2.8.5 version: 2.8.5 - disposable-email: - specifier: ^0.2.3 - version: 0.2.3 + disposable-email-domains-js: + specifier: ^1.5.0 + version: 1.5.0 express: specifier: ^4.17.2 version: 4.18.2 @@ -1359,9 +1362,6 @@ importers: '@types/cors': specifier: ^2.8.12 version: 2.8.12 - '@types/disposable-email': - specifier: ^0.2.0 - version: 0.2.0 '@types/express': specifier: ^4.17.13 version: 4.17.13 @@ -4966,6 +4966,13 @@ packages: '@hapi/hoek': 11.0.4 dev: false + /@hapi/address@5.1.1: + resolution: {integrity: sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA==} + engines: {node: '>=14.0.0'} + dependencies: + '@hapi/hoek': 11.0.4 + dev: false + /@hapi/boom@10.0.1: resolution: {integrity: sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==} dependencies: @@ -6237,10 +6244,6 @@ packages: resolution: {integrity: sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==} dev: true - /@types/disposable-email@0.2.0: - resolution: {integrity: sha512-i4fPC8+a5j7RlKVe9cOHz6cYVxkSFYuJ78GB3EJPMfBJURWmEsD4gb/gD48j7KAWe0M8ZvdJR6a6GaDohTYttw==} - dev: true - /@types/elliptic@6.4.14: resolution: {integrity: sha512-z4OBcDAU0GVwDTuwJzQCiL6188QvZMkvoERgcVjq0/mPM8jCfdwZ3x5zQEVoL9WCAru3aG5wl3Z5Ww5wBWn7ZQ==} dependencies: @@ -8032,8 +8035,13 @@ packages: path-type: 4.0.0 dev: true + /disposable-email-domains-js@1.5.0: + resolution: {integrity: sha512-L1cn+cZhKmxUwixH8n+n0HG+WbCz+LF4coyT6yMh930tpkD90ZWFx3A9dHIdFMVM745saaeNGYScIEstm3Y3yg==} + dev: false + /disposable-email@0.2.3: resolution: {integrity: sha512-gkBQQ5Res431ZXqLlAafrXHizG7/1FWmi8U2RTtriD78Vc10HhBUvdJun3R4eSF0KRIQQJs+wHlxjkED/Hr1EQ==} + dev: true /dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}