diff --git a/backend/src/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-factory.ts b/backend/src/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-factory.ts index 598eda18b..fc42bd186 100644 --- a/backend/src/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-factory.ts +++ b/backend/src/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-factory.ts @@ -58,7 +58,7 @@ export const BitbucketSecretScanningFactory = () => { const authHeader = `Basic ${Buffer.from(`${email}:${apiToken}`).toString("base64")}`; const { data } = await request.post<{ uuid: string }>( - `${IntegrationUrls.BITBUCKET_API_URL}/2.0/workspaces/${payload.config.workspaceSlug}/hooks`, + `${IntegrationUrls.BITBUCKET_API_URL}/2.0/workspaces/${encodeURIComponent(payload.config.workspaceSlug)}/hooks`, { description: "Infisical webhook for push events", url: `${cfg.SITE_URL}/secret-scanning/webhooks/bitbucket`, @@ -92,7 +92,7 @@ export const BitbucketSecretScanningFactory = () => { const newWebhookUrl = `${cfg.SITE_URL}/secret-scanning/webhooks/bitbucket?dataSourceId=${dataSourceId}`; await request.put( - `${IntegrationUrls.BITBUCKET_API_URL}/2.0/workspaces/${payload.config.workspaceSlug}/hooks/${webhookId}`, + `${IntegrationUrls.BITBUCKET_API_URL}/2.0/workspaces/${encodeURIComponent(payload.config.workspaceSlug)}/hooks/${webhookId}`, { description: "Infisical webhook for push events", url: newWebhookUrl, diff --git a/backend/src/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-service.ts b/backend/src/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-service.ts index 4a29245ed..62825f397 100644 --- a/backend/src/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-service.ts +++ b/backend/src/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-service.ts @@ -5,7 +5,7 @@ import { logger } from "@app/lib/logger"; import { TBitbucketDataSource, TBitbucketPushEvent } from "./bitbucket-secret-scanning-types"; -export const bitBucketSecretScanningService = ( +export const bitbucketSecretScanningService = ( secretScanningV2DAL: TSecretScanningV2DALFactory, secretScanningV2Queue: Pick ) => { diff --git a/backend/src/ee/services/secret-scanning-v2/secret-scanning-v2-service.ts b/backend/src/ee/services/secret-scanning-v2/secret-scanning-v2-service.ts index fbba667b7..9d3d5dda6 100644 --- a/backend/src/ee/services/secret-scanning-v2/secret-scanning-v2-service.ts +++ b/backend/src/ee/services/secret-scanning-v2/secret-scanning-v2-service.ts @@ -51,7 +51,7 @@ import { TAppConnection } from "@app/services/app-connection/app-connection-type import { TKmsServiceFactory } from "@app/services/kms/kms-service"; import { KmsDataKey } from "@app/services/kms/kms-types"; -import { bitBucketSecretScanningService } from "./bitbucket/bitbucket-secret-scanning-service"; +import { bitbucketSecretScanningService } from "./bitbucket/bitbucket-secret-scanning-service"; import { TSecretScanningV2DALFactory } from "./secret-scanning-v2-dal"; import { TSecretScanningV2QueueServiceFactory } from "./secret-scanning-v2-queue"; @@ -901,6 +901,6 @@ export const secretScanningV2ServiceFactory = ({ findSecretScanningConfigByProjectId, upsertSecretScanningConfig, github: githubSecretScanningService(secretScanningV2DAL, secretScanningV2Queue), - bitbucket: bitBucketSecretScanningService(secretScanningV2DAL, secretScanningV2Queue) + bitbucket: bitbucketSecretScanningService(secretScanningV2DAL, secretScanningV2Queue) }; }; diff --git a/backend/src/server/plugins/secret-scanner-v2.ts b/backend/src/server/plugins/secret-scanner-v2.ts index 047a23373..b61754d7e 100644 --- a/backend/src/server/plugins/secret-scanner-v2.ts +++ b/backend/src/server/plugins/secret-scanner-v2.ts @@ -1,14 +1,14 @@ import type { EmitterWebhookEventName } from "@octokit/webhooks/dist-types/types"; import { PushEvent } from "@octokit/webhooks-types"; +import crypto from "crypto"; import { Probot } from "probot"; import { z } from "zod"; +import { generateBitbucketWebhookSecret } from "@app/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-factory"; import { TBitbucketPushEvent } from "@app/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-types"; import { getConfig } from "@app/lib/config/env"; import { logger } from "@app/lib/logger"; import { writeLimit } from "@app/server/config/rateLimiter"; -import crypto from "crypto"; -import { generateBitbucketWebhookSecret } from "@app/ee/services/secret-scanning-v2/bitbucket/bitbucket-secret-scanning-factory"; export const registerSecretScanningV2Webhooks = async (server: FastifyZodProvider) => { const probotApp = (app: Probot) => { diff --git a/backend/src/server/routes/v1/app-connection-routers/bitbucket-connection-router.ts b/backend/src/server/routes/v1/app-connection-routers/bitbucket-connection-router.ts index 253002e76..3f9ca9059 100644 --- a/backend/src/server/routes/v1/app-connection-routers/bitbucket-connection-router.ts +++ b/backend/src/server/routes/v1/app-connection-routers/bitbucket-connection-router.ts @@ -62,7 +62,7 @@ export const registerBitbucketConnectionRouter = async (server: FastifyZodProvid connectionId: z.string().uuid() }), querystring: z.object({ - workspaceSlug: z.string() + workspaceSlug: z.string().min(1).max(255) }), response: { 200: z.object({ diff --git a/backend/src/services/app-connection/app-connection-service.ts b/backend/src/services/app-connection/app-connection-service.ts index a1649a1c4..e964df25f 100644 --- a/backend/src/services/app-connection/app-connection-service.ts +++ b/backend/src/services/app-connection/app-connection-service.ts @@ -46,7 +46,7 @@ import { ValidateAzureDevOpsConnectionCredentialsSchema } from "./azure-devops/a import { azureDevOpsConnectionService } from "./azure-devops/azure-devops-service"; import { ValidateAzureKeyVaultConnectionCredentialsSchema } from "./azure-key-vault"; import { ValidateBitbucketConnectionCredentialsSchema } from "./bitbucket"; -import { bitBucketConnectionService } from "./bitbucket/bitbucket-connection-service"; +import { bitbucketConnectionService } from "./bitbucket/bitbucket-connection-service"; import { ValidateCamundaConnectionCredentialsSchema } from "./camunda"; import { camundaConnectionService } from "./camunda/camunda-connection-service"; import { ValidateCloudflareConnectionCredentialsSchema } from "./cloudflare/cloudflare-connection-schema"; @@ -536,7 +536,7 @@ export const appConnectionServiceFactory = ({ flyio: flyioConnectionService(connectAppConnectionById), gitlab: gitlabConnectionService(connectAppConnectionById, appConnectionDAL, kmsService), cloudflare: cloudflareConnectionService(connectAppConnectionById), - bitbucket: bitBucketConnectionService(connectAppConnectionById), + bitbucket: bitbucketConnectionService(connectAppConnectionById), zabbix: zabbixConnectionService(connectAppConnectionById) }; }; diff --git a/backend/src/services/app-connection/bitbucket/bitbucket-connection-fns.ts b/backend/src/services/app-connection/bitbucket/bitbucket-connection-fns.ts index 14159fa49..2d418a8a3 100644 --- a/backend/src/services/app-connection/bitbucket/bitbucket-connection-fns.ts +++ b/backend/src/services/app-connection/bitbucket/bitbucket-connection-fns.ts @@ -95,7 +95,7 @@ export const listBitbucketRepositories = async (appConnection: TBitbucketConnect let allRepos: TBitbucketRepo[] = []; let nextUrl: string | undefined = - `${IntegrationUrls.BITBUCKET_API_URL}/2.0/repositories/${workspaceSlug}?pagelen=100`; + `${IntegrationUrls.BITBUCKET_API_URL}/2.0/repositories/${encodeURIComponent(workspaceSlug)}?pagelen=100`; let iterationCount = 0; // Limit to 10 iterations, fetching at most 10 * 100 = 1000 repositories diff --git a/backend/src/services/app-connection/bitbucket/bitbucket-connection-schemas.ts b/backend/src/services/app-connection/bitbucket/bitbucket-connection-schemas.ts index fce641c5d..fab1bf74c 100644 --- a/backend/src/services/app-connection/bitbucket/bitbucket-connection-schemas.ts +++ b/backend/src/services/app-connection/bitbucket/bitbucket-connection-schemas.ts @@ -11,8 +11,19 @@ import { import { BitbucketConnectionMethod } from "./bitbucket-connection-enums"; export const BitbucketConnectionAccessTokenCredentialsSchema = z.object({ - apiToken: z.string().trim().min(1, "API Token required").describe(AppConnections.CREDENTIALS.BITBUCKET.apiToken), - email: z.string().email().trim().min(1, "Email required").describe(AppConnections.CREDENTIALS.BITBUCKET.email) + apiToken: z + .string() + .trim() + .min(1, "API Token required") + .max(255) + .describe(AppConnections.CREDENTIALS.BITBUCKET.apiToken), + email: z + .string() + .email() + .trim() + .min(1, "Email required") + .max(255) + .describe(AppConnections.CREDENTIALS.BITBUCKET.email) }); const BaseBitbucketConnectionSchema = BaseAppConnectionSchema.extend({ app: z.literal(AppConnection.Bitbucket) }); diff --git a/backend/src/services/app-connection/bitbucket/bitbucket-connection-service.ts b/backend/src/services/app-connection/bitbucket/bitbucket-connection-service.ts index 290ac21e3..f08a8d276 100644 --- a/backend/src/services/app-connection/bitbucket/bitbucket-connection-service.ts +++ b/backend/src/services/app-connection/bitbucket/bitbucket-connection-service.ts @@ -10,7 +10,7 @@ type TGetAppConnectionFunc = ( actor: OrgServiceActor ) => Promise; -export const bitBucketConnectionService = (getAppConnection: TGetAppConnectionFunc) => { +export const bitbucketConnectionService = (getAppConnection: TGetAppConnectionFunc) => { const listWorkspaces = async (connectionId: string, actor: OrgServiceActor) => { const appConnection = await getAppConnection(AppConnection.Bitbucket, connectionId, actor); const workspaces = await listBitbucketWorkspaces(appConnection); diff --git a/docs/documentation/platform/secret-scanning/bitbucket.mdx b/docs/documentation/platform/secret-scanning/bitbucket.mdx index 9b3defbcf..397ee6017 100644 --- a/docs/documentation/platform/secret-scanning/bitbucket.mdx +++ b/docs/documentation/platform/secret-scanning/bitbucket.mdx @@ -20,7 +20,7 @@ description: "Learn how to configure secret scanning for Bitbucket." 3. Configure which workspace and repositories you would like to scan. Then click **Next**. ![Data Source Configuration](/images/platform/secret-scanning/bitbucket/step-3.png) - - **Bitbucket Radar Connection** - the connection that has access to the repositories you want to scan. + - **Bitbucket Connection** - the connection that has access to the repositories you want to scan. - **Workspace** - the Bitbucket workspace to scan secrets in. - **Scan Repositories** - select which repositories you would like to scan. - **All Repositories** - Infisical will scan all repositories associated with your connection. diff --git a/docs/integrations/app-connections/1password.mdx b/docs/integrations/app-connections/1password.mdx index 0c3926a1b..394d8bc23 100644 --- a/docs/integrations/app-connections/1password.mdx +++ b/docs/integrations/app-connections/1password.mdx @@ -92,7 +92,7 @@ Infisical supports the use of [Service Accounts](https://developer.1password.com "method": "api-token", "credentials": { "instanceUrl": "https://1pass.example.com", - "apiToken": "[PRIVATE TOKEN]" + "apiToken": "" } }' ``` diff --git a/docs/integrations/app-connections/bitbucket.mdx b/docs/integrations/app-connections/bitbucket.mdx index 72035aee3..0af1a23b6 100644 --- a/docs/integrations/app-connections/bitbucket.mdx +++ b/docs/integrations/app-connections/bitbucket.mdx @@ -93,7 +93,7 @@ Infisical supports the use of [API Tokens](https://support.atlassian.com/bitbuck "method": "api-token", "credentials": { "email": "user@example.com", - "apiToken": "[PRIVATE TOKEN]" + "apiToken": "" } }' ``` diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/OCIVaultSyncFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/OCIVaultSyncFields.tsx index 26fa601f6..12092e301 100644 --- a/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/OCIVaultSyncFields.tsx +++ b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/OCIVaultSyncFields.tsx @@ -120,7 +120,7 @@ export const OCIVaultSyncFields = () => { menuPlacement="top" isLoading={isVaultsLoading && Boolean(connectionId)} isDisabled={!connectionId || !selectedCompartment} - value={vaults?.find((v) => v.id === value) ?? null} + value={vaults?.find((v) => v.id === value) || null} onChange={(option) => { onChange((option as SingleValue<{ id: string }>)?.id ?? null); setValue("destinationConfig.keyOcid", ""); diff --git a/frontend/src/hooks/api/appConnections/bitbucket/queries.tsx b/frontend/src/hooks/api/appConnections/bitbucket/queries.tsx index f17e516da..df74254a0 100644 --- a/frontend/src/hooks/api/appConnections/bitbucket/queries.tsx +++ b/frontend/src/hooks/api/appConnections/bitbucket/queries.tsx @@ -10,12 +10,12 @@ import { TBitbucketWorkspace } from "./types"; -const bitBucketConnectionKeys = { +const bitbucketConnectionKeys = { all: [...appConnectionKeys.all, "bitbucket"] as const, listRepos: (connectionId: string, workspaceSlug: string) => - [...bitBucketConnectionKeys.all, "repos", connectionId, workspaceSlug] as const, + [...bitbucketConnectionKeys.all, "repos", connectionId, workspaceSlug] as const, listWorkspaces: (connectionId: string) => - [...bitBucketConnectionKeys.all, "workspaces", connectionId] as const + [...bitbucketConnectionKeys.all, "workspaces", connectionId] as const }; export const useBitbucketConnectionListWorkspaces = ( @@ -25,13 +25,13 @@ export const useBitbucketConnectionListWorkspaces = ( TBitbucketWorkspace[], unknown, TBitbucketWorkspace[], - ReturnType + ReturnType >, "queryKey" | "queryFn" > ) => { return useQuery({ - queryKey: bitBucketConnectionKeys.listWorkspaces(connectionId), + queryKey: bitbucketConnectionKeys.listWorkspaces(connectionId), queryFn: async () => { const { data } = await apiRequest.get( `/api/v1/app-connections/bitbucket/${connectionId}/workspaces` @@ -52,18 +52,18 @@ export const useBitbucketConnectionListRepositories = ( unknown, TBitbucketRepo[], // The ReturnType here will be a supertype of the actual queryKey, which is acceptable - ReturnType + ReturnType >, "queryKey" | "queryFn" > ) => { return useQuery({ // Append workspaceSlug to the existing query key for unique caching - queryKey: bitBucketConnectionKeys.listRepos(connectionId, workspaceSlug), + queryKey: bitbucketConnectionKeys.listRepos(connectionId, workspaceSlug), queryFn: async () => { const { data } = await apiRequest.get( // Include workspaceSlug in the API endpoint path - `/api/v1/app-connections/bitbucket/${connectionId}/repositories?workspaceSlug=${workspaceSlug}` + `/api/v1/app-connections/bitbucket/${connectionId}/repositories?workspaceSlug=${encodeURIComponent(workspaceSlug)}` ); return data.repositories; diff --git a/frontend/src/pages/secret-manager/integrations/BitbucketConfigurePage/BitbucketConfigurePage.tsx b/frontend/src/pages/secret-manager/integrations/BitbucketConfigurePage/BitbucketConfigurePage.tsx index 3d381c7e0..291dec6ca 100644 --- a/frontend/src/pages/secret-manager/integrations/BitbucketConfigurePage/BitbucketConfigurePage.tsx +++ b/frontend/src/pages/secret-manager/integrations/BitbucketConfigurePage/BitbucketConfigurePage.tsx @@ -89,8 +89,8 @@ export const BitbucketConfigurePage = () => { } }); - const bitBucketWorkspace = watch("targetWorkspace"); - const bitBucketRepo = watch("targetRepo"); + const bitbucketWorkspace = watch("targetWorkspace"); + const bitbucketRepo = watch("targetRepo"); const integrationAuthId = useSearch({ from: ROUTE_PATHS.SecretManager.Integratons.BitbucketConfigurePage.id, @@ -103,17 +103,17 @@ export const BitbucketConfigurePage = () => { const { data: bitbucketRepos, isPending: isBitbucketReposLoading } = useGetIntegrationAuthApps({ integrationAuthId: (integrationAuthId as string) ?? "", - workspaceSlug: bitBucketWorkspace?.slug + workspaceSlug: bitbucketWorkspace?.slug }); const { data: bitbucketEnvironments, isPending: isBitbucketEnvironmentsLoading } = useGetIntegrationAuthBitbucketEnvironments( { integrationAuthId: (integrationAuthId as string) ?? "", - workspaceSlug: bitBucketWorkspace?.slug ?? "", - repoSlug: bitBucketRepo?.appId ?? "" + workspaceSlug: bitbucketWorkspace?.slug ?? "", + repoSlug: bitbucketRepo?.appId ?? "" }, - { enabled: Boolean(bitBucketWorkspace?.slug && bitBucketRepo?.appId) } + { enabled: Boolean(bitbucketWorkspace?.slug && bitbucketRepo?.appId) } ); const onSubmit = async ({ @@ -167,8 +167,8 @@ export const BitbucketConfigurePage = () => { useEffect(() => { if ( - bitBucketWorkspace || - bitBucketRepo || + bitbucketWorkspace || + bitbucketRepo || !bitbucketRepos || !bitbucketWorkspaces || !currentWorkspace @@ -325,7 +325,7 @@ export const BitbucketConfigurePage = () => { ? "Select an environment..." : "No environments found..." } - isLoading={isBitbucketEnvironmentsLoading && Boolean(bitBucketRepo)} + isLoading={isBitbucketEnvironmentsLoading && Boolean(bitbucketRepo)} isDisabled={!bitbucketEnvironments?.length || isBitbucketEnvironmentsLoading} />