@@ -44,57 +44,47 @@ export async function getGiteaRepoUrls(adminUsername, adminPassword, orgName, do
4444 }
4545}
4646
47- const ALLOWED_REPO_HOSTS = [ 'github.com' , 'gitlab.com' ]
48-
49- const SAFE_REPO_PATH_REGEX = / ^ [ A - Z a - z 0 - 9 _ . - ] + \/ [ A - Z a - z 0 - 9 _ . - ] + $ /
47+ const SAFE_HOST_REGEX = / ^ [ A - Z a - z 0 - 9 . - ] + \. [ A - Z a - z ] { 2 , } $ /
48+ const SAFE_REPO_PATH_REGEX = / ^ [ A - Z a - z 0 - 9 _ . - ] + (?: \/ [ A - Z a - z 0 - 9 _ . - ] + ) + $ /
5049
5150export function normalizeRepoUrl ( inputUrl : string , isPrivate : boolean , isSSH : boolean ) : string | null {
5251 try {
5352 const cleanUrl = inputUrl . trim ( ) . replace ( / \/ $ / , '' )
5453
5554 let hostname : string
56- let owner : string
57- let repoName : string
55+ let repoPath : string
5856
5957 if ( cleanUrl . startsWith ( 'git@' ) ) {
6058 const match = cleanUrl
6159 . replace ( / \. g i t $ / , '' )
62- . match ( / ^ g i t @ ( g i t h u b \. c o m | g i t l a b \. c o m ) : ( [ A - Z a - z 0 - 9 _ . - ] + ) \/ ( [ A - Z a - z 0 - 9 _ . - ] + ) $ / )
60+ . match ( / ^ g i t @ ( [ A - Z a - z 0 - 9 . - ] + \. [ A - Z a - z ] { 2 , } ) : ( [ A - Z a - z 0 - 9 _ . - ] + (?: \/ [ A - Z a - z 0 - 9 _ . - ] + ) + ) $ / )
6361
6462 if ( ! match ) return null
6563
6664 hostname = match [ 1 ]
67- owner = match [ 2 ]
68- repoName = match [ 3 ]
65+ repoPath = match [ 2 ]
6966 } else {
7067 const urlToParse = / ^ [ a - z ] [ a - z 0 - 9 + . - ] * : / i. test ( cleanUrl ) ? cleanUrl : `https://${ cleanUrl } `
7168
7269 const parsed = new URL ( urlToParse )
7370
7471 if ( parsed . protocol !== 'https:' ) return null
72+ if ( ! SAFE_HOST_REGEX . test ( parsed . hostname ) ) return null
7573
76- hostname = parsed . hostname
77- if ( ! ALLOWED_REPO_HOSTS . includes ( hostname ) ) return null
74+ repoPath = parsed . pathname . replace ( / \. g i t $ / , '' ) . replace ( / ^ \/ | \/ $ / g, '' )
7875
79- const parts = parsed . pathname
80- . replace ( / \. g i t $ / , '' )
81- . split ( '/' )
82- . filter ( Boolean )
83- if ( parts . length !== 2 ) return null
76+ if ( ! SAFE_REPO_PATH_REGEX . test ( repoPath ) ) return null
8477
85- owner = parts [ 0 ]
86- repoName = parts [ 1 ]
87-
88- if ( ! SAFE_REPO_PATH_REGEX . test ( `${ owner } /${ repoName } ` ) ) return null
78+ hostname = parsed . hostname
8979 }
9080
91- const repoWithGitSuffix = `${ repoName } .git`
81+ const repoWithGitSuffix = `${ repoPath } .git`
9282
9383 if ( isPrivate && isSSH ) {
94- return `git@${ hostname } :${ owner } / ${ repoWithGitSuffix } `
84+ return `git@${ hostname } :${ repoWithGitSuffix } `
9585 }
9686
97- return `https://${ hostname } /${ owner } / ${ repoWithGitSuffix } `
87+ return `https://${ hostname } /${ repoWithGitSuffix } `
9888 } catch {
9989 return null
10090 }
0 commit comments