mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-25 15:01:49 +00:00
3eb6f5a31b
* feat(vulnerabilities): add support for github-actions vulnerability alerts * fix failed merge from main * now for real * review comments * remove no longer needed assertion
134 lines
3.4 KiB
TypeScript
134 lines
3.4 KiB
TypeScript
import { z } from 'zod/v3';
|
|
import { logger } from '../../../logger/index.ts';
|
|
import { LooseArray } from '../../../util/schema-utils/index.ts';
|
|
|
|
const Ecosystem = z.enum([
|
|
'actions',
|
|
'composer',
|
|
'go',
|
|
'maven',
|
|
'npm',
|
|
'nuget',
|
|
'pip',
|
|
'rubygems',
|
|
'rust',
|
|
]);
|
|
export type Ecosystem = z.infer<typeof Ecosystem>;
|
|
|
|
const Package = z.object({
|
|
ecosystem: Ecosystem.catch((ctx) => {
|
|
logger.debug(
|
|
{ ecosystem: ctx.input },
|
|
'Skipping vulnerability alert with unsupported ecosystem',
|
|
);
|
|
return undefined as any;
|
|
}),
|
|
name: z.string(),
|
|
});
|
|
|
|
const SecurityVulnerability = z
|
|
.object({
|
|
first_patched_version: z.object({ identifier: z.string() }).nullish(),
|
|
package: Package,
|
|
vulnerable_version_range: z.string(),
|
|
})
|
|
.nullable();
|
|
|
|
const SecurityAdvisory = z.object({
|
|
description: z.string(),
|
|
identifiers: z.array(
|
|
z.object({
|
|
type: z.string(),
|
|
value: z.string(),
|
|
}),
|
|
),
|
|
references: z.array(z.object({ url: z.string() })).optional(),
|
|
});
|
|
|
|
export const GithubVulnerabilityAlert = LooseArray(
|
|
z.object({
|
|
dismissed_reason: z.string().nullish(),
|
|
security_advisory: SecurityAdvisory,
|
|
security_vulnerability: SecurityVulnerability,
|
|
dependency: z.object({
|
|
manifest_path: z.string(),
|
|
}),
|
|
}),
|
|
{
|
|
onError: ({ error }) => {
|
|
logger.debug(
|
|
{ error },
|
|
'Vulnerability Alert: Failed to parse some alerts',
|
|
);
|
|
},
|
|
},
|
|
).transform((alerts) =>
|
|
alerts.filter((alert) => alert.security_vulnerability?.package?.ecosystem),
|
|
);
|
|
export type GithubVulnerabilityAlert = z.infer<typeof GithubVulnerabilityAlert>;
|
|
|
|
// https://docs.github.com/en/rest/repos/contents?apiVersion=2022-11-28#get-repository-content
|
|
const GithubResponseMetadata = z.object({
|
|
name: z.string(),
|
|
path: z.string(),
|
|
});
|
|
|
|
export const GithubFileMeta = GithubResponseMetadata.extend({
|
|
type: z.literal('file'),
|
|
});
|
|
export type GithubFileMeta = z.infer<typeof GithubFileMeta>;
|
|
|
|
export const GithubFile = GithubFileMeta.extend({
|
|
content: z.string(),
|
|
encoding: z.string(),
|
|
});
|
|
export type GithubFile = z.infer<typeof GithubFile>;
|
|
|
|
export const GithubDirectory = GithubResponseMetadata.extend({
|
|
type: z.literal('dir'),
|
|
});
|
|
|
|
export type GithubDirectory = z.infer<typeof GithubDirectory>;
|
|
|
|
export const GithubOtherContent = GithubResponseMetadata.extend({
|
|
type: z.literal('symlink').or(z.literal('submodule')),
|
|
});
|
|
|
|
export type GithubOtherContent = z.infer<typeof GithubOtherContent>;
|
|
|
|
export const GithubElement = GithubFile.or(GithubFileMeta)
|
|
.or(GithubDirectory)
|
|
.or(GithubOtherContent);
|
|
export type GithubElement = z.infer<typeof GithubElement>;
|
|
|
|
export const GithubContentResponse = z.array(GithubElement).or(GithubElement);
|
|
|
|
export const GithubBranchProtection = z.object({
|
|
required_status_checks: z
|
|
.object({
|
|
strict: z.boolean(),
|
|
})
|
|
.nullish()
|
|
.optional(),
|
|
});
|
|
export type GithubBranchProtection = z.infer<typeof GithubBranchProtection>;
|
|
|
|
const GithubRulesetRule = z.discriminatedUnion('type', [
|
|
z.object({
|
|
type: z.literal('non_fast_forward'),
|
|
}),
|
|
z.object({
|
|
type: z.literal('required_status_checks'),
|
|
parameters: z.object({
|
|
strict_required_status_checks_policy: z.boolean().optional(),
|
|
}),
|
|
}),
|
|
// prevents deletion
|
|
z.object({
|
|
type: z.literal('deletion'),
|
|
}),
|
|
]);
|
|
|
|
export const GithubBranchRulesets = LooseArray(GithubRulesetRule);
|
|
export type GithubBranchRulesets = z.infer<typeof GithubBranchRulesets>;
|