Add proper URI component encoding + hostname check

This commit is contained in:
x032205
2025-07-25 16:55:21 -04:00
parent 52ef0e6b81
commit 0b7b32bdc3
3 changed files with 18 additions and 13 deletions
@@ -14,6 +14,11 @@ export const blockLocalAndPrivateIpAddresses = async (url: string) => {
if (appCfg.isDevelopmentMode) return; if (appCfg.isDevelopmentMode) return;
const validUrl = new URL(url); const validUrl = new URL(url);
if (validUrl.username || validUrl.password) {
throw new BadRequestError({ message: "URLs with user credentials (e.g., user:pass@) are not allowed" });
}
const inputHostIps: string[] = []; const inputHostIps: string[] = [];
if (isIPv4(validUrl.hostname)) { if (isIPv4(validUrl.hostname)) {
inputHostIps.push(validUrl.hostname); inputHostIps.push(validUrl.hostname);
@@ -241,7 +241,7 @@ export const getGitHubEnvironments = async (
return await makePaginatedGitHubRequest<GitHubEnvironment, { environments: GitHubEnvironment[] }>( return await makePaginatedGitHubRequest<GitHubEnvironment, { environments: GitHubEnvironment[] }>(
appConnection, appConnection,
gatewayService, gatewayService,
`/repos/${owner}/${repo}/environments`, `/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/environments`,
(data) => data.environments (data) => data.environments
); );
} catch (error) { } catch (error) {
@@ -26,16 +26,16 @@ const getEncryptedSecrets = async (
let path: string; let path: string;
switch (destinationConfig.scope) { switch (destinationConfig.scope) {
case GitHubSyncScope.Organization: { case GitHubSyncScope.Organization: {
path = `/orgs/${destinationConfig.org}/actions/secrets`; path = `/orgs/${encodeURIComponent(destinationConfig.org)}/actions/secrets`;
break; break;
} }
case GitHubSyncScope.Repository: { case GitHubSyncScope.Repository: {
path = `/repos/${destinationConfig.owner}/${destinationConfig.repo}/actions/secrets`; path = `/repos/${encodeURIComponent(destinationConfig.owner)}/${encodeURIComponent(destinationConfig.repo)}/actions/secrets`;
break; break;
} }
case GitHubSyncScope.RepositoryEnvironment: case GitHubSyncScope.RepositoryEnvironment:
default: { default: {
path = `/repos/${destinationConfig.owner}/${destinationConfig.repo}/environments/${destinationConfig.env}/secrets`; path = `/repos/${encodeURIComponent(destinationConfig.owner)}/${encodeURIComponent(destinationConfig.repo)}/environments/${encodeURIComponent(destinationConfig.env)}/secrets`;
break; break;
} }
} }
@@ -58,16 +58,16 @@ const getPublicKey = async (
let path: string; let path: string;
switch (destinationConfig.scope) { switch (destinationConfig.scope) {
case GitHubSyncScope.Organization: { case GitHubSyncScope.Organization: {
path = `/orgs/${destinationConfig.org}/actions/secrets/public-key`; path = `/orgs/${encodeURIComponent(destinationConfig.org)}/actions/secrets/public-key`;
break; break;
} }
case GitHubSyncScope.Repository: { case GitHubSyncScope.Repository: {
path = `/repos/${destinationConfig.owner}/${destinationConfig.repo}/actions/secrets/public-key`; path = `/repos/${encodeURIComponent(destinationConfig.owner)}/${encodeURIComponent(destinationConfig.repo)}/actions/secrets/public-key`;
break; break;
} }
case GitHubSyncScope.RepositoryEnvironment: case GitHubSyncScope.RepositoryEnvironment:
default: { default: {
path = `/repos/${destinationConfig.owner}/${destinationConfig.repo}/environments/${destinationConfig.env}/secrets/public-key`; path = `/repos/${encodeURIComponent(destinationConfig.owner)}/${encodeURIComponent(destinationConfig.repo)}/environments/${encodeURIComponent(destinationConfig.env)}/secrets/public-key`;
break; break;
} }
} }
@@ -96,16 +96,16 @@ const deleteSecret = async (
let path: string; let path: string;
switch (destinationConfig.scope) { switch (destinationConfig.scope) {
case GitHubSyncScope.Organization: { case GitHubSyncScope.Organization: {
path = `/orgs/${destinationConfig.org}/actions/secrets/${encryptedSecret.name}`; path = `/orgs/${encodeURIComponent(destinationConfig.org)}/actions/secrets/${encodeURIComponent(encryptedSecret.name)}`;
break; break;
} }
case GitHubSyncScope.Repository: { case GitHubSyncScope.Repository: {
path = `/repos/${destinationConfig.owner}/${destinationConfig.repo}/actions/secrets/${encryptedSecret.name}`; path = `/repos/${encodeURIComponent(destinationConfig.owner)}/${encodeURIComponent(destinationConfig.repo)}/actions/secrets/${encodeURIComponent(encryptedSecret.name)}`;
break; break;
} }
case GitHubSyncScope.RepositoryEnvironment: case GitHubSyncScope.RepositoryEnvironment:
default: { default: {
path = `/repos/${destinationConfig.owner}/${destinationConfig.repo}/environments/${destinationConfig.env}/secrets/${encryptedSecret.name}`; path = `/repos/${encodeURIComponent(destinationConfig.owner)}/${encodeURIComponent(destinationConfig.repo)}/environments/${encodeURIComponent(destinationConfig.env)}/secrets/${encodeURIComponent(encryptedSecret.name)}`;
break; break;
} }
} }
@@ -135,7 +135,7 @@ const putSecret = async (
switch (destinationConfig.scope) { switch (destinationConfig.scope) {
case GitHubSyncScope.Organization: { case GitHubSyncScope.Organization: {
const { visibility, selectedRepositoryIds } = destinationConfig; const { visibility, selectedRepositoryIds } = destinationConfig;
path = `/orgs/${destinationConfig.org}/actions/secrets/${payload.secret_name}`; path = `/orgs/${encodeURIComponent(destinationConfig.org)}/actions/secrets/${encodeURIComponent(payload.secret_name)}`;
body = { body = {
...payload, ...payload,
visibility, visibility,
@@ -146,12 +146,12 @@ const putSecret = async (
break; break;
} }
case GitHubSyncScope.Repository: { case GitHubSyncScope.Repository: {
path = `/repos/${destinationConfig.owner}/${destinationConfig.repo}/actions/secrets/${payload.secret_name}`; path = `/repos/${encodeURIComponent(destinationConfig.owner)}/${encodeURIComponent(destinationConfig.repo)}/actions/secrets/${encodeURIComponent(payload.secret_name)}`;
break; break;
} }
case GitHubSyncScope.RepositoryEnvironment: case GitHubSyncScope.RepositoryEnvironment:
default: { default: {
path = `/repos/${destinationConfig.owner}/${destinationConfig.repo}/environments/${destinationConfig.env}/secrets/${payload.secret_name}`; path = `/repos/${encodeURIComponent(destinationConfig.owner)}/${encodeURIComponent(destinationConfig.repo)}/environments/${encodeURIComponent(destinationConfig.env)}/secrets/${encodeURIComponent(payload.secret_name)}`;
break; break;
} }
} }