162 lines · 6.0 KB
import { z } from "zod";
import { badRequest, forbidden, notFoundError } from "../errors";
import { limitWrite, limitAccountWrite } from "../limits";
import {
  addAdvisoryComment,
  advisoryDetail,
  canManageAdvisories,
  createAdvisory,
  listAdvisories,
  setAdvisoryCollaborator,
  setAdvisoryState,
  updateAdvisory,
} from "../security/advisories";
import { loadSecuritySettings } from "../security/settings";
import { addSigningKey, deleteSigningKey, listSigningKeys } from "../security/signatures";
import { noContent, readJson, requireAccountScope } from "./http";
import type { ApiContext } from "./http";
import { advisoryAccess, ghsa, requireAdvisoryAdmin } from "./security";
import { accountName, markdownBody, title } from "~/lib/validation";

const optionalText = (max: number) =>
  z
    .string()
    .trim()
    .max(max)
    .transform((value) => value || null)
    .nullable()
    .default(null);

const advisoryFields = z.object({
  title,
  description: markdownBody.min(1, "Describe the vulnerability"),
  severity: z.enum(["low", "moderate", "high", "critical"]),
  cve_id: optionalText(32).refine((value) => value === null || /^CVE-\d{4}-\d{4,}$/.test(value), "Use CVE-YYYY-NNNN"),
  cwe_ids: optionalText(200),
  ecosystem: z.enum(["npm", "pip", "go", "cargo", "rubygems", "composer", "other"]).nullable().default(null),
  package_name: optionalText(214),
  affected_versions: optionalText(200),
  patched_versions: optionalText(200),
});