diff --git a/lib/auth.js b/lib/auth.js index 2569b04..761d01c 100644 --- a/lib/auth.js +++ b/lib/auth.js @@ -1,4 +1,3 @@ -import assert from 'node:assert'; import fs from 'node:fs'; import { ClientRequest } from 'node:http'; import util from 'node:util'; @@ -11,9 +10,27 @@ const ghauth = util.promisify(ghauthBase); export default lazy(auth); +function errorExit(message) { + process.stderr.write(`${message}\n`); + process.exit(1); +} + function check(username, token) { - assert(typeof username === 'string' && /^[a-zA-Z0-9]*/.test(username)); - assert(typeof token === 'string' && /^[0-9a-f]*/.test(token)); + if (typeof username !== 'string') { + errorExit(`username must be a string, received ${typeof username}`); + } + if (!/^[a-zA-Z0-9-]+$/.test(username)) { + errorExit( + 'username may only contain alphanumeric characters or hyphens, ' + + `received ${username}` + ); + } + if (typeof token !== 'string') { + errorExit(`token must be a string, received ${typeof token}`); + } + if (!/^[0-9a-f]+$/.test(token)) { + errorExit(`token must be lowercase hexadecimal, received ${token}`); + } } function lazy(fn) { @@ -36,8 +53,7 @@ async function tryCreateGitHubToken(githubAuth) { note: 'node-core-utils CLI tools' }); } catch (e) { - process.stderr.write(`Could not get token: ${e.message}\n`); - process.exit(1); + errorExit(`Could not get token: ${e.message}`); } return credentials; } @@ -84,11 +100,11 @@ async function auth( if (options.jenkins) { const { username, jenkins_token } = getMergedConfig(); if (!username || !jenkins_token) { - process.stdout.write( + errorExit( 'Get your Jenkins API token in https://ci.nodejs.org/me/configure ' + 'and run the following command to add it to your ncu config: ' + - 'ncu-config --global set jenkins_token TOKEN\n'); - process.exit(1); + 'ncu-config --global set jenkins_token TOKEN' + ); }; check(username, jenkins_token); result.jenkins = encode(username, jenkins_token); diff --git a/test/unit/auth.test.js b/test/unit/auth.test.js index ea68aea..589de00 100644 --- a/test/unit/auth.test.js +++ b/test/unit/auth.test.js @@ -70,6 +70,43 @@ describe('auth', async function() { 'Could not get token: Bad credentials\n', 'run-auth-error' ); }); + + it('does not accept a non-string username', async function() { + this.timeout(2000); + await runAuthScript( + { HOME: { username: {}, token: '0123456789abcdef' } }, + [], + 'username must be a string, received object\n' + ); + }); + + it('does not accept a non-string token', async function() { + this.timeout(2000); + await runAuthScript( + { HOME: { username: 'nyancat', token: 42 } }, + [], + 'token must be a string, received number\n' + ); + }); + + it('does not accept an invalid username format', async function() { + this.timeout(2000); + await runAuthScript( + { HOME: { username: ' ^^^ ', token: '0123456789abcdef' } }, + [], + 'username may only contain alphanumeric characters or hyphens, ' + + 'received ^^^ \n' + ); + }); + + it('does not accept an invalid token format', async function() { + this.timeout(2000); + await runAuthScript( + { HOME: { username: 'nyancat', token: '0123456789ABCDEF' } }, + [], + 'token must be lowercase hexadecimal, received 0123456789ABCDEF\n' + ); + }); }); // ncurc: { HOME: 'text to put in home ncurc',