@@ -4,36 +4,90 @@ import * as path from "path";
44
55import test from "ava" ;
66
7- import { scanArtifactsForTokens } from "./artifact-scanner" ;
7+ import { scanArtifactsForTokens , TokenType } from "./artifact-scanner" ;
88import { getRunnerLogger } from "./logging" ;
9- import { getRecordingLogger , LoggedMessage } from "./testing-utils" ;
9+ import {
10+ checkExpectedLogMessages ,
11+ getRecordingLogger ,
12+ LoggedMessage ,
13+ } from "./testing-utils" ;
1014
11- test ( "scanArtifactsForTokens detects GitHub tokens in files" , async ( t ) => {
12- const logger = getRunnerLogger ( true ) ;
13- const tempDir = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , "scanner-test-" ) ) ;
15+ function makeTestToken ( length : number = 36 ) {
16+ const chars =
17+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" ;
18+ return chars . repeat ( Math . ceil ( length / chars . length ) ) . slice ( 0 , length ) ;
19+ }
1420
15- try {
16- // Create a test file with a fake GitHub token
17- const testFile = path . join ( tempDir , "test.txt" ) ;
18- fs . writeFileSync (
19- testFile ,
20- "This is a test file with token ghp_1234567890123456789012345678901234AB" ,
21- ) ;
21+ test ( "makeTestToken" , ( t ) => {
22+ t . is ( makeTestToken ( ) . length , 36 ) ;
23+ t . is ( makeTestToken ( 255 ) . length , 255 ) ;
24+ } ) ;
2225
23- const error = await t . throwsAsync (
24- async ( ) => await scanArtifactsForTokens ( [ testFile ] , logger ) ,
25- ) ;
26+ const testTokens = [
27+ {
28+ type : TokenType . PersonalAccessClassic ,
29+ value : `ghp_${ makeTestToken ( ) } ` ,
30+ checkPattern : "Personal Access Token" ,
31+ } ,
32+ {
33+ type : TokenType . PersonalAccessFineGrained ,
34+ value :
35+ "github_pat_1234567890ABCDEFGHIJKL_MNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHI" ,
36+ checkPattern : "Personal Access Token" ,
37+ } ,
38+ {
39+ type : TokenType . OAuth ,
40+ value : `gho_${ makeTestToken ( ) } ` ,
41+ } ,
42+ {
43+ type : TokenType . UserToServer ,
44+ value : `ghu_${ makeTestToken ( ) } ` ,
45+ } ,
46+ {
47+ type : TokenType . ServerToServer ,
48+ value : `ghs_${ makeTestToken ( ) } ` ,
49+ } ,
50+ {
51+ type : TokenType . Refresh ,
52+ value : `ghr_${ makeTestToken ( ) } ` ,
53+ } ,
54+ {
55+ type : TokenType . AppInstallationAccess ,
56+ value : `ghs_${ makeTestToken ( 255 ) } ` ,
57+ } ,
58+ ] ;
2659
27- t . regex (
28- error ?. message || "" ,
29- / F o u n d 1 p o t e n t i a l G i t H u b t o k e n .* P e r s o n a l A c c e s s T o k e n / ,
30- ) ;
31- t . regex ( error ?. message || "" , / t e s t \. t x t / ) ;
32- } finally {
33- // Clean up
34- fs . rmSync ( tempDir , { recursive : true , force : true } ) ;
35- }
36- } ) ;
60+ for ( const { type, value, checkPattern } of testTokens ) {
61+ test ( `scanArtifactsForTokens detects GitHub ${ type } tokens in files` , async ( t ) => {
62+ const logMessages = [ ] ;
63+ const logger = getRecordingLogger ( logMessages , { logToConsole : false } ) ;
64+ const tempDir = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , "scanner-test-" ) ) ;
65+
66+ try {
67+ // Create a test file with a fake GitHub token
68+ const testFile = path . join ( tempDir , "test.txt" ) ;
69+ fs . writeFileSync ( testFile , `This is a test file with token ${ value } ` ) ;
70+
71+ const error = await t . throwsAsync (
72+ async ( ) => await scanArtifactsForTokens ( [ testFile ] , logger ) ,
73+ ) ;
74+
75+ t . regex (
76+ error ?. message || "" ,
77+ new RegExp ( `Found 1 potential GitHub token.*${ checkPattern || type } ` ) ,
78+ ) ;
79+ t . regex ( error ?. message || "" , / t e s t \. t x t / ) ;
80+
81+ checkExpectedLogMessages ( t , logMessages , [
82+ "Starting best-effort check" ,
83+ `Found 1 ${ type } ` ,
84+ ] ) ;
85+ } finally {
86+ // Clean up
87+ fs . rmSync ( tempDir , { recursive : true , force : true } ) ;
88+ }
89+ } ) ;
90+ }
3791
3892test ( "scanArtifactsForTokens handles files without tokens" , async ( t ) => {
3993 const logger = getRunnerLogger ( true ) ;
0 commit comments