diff --git a/src/artifact-scanner.test.ts b/src/artifact-scanner.test.ts index 5678d2cad..55b07d7d3 100644 --- a/src/artifact-scanner.test.ts +++ b/src/artifact-scanner.test.ts @@ -4,37 +4,91 @@ import * as path from "path"; import test from "ava"; -import { scanArtifactsForTokens } from "./artifact-scanner"; +import { scanArtifactsForTokens, TokenType } from "./artifact-scanner"; import { getRunnerLogger } from "./logging"; -import { getRecordingLogger, LoggedMessage } from "./testing-utils"; +import { + checkExpectedLogMessages, + getRecordingLogger, + LoggedMessage, +} from "./testing-utils"; -test("scanArtifactsForTokens detects GitHub tokens in files", async (t) => { - const logger = getRunnerLogger(true); - const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "scanner-test-")); +function makeTestToken(length: number = 36) { + const chars = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + return chars.repeat(Math.ceil(length / chars.length)).slice(0, length); +} - try { - // Create a test file with a fake GitHub token - const testFile = path.join(tempDir, "test.txt"); - fs.writeFileSync( - testFile, - "This is a test file with token ghp_1234567890123456789012345678901234AB", - ); - - const error = await t.throwsAsync( - async () => await scanArtifactsForTokens([testFile], logger), - ); - - t.regex( - error?.message || "", - /Found 1 potential GitHub token.*Personal Access Token/, - ); - t.regex(error?.message || "", /test\.txt/); - } finally { - // Clean up - fs.rmSync(tempDir, { recursive: true, force: true }); - } +test("makeTestToken", (t) => { + t.is(makeTestToken().length, 36); + t.is(makeTestToken(255).length, 255); }); +const testTokens = [ + { + type: TokenType.PersonalAccessClassic, + value: `ghp_${makeTestToken()}`, + checkPattern: "Personal Access Token", + }, + { + type: TokenType.PersonalAccessFineGrained, + value: + "github_pat_1234567890ABCDEFGHIJKL_MNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHI", + checkPattern: "Personal Access Token", + }, + { + type: TokenType.OAuth, + value: `gho_${makeTestToken()}`, + }, + { + type: TokenType.UserToServer, + value: `ghu_${makeTestToken()}`, + }, + { + type: TokenType.ServerToServer, + value: `ghs_${makeTestToken()}`, + }, + { + type: TokenType.Refresh, + value: `ghr_${makeTestToken()}`, + }, + { + type: TokenType.AppInstallationAccess, + value: `ghs_${makeTestToken(255)}`, + }, +]; + +for (const { type, value, checkPattern } of testTokens) { + test(`scanArtifactsForTokens detects GitHub ${type} tokens in files`, async (t) => { + const logMessages = []; + const logger = getRecordingLogger(logMessages, { logToConsole: false }); + const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "scanner-test-")); + + try { + // Create a test file with a fake GitHub token + const testFile = path.join(tempDir, "test.txt"); + fs.writeFileSync(testFile, `This is a test file with token ${value}`); + + const error = await t.throwsAsync( + async () => await scanArtifactsForTokens([testFile], logger), + ); + + t.regex( + error?.message || "", + new RegExp(`Found 1 potential GitHub token.*${checkPattern || type}`), + ); + t.regex(error?.message || "", /test\.txt/); + + checkExpectedLogMessages(t, logMessages, [ + "Starting best-effort check", + `Found 1 ${type}`, + ]); + } finally { + // Clean up + fs.rmSync(tempDir, { recursive: true, force: true }); + } + }); +} + test("scanArtifactsForTokens handles files without tokens", async (t) => { const logger = getRunnerLogger(true); const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "scanner-test-"));