mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-24 22:48:06 +00:00
b2d3b64c48
* refactor(lint): enforce err key for errors in logger metadata * refactor(lint): flag error message and stack strings in logger-err-key
186 lines
4.7 KiB
TypeScript
186 lines
4.7 KiB
TypeScript
import { z } from 'zod/v4';
|
|
import { logger } from '../../../logger/index.ts';
|
|
import {
|
|
DeepNullish,
|
|
LooseArray,
|
|
Nullish,
|
|
} 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 Severity = z.enum(['low', 'medium', 'high', 'critical']);
|
|
|
|
const SecurityVulnerability = z
|
|
.object({
|
|
first_patched_version: Nullish(z.object({ identifier: z.string() })),
|
|
package: Package,
|
|
severity: Severity,
|
|
vulnerable_version_range: z.string(),
|
|
})
|
|
.nullable();
|
|
|
|
const CvssSeverity = z.object({
|
|
vector_string: z.string().nullable(),
|
|
score: z.number().nullable(),
|
|
});
|
|
|
|
const SecurityAdvisory = z.object({
|
|
ghsa_id: z.string(),
|
|
summary: z.string(),
|
|
description: z.string(),
|
|
identifiers: z.array(
|
|
z.object({
|
|
type: z.string(),
|
|
value: z.string(),
|
|
}),
|
|
),
|
|
references: z.array(z.object({ url: z.string() })).optional(),
|
|
severity: Severity,
|
|
cvss_severities: Nullish(
|
|
DeepNullish(
|
|
z.object({
|
|
cvss_v3: CvssSeverity.optional(),
|
|
cvss_v4: CvssSeverity.optional(),
|
|
}),
|
|
),
|
|
),
|
|
});
|
|
export type SecurityAdvisory = z.infer<typeof SecurityAdvisory>;
|
|
|
|
export const GithubVulnerabilityAlerts = LooseArray(
|
|
z.object({
|
|
dismissed_reason: Nullish(z.string()),
|
|
security_advisory: SecurityAdvisory,
|
|
security_vulnerability: SecurityVulnerability,
|
|
dependency: z.object({
|
|
manifest_path: z.string(),
|
|
}),
|
|
}),
|
|
{
|
|
onError: ({ error }) => {
|
|
logger.debug(
|
|
{ err: error },
|
|
'Vulnerability Alert: Failed to parse some alerts',
|
|
);
|
|
},
|
|
},
|
|
).transform((alerts) =>
|
|
alerts.filter((alert) => alert.security_vulnerability?.package?.ecosystem),
|
|
);
|
|
export type GithubVulnerabilityAlerts = z.infer<
|
|
typeof GithubVulnerabilityAlerts
|
|
>;
|
|
export type GithubVulnerabilityAlert = GithubVulnerabilityAlerts[number];
|
|
|
|
// 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: Nullish(
|
|
z.object({
|
|
strict: z.boolean(),
|
|
}),
|
|
),
|
|
});
|
|
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>;
|
|
|
|
const GithubIssueBase = z.object({
|
|
number: z.number(),
|
|
state: z.string().transform((val) => val.toLowerCase()),
|
|
title: z.string(),
|
|
body: z.string(),
|
|
});
|
|
|
|
const GithubGraphqlIssue = GithubIssueBase.extend({
|
|
updatedAt: z.string(),
|
|
}).transform((issue) => {
|
|
const lastModified = issue.updatedAt;
|
|
const { number, state, title, body } = issue;
|
|
return { number, state, title, body, lastModified };
|
|
});
|
|
|
|
const GithubRestIssue = GithubIssueBase.extend({
|
|
updated_at: z.string(),
|
|
}).transform((issue) => {
|
|
const lastModified = issue.updated_at;
|
|
const { number, state, title, body } = issue;
|
|
return { number, state, title, body, lastModified };
|
|
});
|
|
|
|
export const GithubIssue = z.union([GithubGraphqlIssue, GithubRestIssue]);
|
|
export type GithubIssue = z.infer<typeof GithubIssue>;
|