security: address remaining code scanning alerts (#253)

This commit is contained in:
Vasanth T
2026-04-03 20:16:53 +05:30
committed by GitHub
parent c1e5e363cd
commit 931ee96f5a
10 changed files with 87 additions and 36 deletions

View File

@@ -282,17 +282,16 @@ function InstallGitHubApp(props: {
return;
}
const repoWarnings: Warning[] = [];
if (repoName_1.includes('github.com')) {
const slug = extractGitHubRepoSlug(repoName_1);
if (!slug) {
repoWarnings.push({
title: 'Invalid GitHub URL format',
message: 'The repository URL format appears to be invalid.',
instructions: ['Use format: owner/repo or https://github.com/owner/repo', 'Example: anthropics/claude-cli']
});
} else {
repoName_1 = slug;
}
const slug = extractGitHubRepoSlug(repoName_1);
const isUrlLike = /^[a-z][a-z0-9+.-]*:\/\//i.test(repoName_1) || repoName_1.startsWith('www.');
if (slug) {
repoName_1 = slug;
} else if (isUrlLike) {
repoWarnings.push({
title: 'Invalid GitHub URL format',
message: 'The repository URL format appears to be invalid.',
instructions: ['Use format: owner/repo or https://github.com/owner/repo', 'Example: anthropics/claude-cli']
});
}
if (!repoName_1.includes('/')) {
repoWarnings.push({

View File

@@ -33,4 +33,16 @@ test('rejects malformed or non-GitHub URLs', () => {
assert.equal(extractGitHubRepoSlug('https://gitlab.com/Gitlawb/openclaude'), null)
assert.equal(extractGitHubRepoSlug('https://github.com/Gitlawb'), null)
assert.equal(extractGitHubRepoSlug('not actually github.com/Gitlawb/openclaude'), null)
assert.equal(
extractGitHubRepoSlug('https://evil.example/?next=github.com/Gitlawb/openclaude'),
null,
)
assert.equal(
extractGitHubRepoSlug('https://github.com.evil.example/Gitlawb/openclaude'),
null,
)
assert.equal(
extractGitHubRepoSlug('https://example.com/github.com/Gitlawb/openclaude'),
null,
)
})

View File

@@ -1,12 +1,24 @@
export function extractGitHubRepoSlug(value: string): string | null {
const trimmed = value.trim()
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed) && !trimmed.includes('github.com')) {
return null
const slugMatch = trimmed.match(
/^(?<owner>[^/:\s]+)\/(?<repo>[^/\s]+?)(?:\.git)?\/?$/i,
)
if (slugMatch?.groups?.owner && slugMatch.groups.repo) {
return `${slugMatch.groups.owner}/${slugMatch.groups.repo}`.replace(
/\.git$/i,
'',
)
}
if (!trimmed.includes('github.com')) {
return trimmed
const shorthandUrlMatch = trimmed.match(
/^(?:https?:\/\/)?(?:www\.)?github\.com\/(?<owner>[^/:\s]+)\/(?<repo>[^/\s]+?)(?:\.git)?\/?$/i,
)
if (shorthandUrlMatch?.groups?.owner && shorthandUrlMatch.groups.repo) {
return `${shorthandUrlMatch.groups.owner}/${shorthandUrlMatch.groups.repo}`.replace(
/\.git$/i,
'',
)
}
const sshMatch = trimmed.match(
@@ -16,6 +28,10 @@ export function extractGitHubRepoSlug(value: string): string | null {
return `${sshMatch.groups.owner}/${sshMatch.groups.repo}`
}
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed)) {
return null
}
try {
const parsed = new URL(trimmed)
const hostname = parsed.hostname.toLowerCase()