124 lines · 5.1 KB
import { createServerFn } from "@tanstack/react-start";
import { z } from "zod";
import { requireViewer, viewerMiddleware } from "./middleware";
import { badRequest, forbidden } from "~/server/errors";
import { limitBrowse, limitWrite } from "~/server/limits";
import { requireRepoAccess } from "~/server/repos";
import {
  addAdvisoryComment,
  advisoryDetail,
  canManageAdvisories,
  createAdvisory,
  listAdvisories,
  setAdvisoryCollaborator,
  setAdvisoryState,
  updateAdvisory,
} from "~/server/security/advisories";
import { loadSecuritySettings } from "~/server/security/settings";
import { accountName, markdownBody, repoRef, title } from "~/lib/validation";

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

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

const ghsaId = z.string().regex(/^GITFOR-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}$/);