import {z} from 'zod' export type GetApiApiV30ProjectsProjectUuidScansScanUuidCodeFindingsFindingUuidArgs = {projectUuid: string, scanUuid: string, findingUuid: string}; export type GetApiApiV30ProjectsProjectUuidScansScanUuidCodeFindingsFindingUuidOptions = {baseUrl?: string | undefined, bearerKey?: string | undefined, fetch?: typeof fetch | undefined}; export const dtoAzureDevOpsWorkItem = z.object({project: z.string().optional(), workItemId: z.number().int().optional()}); export const dtoJiraIssue = z.object({issueId: z.string().optional(), project: z.string().optional()}); export const dtoJiraPlatformIssue = z.object({createdBy: z.string().optional(), createdByName: z.string().optional(), createdTime: z.string().optional(), errorMessage: z.string().optional(), internalStatus: z.string().optional(), issueKey: z.string().optional(), issueStatus: z.string().optional(), publicLink: z.string().optional()}); export const dtoFindingAlmIssues = z.object({azure: dtoAzureDevOpsWorkItem.optional(), jira: dtoJiraIssue.optional(), jiraPlatform: dtoJiraPlatformIssue.optional()}); export const dtoFindingComment = z.object({body: z.string().optional(), createdBy: z.string().optional(), createdTime: z.string().optional()}); export const dtoFilterType = z.object({code: z.number().int().optional(), name: z.string().optional()}); export const dtoFilter = z.object({filterTypes: z.array(dtoFilterType).optional(), isFiltered: z.boolean().optional()}); export const dtoCallStackItem = z.object({endLine: z.number().int().optional(), file: z.string().optional(), kind: z.string().optional(), line: z.number().int().optional(), name: z.string().optional(), snippet: z.string().optional(), startLine: z.number().int().optional()}); export const dtoDataFlow = z.object({ageRating: z.number().optional(), confidenceRating: z.number().optional(), createdTime: z.string().optional(), filter: dtoFilter.optional(), functionCalls: z.array(dtoCallStackItem).optional(), id: z.string().optional(), inputFlow: z.array(dtoCallStackItem).optional(), inputKind: z.string().optional(), inputSource: z.string().optional(), isNew: z.boolean().optional(), rating: z.number().optional(), sink: z.string().optional(), sinkFile: z.string().optional(), sinkKind: z.string().optional(), sinkLine: z.number().int().optional(), sinkSnippet: z.string().optional()}); export const dtoRiskFactorEndpoint = z.object({endpoint: z.string().optional(), method: z.string().optional()}); export const dtoRiskFactors = z.object({endpoints: z.array(dtoRiskFactorEndpoint).optional(), hasEndpoints: z.boolean().optional(), isExploitable: z.boolean().optional(), probability: z.string().optional()}); export const dtoLineBlame = z.object({commitId: z.string().optional(), file: z.string().optional(), line: z.number().int().optional()}); export const dtoFindingSharedStep = z.object({endLine: z.number().int().optional(), file: z.string().optional(), kind: z.string().optional(), line: z.number().int().optional(), lineBlame: dtoLineBlame.optional(), name: z.string().optional(), snippet: z.string().optional(), startLine: z.number().int().optional()}); export const dtoCapecInfo = z.object({id: z.string().optional(), title: z.string().optional(), url: z.string().optional()}); export const dtoCweInfo = z.object({id: z.string().optional(), title: z.string().optional(), url: z.string().optional()}); export const dtoHipaaInfo = z.object({control: z.string().optional(), title: z.string().optional()}); export const dtoHitrustInfo = z.object({control: z.string().optional(), title: z.string().optional()}); export const dtoNistInfo = z.object({control: z.string().optional(), priority: z.string().optional(), title: z.string().optional(), url: z.string().optional()}); export const dtoOwaspInfo = z.object({index: z.string().optional(), title: z.string().optional(), url: z.string().optional()}); export const dtoOwasp2021Info = z.object({index: z.string().optional(), title: z.string().optional(), url: z.string().optional()}); export const dtoPcidssInfo = z.object({section: z.string().optional(), title: z.string().optional()}); export const dtoSansTop25Info = z.object({rank: z.number().int().optional(), title: z.string().optional()}); export const dtoVulnerabilityTypeDefinition = z.object({capec: dtoCapecInfo.optional(), commonId: z.string().optional(), cwe: dtoCweInfo.optional(), description: z.string().optional(), driver: z.string().optional(), engineId: z.number().int().optional(), hipaa: dtoHipaaInfo.optional(), hitrust: dtoHitrustInfo.optional(), id: z.number().int().optional(), language: z.string().optional(), name: z.string().optional(), nist: dtoNistInfo.optional(), order: z.number().int().optional(), owasp: dtoOwaspInfo.optional(), owasp2021: dtoOwasp2021Info.optional(), pcidss: dtoPcidssInfo.optional(), recommendations: z.array(z.string()).optional(), references: z.array(z.string()).optional(), sansTop25: dtoSansTop25Info.optional(), sarif: z.string().optional(), sarifLevel: z.string().optional(), severity: z.string().optional(), severityRating: z.number().optional()}); export const dtoWorkflow = z.object({name: z.string().optional(), uuid: z.string().optional()}); export const dtoFindingV3 = z.object({ageRating: z.number().optional(), almIssues: dtoFindingAlmIssues.optional(), appId: z.string().optional(), baseline: z.boolean().optional(), comments: z.array(dtoFindingComment).optional(), confidenceRating: z.number().optional(), correlatedDastFindingUuids: z.array(z.string()).optional(), createdTime: z.string().optional(), dataFlows: z.array(dtoDataFlow).optional(), description: z.string().optional(), hasRemediation: z.boolean().optional(), id: z.string().optional(), isNew: z.boolean().optional(), issueStatus: z.number().int().optional(), projectId: z.string().optional(), rating: z.number().optional(), refId: z.string().optional(), reviewed: z.boolean().optional(), riskFactors: dtoRiskFactors.optional(), scanId: z.string().optional(), severity: z.string().optional(), severityRating: z.number().optional(), sharedStep: dtoFindingSharedStep.optional(), snapshotId: z.string().optional(), suppressed: z.boolean().optional(), suppressedBy: z.string().optional(), suppressionMessage: z.string().optional(), suppressionRejected: z.boolean().optional(), suppressionRequestComment: z.string().optional(), suppressionRequested: z.boolean().optional(), suppressionTime: z.string().optional(), type: dtoVulnerabilityTypeDefinition.optional(), workflowViolations: z.array(dtoWorkflow).optional(), workflowViolationsCount: z.number().int().optional()}); export const dtoMendResponseDtoFindingV3 = z.object({additionalData: z.record(z.string(), z.unknown()).optional(), response: dtoFindingV3.optional(), supportToken: z.string().optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Get a project scan finding (Code - SAST) * * GET /api/v3.0/projects/{projectUuid}/scans/{scanUuid}/code/findings/{findingUuid} */ export const getApiApiV30ProjectsProjectUuidScansScanUuidCodeFindingsFindingUuid = async (args: GetApiApiV30ProjectsProjectUuidScansScanUuidCodeFindingsFindingUuidArgs, options?: GetApiApiV30ProjectsProjectUuidScansScanUuidCodeFindingsFindingUuidOptions) => { const {baseUrl = "https://baseUrl", fetch: fetchFn = fetch, bearerKey} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (bearerKey !== undefined) headers.set('authorization', `Bearer ${bearerKey}`) const url = `${baseUrl.replace(/\/+$/, '')}/api/v3.0/projects/${encodeURIComponent(String(args.projectUuid))}/scans/${encodeURIComponent(String(args.scanUuid))}/code/findings/${encodeURIComponent(String(args.findingUuid))}${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(dtoMendResponseDtoFindingV3, await res.json()) };