diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts index 90098a7b6..b9325ed28 100644 --- a/backend/src/lib/api-docs/constants.ts +++ b/backend/src/lib/api-docs/constants.ts @@ -221,7 +221,8 @@ export const SECRETS = { export const RAW_SECRETS = { LIST: { - recursive: "Whether or not to fetch all secrets from the specified base path, and all of its subdirectories.", + recursive: + "Whether or not to fetch all secrets from the specified base path, and all of its subdirectories. Note, the max depth is 20 deep.", workspaceId: "The ID of the project to list secrets from.", workspaceSlug: "The slug of the project to list secrets from. This parameter is only usable by machine identities.", environment: "The slug of the environment to list secrets from.", diff --git a/backend/src/services/secret/secret-fns.ts b/backend/src/services/secret/secret-fns.ts index 24c2bd811..2bfda2cbe 100644 --- a/backend/src/services/secret/secret-fns.ts +++ b/backend/src/services/secret/secret-fns.ts @@ -21,6 +21,7 @@ import { } from "@app/lib/crypto"; import { BadRequestError } from "@app/lib/errors"; import { groupBy, unique } from "@app/lib/fn"; +import { logger } from "@app/lib/logger"; import { ActorAuthMethod, ActorType } from "../auth/auth-type"; import { getBotKeyFnFactory } from "../project-bot/project-bot-fns"; @@ -92,7 +93,8 @@ const buildHierarchy = (folders: TSecretFolders[]): FolderMap => { const generatePaths = ( map: FolderMap, parentId: string = "null", - basePath: string = "" + basePath: string = "", + currentDepth: number = 0 ): { path: string; folderId: string }[] => { const children = map[parentId || "null"] || []; let paths: { path: string; folderId: string }[] = []; @@ -105,13 +107,20 @@ const generatePaths = ( // eslint-disable-next-line no-nested-ternary const currPath = basePath === "" ? (isRootFolder ? "/" : `/${child.name}`) : `${basePath}/${child.name}`; + // Add the current path paths.push({ path: currPath, folderId: child.id - }); // Add the current path + }); - // Recursively generate paths for children, passing down the formatted pathh - const childPaths = generatePaths(map, child.id, currPath); + // We make sure that the recursion depth doesn't exceed 20. + // We do this to create "circuit break", basically to ensure that we can't encounter any potential memory leaks. + if (currentDepth >= 20) { + logger.info(`generatePaths: Recursion depth exceeded 20, breaking out of recursion [map=${JSON.stringify(map)}]`); + return; + } + // Recursively generate paths for children, passing down the formatted path + const childPaths = generatePaths(map, child.id, currPath, currentDepth + 1); paths = paths.concat( childPaths.map((p) => ({ path: p.path,