@conterra/vuln-scan 1.0.12 → 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,23 +1,23 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var er=Object.create;var rt=Object.defineProperty;var tr=Object.getOwnPropertyDescriptor;var rr=Object.getOwnPropertyNames;var nr=Object.getPrototypeOf,ir=Object.prototype.hasOwnProperty;var nt=(t,e)=>()=>{try{return e||t((e={exports:{}}).exports,e),e.exports}catch(r){throw e=0,r}};var or=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of rr(e))!ir.call(t,i)&&i!==r&&rt(t,i,{get:()=>e[i],enumerable:!(n=tr(e,i))||n.enumerable});return t};var X=(t,e,r)=>(r=t!=null?er(nr(t)):{},or(e||!t||!t.__esModule?rt(r,"default",{value:t,enumerable:!0}):r,t));var yt=nt((Jn,bt)=>{"use strict";bt.exports=Ir;function Lr(t){let e={defaultWidth:0,output:process.stdout,tty:require("tty")};return t?(Object.keys(e).forEach(function(r){t[r]||(t[r]=e[r])}),t):e}function Ir(t){let e=Lr(t);if(e.output.getWindowSize)return e.output.getWindowSize()[0]||e.defaultWidth;if(e.tty.getWindowSize)return e.tty.getWindowSize()[1]||e.defaultWidth;if(e.output.columns)return e.output.columns;if(process.env.CLI_WIDTH){let r=parseInt(process.env.CLI_WIDTH,10);if(!isNaN(r)&&r!==0)return r}return e.defaultWidth}});var jt=nt((li,kt)=>{var $r=require("stream"),je=class extends $r{#r=null;constructor(e={}){super(e),this.writable=this.readable=!0,this.muted=!1,this.on("pipe",this._onpipe),this.replace=e.replace,this._prompt=e.prompt||null,this._hadControl=!1}#t(e,r){return this._dest?this._dest[e]:this._src?this._src[e]:r}#e(e,...r){typeof this._dest?.[e]=="function"&&this._dest[e](...r),typeof this._src?.[e]=="function"&&this._src[e](...r)}get isTTY(){return this.#r!==null?this.#r:this.#t("isTTY",!1)}set isTTY(e){this.#r=e}get rows(){return this.#t("rows")}get columns(){return this.#t("columns")}mute(){this.muted=!0}unmute(){this.muted=!1}_onpipe(e){this._src=e}pipe(e,r){return this._dest=e,super.pipe(e,r)}pause(){if(this._src)return this._src.pause()}resume(){if(this._src)return this._src.resume()}write(e){if(this.muted){if(!this.replace)return!0;if(e.match(/^\u001b/))return e.indexOf(this._prompt)===0&&(e=e.slice(this._prompt.length),e=e.replace(/./g,this.replace),e=this._prompt+e),this._hadControl=!0,this.emit("data",e);this._prompt&&this._hadControl&&e.indexOf(this._prompt)===0&&(this._hadControl=!1,this.emit("data",this._prompt),e=e.slice(this._prompt.length)),e=e.toString().replace(/./g,this.replace)}this.emit("data",e)}end(e){this.muted&&(e&&this.replace?e=e.toString().replace(/./g,this.replace):e=null),e&&this.emit("data",e),this.emit("end")}destroy(...e){return this.#e("destroy",...e)}destroySoon(...e){return this.#e("destroySoon",...e)}close(...e){return this.#e("close",...e)}};kt.exports=je});var G=X(require("path")),Ce=require("fs/promises");var N=require("fs/promises");async function me(t){try{return await sr(t)?JSON.parse(await(0,N.readFile)(t,{encoding:"utf-8"})):void 0}catch(e){throw new Error(`Error reading JSON file ${t}: ${e}`,{cause:e})}}async function it(t,e){let r=JSON.stringify(e,null,4)+`
3
- `,n=await ar(t,r);await(0,N.writeFile)(t,n,{encoding:"utf-8"})}async function sr(t){try{return await(0,N.access)(t,N.constants.F_OK),!0}catch{return!1}}async function ar(t,e){let r=await cr();if(!r)return e;let n=await r.resolveConfig(t);return n?await r.format(e,{...n,filepath:t}):e}var lr;function cr(){return lr??=import("prettier").catch(()=>{})}var re=["UNKNOWN","LOW","MEDIUM","HIGH","CRITICAL"];var Be=class t{constructor(e){this.workingDir=e}workingDir;static DEFAULT_MAVEN_REPO="https://repository.conterra.de/repository/maven-mirror-ct";static DEFAULT_VEX_SUBDIR="input/vex";static DEFAULT_OUT_SUBDIR="output";static DEFAULT_CACHE_SUBDIR="cache";static DEFAULT_SCANNERS=["grype","trivy","ossindex"];normalize(e,r){let n=e.findNoLongerDetectedVulnerabilitiesOnlyForSnapshots??!1;return{projectConfigFileLocation:r,onNewVulnerabilities:e.onNewVulnerabilities??(e.failOnNewVulnerabilities?"fail":"warn"),onNoLongerDetectedVulnerabilities:e.onNoLongerDetectedVulnerabilities??"ignore",reportNoLongerDetectedVulnerabilities:e.reportNoLongerDetectedVulnerabilities??!0,consoleReport:e.consoleReport??"BY_PROJECT_DETAILED",createSubDirsForProject:e.createSubDirsForProject??!0,mavenRepo:e.mavenRepo??t.DEFAULT_MAVEN_REPO,vexUrls:e.vexUrls??[],vexDir:this.resolvePath(e.vexDir)??(0,G.resolve)(this.workingDir,t.DEFAULT_VEX_SUBDIR),outDir:this.resolvePath(e.outDir)??(0,G.resolve)(this.workingDir,t.DEFAULT_OUT_SUBDIR),cacheDir:this.resolvePath(e.cacheDir)??(0,G.resolve)(this.workingDir,t.DEFAULT_CACHE_SUBDIR),scanners:this.normalizeScanners(e.scanners,r),projects:this.normalizeProjects(e.projects??[],n)}}normalizeScanners(e,r){return(e??t.DEFAULT_SCANNERS).map(i=>{if(typeof i!="string")throw new Error(`Invalid scanner name '${String(i)}' in configuration file '${r}'`);let o=i.split("@");if(o.length>2)throw new Error(`Invalid scanner name '${i}' in configuration file '${r}'`);return{name:o[0],version:o[1]??""}})}normalizeProjects(e,r){return e.map(n=>{let i=n;if(!i.name)throw new Error("Project name is missing on entry: "+JSON.stringify(i));if(!i.version)throw new Error("Project version is missing on entry: "+JSON.stringify(i));if(!i.purl)throw new Error("Project purl is missing on entry: "+JSON.stringify(i));let o={...i,purlAliases:i.purlAliases??[],enabled:i.enabled??!0,silent:i.silent??!1,minimumSeverity:i.minimumSeverity??"UNKNOWN"};return o.sbomFile?{...o,sbomFile:this.resolvePath(o.sbomFile)??o.sbomFile}:{...o,detectNoLongerUsedVulnerabilities:r?o.purl.endsWith("-SNAPSHOT"):!0}})}resolvePath(e){if(e)return G.default.isAbsolute(e)?e:(0,G.resolve)(this.workingDir,e)}},he=class{constructor(e){this.workingDir=e;this.normalizer=new Be(e)}workingDir;normalizer;projectConfigCache;async loadProjectConfig(){return this.projectConfigCache??=this.doLoadProjectConfig(),this.projectConfigCache}async doLoadProjectConfig(){let e=(0,G.resolve)(this.workingDir,"vuln-scan-conf.json"),r=await me(e);if(!r)throw new Error(`Missing project configuration file '${e}'`);return this.normalizer.normalize(r,e)}async loadJiraConfig(e){let r=await(0,Ce.readFile)(e,"utf8"),n=JSON.parse(r);if(!n.issues&&n.issue&&(n.issues=n.issue),!n.jiraUrl||typeof n.jiraUrl!="string")throw new Error("jira-conf.json: missing or invalid 'jiraUrl' field");if(!Array.isArray(n.issues))throw new Error("jira-conf.json: missing or invalid 'issues' array");this.validateAutoCloseSeverity(n.autoCloseBelowSeverity,"jira-conf.json: invalid 'autoCloseBelowSeverity'");for(let[i,o]of n.issues.entries())o&&typeof o=="object"&&this.validateAutoCloseSeverity(o.autoCloseBelowSeverity,`jira-conf.json: invalid 'issues[${i}].autoCloseBelowSeverity'`);return n}validateAutoCloseSeverity(e,r){if(e!==void 0&&!re.includes(e))throw new Error(`${r} value '${String(e)}'. Must be one of: ${re.join(", ")}`)}async loadAutoVexConfig(e){let r=await(0,Ce.readFile)(e,"utf8"),n=JSON.parse(r);if(!n.impactStatement||typeof n.impactStatement!="string")throw new Error("auto-vex-conf.json: missing or invalid 'impactStatement' field (must be a non-empty string)");if(n.maxSeverity!==void 0&&!re.includes(n.maxSeverity))throw new Error(`auto-vex-conf.json: invalid 'maxSeverity' value '${String(n.maxSeverity)}'. Must be one of: ${re.join(", ")}`);return n}};var Zt=require("path");var ot=require("crypto");var ur="auto_vex_max_severity=";function dr(t){return`${ur}${t}`}function st(t){let{cveName:e,purls:r,status:n,impactStatement:i,actionStatement:o,statusNotes:a,justification:s,timestamp:p=new Date().toISOString(),autoVexMaxSeverity:f}=t,h={vulnerability:{name:e},timestamp:p,products:r.map(l=>({"@id":l})),status:n};return i&&(h.impact_statement=i),o&&(h.action_statement=o),f?h.status_notes=dr(f):a&&(h.status_notes=a),s&&(h.justification=s),h}var fr="https://openvex.dev/ns/v0.2.0";function at(t,e="conterra"){let n=`https://openvex.dev/docs/public/vex-${(0,ot.randomUUID)()}`,i=t.timestamp??new Date().toISOString();return{"@context":fr,"@id":n,author:e,timestamp:i,last_updated:i,version:1,statements:[t]}}function lt(t,e){let r=e.timestamp??new Date().toISOString();return{...t,last_updated:r,version:t.version+1,statements:[...t.statements,e]}}var ge=require("fs/promises"),Se=require("path");function ct(t){let e=t.vulnerability.name;return new Set([e,...t.vulnerability.aliases??[]])}var se=class{constructor(e){this.location=e}location;_content=void 0;_exists=!1;get exists(){return this._exists}get content(){return this._content}set content(e){this._content=e,this._exists=e!==void 0}async read(){let e=await me(this.location);this._content=e??void 0,this._exists=this._content!==void 0}async write(){if(this._content===void 0)throw new Error(`Cannot write VexFile: content is undefined (${this.location})`);await(0,ge.mkdir)((0,Se.dirname)((0,Se.resolve)(this.location)),{recursive:!0}),await it(this.location,this._content)}async delete(){await(0,ge.unlink)(this.location),this._exists=!1}upsert(e,r){return this._content===void 0?(this._content=at(e,r),this._exists=!0,{created:!0}):(this._content=lt(this._content,e),{created:!1})}addProductId(e,r){this.assertContentLoaded("addProductId");let n=!1;for(let i of this._content.statements){if(!i.products||i.products.some(a=>a["@id"]===r))continue;let o=i.products.findIndex(a=>a["@id"]===e);o!==-1&&(i.products.splice(o+1,0,{"@id":r}),n=!0)}return n}removeProductId(e,r){this.assertContentLoaded("removeProductId");let n=this._content.statements,i=[],o=!1;for(let a of n){if(r&&!ct(a).has(r)||!a.products)continue;let s=a.products.findIndex(p=>p["@id"]===e);s!==-1&&(a.products.splice(s,1),o=!0,a.products.length===0&&i.push(a))}if(!o)return"unchanged";for(let a of i)n.splice(n.indexOf(a),1);return n.length===0?"emptied":"changed"}hasStatementForProduct(e){return this.assertContentLoaded("hasStatementForProduct"),this._content.statements.some(r=>r.products?.some(n=>n["@id"]===e)??!1)}assertContentLoaded(e){if(this._content===void 0)throw new Error(`VexFile.${e}(): content is not loaded. Call read() first (${this.location})`)}};var pr=["emacs","vim"],mr=new Set(pr);function hr(t){return mr.has(t)}function ut(){let t=process.env.INQUIRER_KEYBINDINGS;return t?Array.from(new Set(t.toLowerCase().split(/[\s,]+/).filter(hr))):[]}var j=(t,e=[])=>t.name==="up"||e.includes("vim")&&t.name==="k"||e.includes("emacs")&&t.ctrl&&t.name==="p",z=(t,e=[])=>t.name==="down"||e.includes("vim")&&t.name==="j"||e.includes("emacs")&&t.ctrl&&t.name==="n",Fe=t=>t.name==="space",ae=t=>t.name==="backspace",le=t=>t.name==="tab",ce=t=>"1234567890".includes(t.name),V=t=>t.name==="enter"||t.name==="return";var we=class extends Error{name="AbortPromptError";message="Prompt was aborted";constructor(e){super(),this.cause=e?.cause}},xe=class extends Error{name="CancelPromptError";message="Prompt was canceled"},ue=class extends Error{name="ExitPromptError"},be=class extends Error{name="HookError"},q=class extends Error{name="ValidationError"};var mt=require("node:async_hooks");var ye=require("node:async_hooks");var dt=new ye.AsyncLocalStorage;function gr(t){return{rl:t,hooks:[],hooksCleanup:[],hooksEffect:[],index:0,handleChange(){}}}function ft(t,e){let r=gr(t);return dt.run(r,()=>{function n(i){r.handleChange=()=>{r.index=0,i()},r.handleChange()}return e(n)})}function Y(){let t=dt.getStore();if(!t)throw new be("[Inquirer] Hook functions can only be called from within a prompt");return t}function Ue(){return Y().rl}function Ne(t){let e=(...r)=>{let n=Y(),i=!1,o=n.handleChange;n.handleChange=()=>{i=!0};let a=t(...r);return i&&o(),n.handleChange=o,a};return ye.AsyncResource.bind(e)}function ne(t){let e=Y(),{index:r}=e,n={get(){return e.hooks[r]},set(o){e.hooks[r]=o},initialized:r in e.hooks},i=t(n);return e.index++,i}function pt(){Y().handleChange()}var Q={queue(t){let e=Y(),{index:r}=e;e.hooksEffect.push(()=>{e.hooksCleanup[r]?.();let n=t(Ue());if(n!=null&&typeof n!="function")throw new q("useEffect return value must be a cleanup function or nothing.");e.hooksCleanup[r]=n})},run(){let t=Y();Ne(()=>{t.hooksEffect.forEach(e=>{e()}),t.hooksEffect.length=0})()},clearAll(){let t=Y();t.hooksCleanup.forEach(e=>{e?.()}),t.hooksEffect.length=0,t.hooksCleanup.length=0}};function Sr(t){return typeof t=="function"}function D(t){return ne(e=>{let r=mt.AsyncResource.bind(function(o){e.get()!==o&&(e.set(o),pt())});if(e.initialized)return[e.get(),r];let n=Sr(t)?t():t;return e.set(n),[n,r]})}function $(t,e){ne(r=>{let n=r.get();(!Array.isArray(n)||e.some((o,a)=>!Object.is(o,n[a])))&&Q.queue(t),r.set(e)})}var F=require("node:util");var B=X(require("node:process"),1);function wr(){return B.default.platform.startsWith("win")?!!B.default.env.CI||!!B.default.env.WT_SESSION||!!B.default.env.TERMINUS_SUBLIME||B.default.env.ConEmuTask==="{cmd::Cmder}"||B.default.env.TERM_PROGRAM==="Terminus-Sublime"||B.default.env.TERM_PROGRAM==="vscode"||B.default.env.TERM==="xterm-256color"||B.default.env.TERM==="alacritty"||B.default.env.TERMINAL_EMULATOR==="JetBrains-JediTerm":B.default.env.TERM!=="linux"}var ht={circleQuestionMark:"(?)",questionMarkPrefix:"(?)",square:"\u2588",squareDarkShade:"\u2593",squareMediumShade:"\u2592",squareLightShade:"\u2591",squareTop:"\u2580",squareBottom:"\u2584",squareLeft:"\u258C",squareRight:"\u2590",squareCenter:"\u25A0",bullet:"\u25CF",dot:"\u2024",ellipsis:"\u2026",pointerSmall:"\u203A",triangleUp:"\u25B2",triangleUpSmall:"\u25B4",triangleDown:"\u25BC",triangleDownSmall:"\u25BE",triangleLeftSmall:"\u25C2",triangleRightSmall:"\u25B8",home:"\u2302",heart:"\u2665",musicNote:"\u266A",musicNoteBeamed:"\u266B",arrowUp:"\u2191",arrowDown:"\u2193",arrowLeft:"\u2190",arrowRight:"\u2192",arrowLeftRight:"\u2194",arrowUpDown:"\u2195",almostEqual:"\u2248",notEqual:"\u2260",lessOrEqual:"\u2264",greaterOrEqual:"\u2265",identical:"\u2261",infinity:"\u221E",subscriptZero:"\u2080",subscriptOne:"\u2081",subscriptTwo:"\u2082",subscriptThree:"\u2083",subscriptFour:"\u2084",subscriptFive:"\u2085",subscriptSix:"\u2086",subscriptSeven:"\u2087",subscriptEight:"\u2088",subscriptNine:"\u2089",oneHalf:"\xBD",oneThird:"\u2153",oneQuarter:"\xBC",oneFifth:"\u2155",oneSixth:"\u2159",oneEighth:"\u215B",twoThirds:"\u2154",twoFifths:"\u2156",threeQuarters:"\xBE",threeFifths:"\u2157",threeEighths:"\u215C",fourFifths:"\u2158",fiveSixths:"\u215A",fiveEighths:"\u215D",sevenEighths:"\u215E",line:"\u2500",lineBold:"\u2501",lineDouble:"\u2550",lineDashed0:"\u2504",lineDashed1:"\u2505",lineDashed2:"\u2508",lineDashed3:"\u2509",lineDashed4:"\u254C",lineDashed5:"\u254D",lineDashed6:"\u2574",lineDashed7:"\u2576",lineDashed8:"\u2578",lineDashed9:"\u257A",lineDashed10:"\u257C",lineDashed11:"\u257E",lineDashed12:"\u2212",lineDashed13:"\u2013",lineDashed14:"\u2010",lineDashed15:"\u2043",lineVertical:"\u2502",lineVerticalBold:"\u2503",lineVerticalDouble:"\u2551",lineVerticalDashed0:"\u2506",lineVerticalDashed1:"\u2507",lineVerticalDashed2:"\u250A",lineVerticalDashed3:"\u250B",lineVerticalDashed4:"\u254E",lineVerticalDashed5:"\u254F",lineVerticalDashed6:"\u2575",lineVerticalDashed7:"\u2577",lineVerticalDashed8:"\u2579",lineVerticalDashed9:"\u257B",lineVerticalDashed10:"\u257D",lineVerticalDashed11:"\u257F",lineDownLeft:"\u2510",lineDownLeftArc:"\u256E",lineDownBoldLeftBold:"\u2513",lineDownBoldLeft:"\u2512",lineDownLeftBold:"\u2511",lineDownDoubleLeftDouble:"\u2557",lineDownDoubleLeft:"\u2556",lineDownLeftDouble:"\u2555",lineDownRight:"\u250C",lineDownRightArc:"\u256D",lineDownBoldRightBold:"\u250F",lineDownBoldRight:"\u250E",lineDownRightBold:"\u250D",lineDownDoubleRightDouble:"\u2554",lineDownDoubleRight:"\u2553",lineDownRightDouble:"\u2552",lineUpLeft:"\u2518",lineUpLeftArc:"\u256F",lineUpBoldLeftBold:"\u251B",lineUpBoldLeft:"\u251A",lineUpLeftBold:"\u2519",lineUpDoubleLeftDouble:"\u255D",lineUpDoubleLeft:"\u255C",lineUpLeftDouble:"\u255B",lineUpRight:"\u2514",lineUpRightArc:"\u2570",lineUpBoldRightBold:"\u2517",lineUpBoldRight:"\u2516",lineUpRightBold:"\u2515",lineUpDoubleRightDouble:"\u255A",lineUpDoubleRight:"\u2559",lineUpRightDouble:"\u2558",lineUpDownLeft:"\u2524",lineUpBoldDownBoldLeftBold:"\u252B",lineUpBoldDownBoldLeft:"\u2528",lineUpDownLeftBold:"\u2525",lineUpBoldDownLeftBold:"\u2529",lineUpDownBoldLeftBold:"\u252A",lineUpDownBoldLeft:"\u2527",lineUpBoldDownLeft:"\u2526",lineUpDoubleDownDoubleLeftDouble:"\u2563",lineUpDoubleDownDoubleLeft:"\u2562",lineUpDownLeftDouble:"\u2561",lineUpDownRight:"\u251C",lineUpBoldDownBoldRightBold:"\u2523",lineUpBoldDownBoldRight:"\u2520",lineUpDownRightBold:"\u251D",lineUpBoldDownRightBold:"\u2521",lineUpDownBoldRightBold:"\u2522",lineUpDownBoldRight:"\u251F",lineUpBoldDownRight:"\u251E",lineUpDoubleDownDoubleRightDouble:"\u2560",lineUpDoubleDownDoubleRight:"\u255F",lineUpDownRightDouble:"\u255E",lineDownLeftRight:"\u252C",lineDownBoldLeftBoldRightBold:"\u2533",lineDownLeftBoldRightBold:"\u252F",lineDownBoldLeftRight:"\u2530",lineDownBoldLeftBoldRight:"\u2531",lineDownBoldLeftRightBold:"\u2532",lineDownLeftRightBold:"\u252E",lineDownLeftBoldRight:"\u252D",lineDownDoubleLeftDoubleRightDouble:"\u2566",lineDownDoubleLeftRight:"\u2565",lineDownLeftDoubleRightDouble:"\u2564",lineUpLeftRight:"\u2534",lineUpBoldLeftBoldRightBold:"\u253B",lineUpLeftBoldRightBold:"\u2537",lineUpBoldLeftRight:"\u2538",lineUpBoldLeftBoldRight:"\u2539",lineUpBoldLeftRightBold:"\u253A",lineUpLeftRightBold:"\u2536",lineUpLeftBoldRight:"\u2535",lineUpDoubleLeftDoubleRightDouble:"\u2569",lineUpDoubleLeftRight:"\u2568",lineUpLeftDoubleRightDouble:"\u2567",lineUpDownLeftRight:"\u253C",lineUpBoldDownBoldLeftBoldRightBold:"\u254B",lineUpDownBoldLeftBoldRightBold:"\u2548",lineUpBoldDownLeftBoldRightBold:"\u2547",lineUpBoldDownBoldLeftRightBold:"\u254A",lineUpBoldDownBoldLeftBoldRight:"\u2549",lineUpBoldDownLeftRight:"\u2540",lineUpDownBoldLeftRight:"\u2541",lineUpDownLeftBoldRight:"\u253D",lineUpDownLeftRightBold:"\u253E",lineUpBoldDownBoldLeftRight:"\u2542",lineUpDownLeftBoldRightBold:"\u253F",lineUpBoldDownLeftBoldRight:"\u2543",lineUpBoldDownLeftRightBold:"\u2544",lineUpDownBoldLeftBoldRight:"\u2545",lineUpDownBoldLeftRightBold:"\u2546",lineUpDoubleDownDoubleLeftDoubleRightDouble:"\u256C",lineUpDoubleDownDoubleLeftRight:"\u256B",lineUpDownLeftDoubleRightDouble:"\u256A",lineCross:"\u2573",lineBackslash:"\u2572",lineSlash:"\u2571"},gt={tick:"\u2714",info:"\u2139",warning:"\u26A0",cross:"\u2718",squareSmall:"\u25FB",squareSmallFilled:"\u25FC",circle:"\u25EF",circleFilled:"\u25C9",circleDotted:"\u25CC",circleDouble:"\u25CE",circleCircle:"\u24DE",circleCross:"\u24E7",circlePipe:"\u24BE",radioOn:"\u25C9",radioOff:"\u25EF",checkboxOn:"\u2612",checkboxOff:"\u2610",checkboxCircleOn:"\u24E7",checkboxCircleOff:"\u24BE",pointer:"\u276F",triangleUpOutline:"\u25B3",triangleLeft:"\u25C0",triangleRight:"\u25B6",lozenge:"\u25C6",lozengeOutline:"\u25C7",hamburger:"\u2630",smiley:"\u32E1",mustache:"\u0DF4",star:"\u2605",play:"\u25B6",nodejs:"\u2B22",oneSeventh:"\u2150",oneNinth:"\u2151",oneTenth:"\u2152"},xr={tick:"\u221A",info:"i",warning:"\u203C",cross:"\xD7",squareSmall:"\u25A1",squareSmallFilled:"\u25A0",circle:"( )",circleFilled:"(*)",circleDotted:"( )",circleDouble:"( )",circleCircle:"(\u25CB)",circleCross:"(\xD7)",circlePipe:"(\u2502)",radioOn:"(*)",radioOff:"( )",checkboxOn:"[\xD7]",checkboxOff:"[ ]",checkboxCircleOn:"(\xD7)",checkboxCircleOff:"( )",pointer:">",triangleUpOutline:"\u2206",triangleLeft:"\u25C4",triangleRight:"\u25BA",lozenge:"\u2666",lozengeOutline:"\u25CA",hamburger:"\u2261",smiley:"\u263A",mustache:"\u250C\u2500\u2510",star:"\u2736",play:"\u25BA",nodejs:"\u2666",oneSeventh:"1/7",oneNinth:"1/9",oneTenth:"1/10"},br={...ht,...gt},yr={...ht,...xr},Er=wr(),vr=Er?br:yr,A=vr,Tn=Object.entries(gt);var Dr={prefix:{idle:(0,F.styleText)("blue","?"),done:(0,F.styleText)("green",A.tick)},spinner:{interval:80,frames:["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"].map(t=>(0,F.styleText)("yellow",t))},keybindings:[],style:{answer:t=>(0,F.styleText)("cyan",t),message:t=>(0,F.styleText)("bold",t),error:t=>(0,F.styleText)("red",`> ${t}`),defaultAnswer:t=>(0,F.styleText)("dim",`(${t})`),help:t=>(0,F.styleText)("dim",t),highlight:t=>(0,F.styleText)("cyan",t),key:t=>(0,F.styleText)("cyan",(0,F.styleText)("bold",`<${t}>`))}};function St(){return{...Dr,keybindings:ut()}}function wt(t){if(typeof t!="object"||t===null)return!1;let e=t;for(;Object.getPrototypeOf(e)!==null;)e=Object.getPrototypeOf(e);return Object.getPrototypeOf(t)===e}function xt(...t){let e={};for(let r of t)for(let[n,i]of Object.entries(r)){let o=e[n];e[n]=wt(o)&&wt(i)?xt(o,i):i}return e}function O(...t){let e=[St(),...t.filter(r=>r!=null)];return xt(...e)}function M({status:t="idle",theme:e}){let[r,n]=D(!1),[i,o]=D(0),{prefix:a,spinner:s}=O(e);return $(()=>{if(t==="loading"){let f,h=-1,l=setTimeout(()=>{n(!0),f=setInterval(()=>{h=h+1,o(h%s.frames.length)},s.interval)},300);return()=>{clearTimeout(l),clearInterval(f)}}else n(!1)},[t]),r?s.frames[i]:typeof a=="string"?a:a[t==="loading"?"idle":t]??a.idle}function Z(t,e){return ne(r=>{let n=r.get();if(!n||n.dependencies.length!==e.length||n.dependencies.some((i,o)=>i!==e[o])){let i=t();return r.set({value:i,dependencies:e}),i}return n.value})}function ee(t){return D({current:t})[0]}function W(t){let e=ee(t);e.current=t,$(r=>{let n=!1,i=Ne((o,a)=>{n||e.current(a,r)});return r.input.on("keypress",i),()=>{n=!0,r.input.removeListener("keypress",i)}},[])}var Ot=X(yt(),1);var Et=(()=>{let t=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g;return e=>{let r=0;for(t.lastIndex=0;t.test(e);)r+=1;return e.length-r}})(),vt=t=>t===12288||t>=65281&&t<=65376||t>=65504&&t<=65510,Dt=t=>t===8987||t===9001||t>=12272&&t<=12287||t>=12289&&t<=12350||t>=12441&&t<=12543||t>=12549&&t<=12591||t>=12593&&t<=12686||t>=12688&&t<=12771||t>=12783&&t<=12830||t>=12832&&t<=12871||t>=12880&&t<=19903||t>=65040&&t<=65049||t>=65072&&t<=65106||t>=65108&&t<=65126||t>=65128&&t<=65131||t>=127488&&t<=127490||t>=127504&&t<=127547||t>=127552&&t<=127560||t>=131072&&t<=196605||t>=196608&&t<=262141;var Pr=/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y,Rr=/[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y,Lt=/(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu,Tr=/\t{1,1000}/y,It=new RegExp("[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*","yu"),_r=/(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y,Cr=new RegExp("\\p{M}+","gu"),Br={limit:1/0,ellipsis:""},Pt=(t,e={},r={})=>{let n=e.limit??1/0,i=e.ellipsis??"",o=e?.ellipsisWidth??(i?Pt(i,Br,r).width:0),a=0,s=r.controlWidth??0,p=r.tabWidth??8,f=r.emojiWidth??2,h=2,l=r.regularWidth??1,u=r.wideWidth??h,g=[[_r,l],[Pr,a],[Rr,s],[Tr,p],[It,f],[Lt,u]],d=0,m=0,S=t.length,b=0,w=!1,E=S,L=Math.max(0,n-o),R=0,I=0,T=0,_=0;e:for(;;){if(I>R||m>=S&&m>d){let c=t.slice(R,I)||t.slice(d,m);b=0;for(let x of c.replaceAll(Cr,"")){let y=x.codePointAt(0)||0;if(vt(y)?_=h:Dt(y)?_=u:_=l,T+_>L&&(E=Math.min(E,Math.max(R,d)+b)),T+_>n){w=!0;break e}b+=x.length,T+=_}R=I=0}if(m>=S)break e;for(let c=0,x=g.length;c<x;c++){let[y,v]=g[c];if(y.lastIndex=m,y.test(t)){if(b=y===Lt?Et(t.slice(m,y.lastIndex)):y===It?1:y.lastIndex-m,_=b*v,T+_>L&&(E=Math.min(E,m+Math.floor((L-T)/v))),T+_>n){w=!0;break e}T+=_,R=d,I=m,m=d=y.lastIndex;continue e}}m+=1}return{width:w?L:T,index:w?E:S,truncated:w,ellipsed:w&&n>=o}},Rt=Pt;var Fr={limit:1/0,ellipsis:"",ellipsisWidth:0},Ur=(t,e={})=>Rt(t,Fr,e).width,K=Ur;var Ee="\x1B",Ft="\x9B",Nr=39,Oe="\x07",Ut="[",Ar="]",Nt="m",ke=`${Ar}8;;`,Tt=new RegExp(`(?:\\${Ut}(?<code>\\d+)m|\\${ke}(?<uri>.*)${Oe})`,"y"),_t=t=>{if(t>=30&&t<=37||t>=90&&t<=97)return 39;if(t>=40&&t<=47||t>=100&&t<=107)return 49;if(t===1||t===2)return 22;if(t===3)return 23;if(t===4)return 24;if(t===7)return 27;if(t===8)return 28;if(t===9)return 29;if(t===0)return 0},Ct=t=>`${Ee}${Ut}${t}${Nt}`,Bt=t=>`${Ee}${ke}${t}${Oe}`,Ae=(t,e,r)=>{let n=e[Symbol.iterator](),i=!1,o=!1,a=t.at(-1),s=a===void 0?0:K(a),p=n.next(),f=n.next(),h=0;for(;!p.done;){let l=p.value,u=K(l);s+u<=r?t[t.length-1]+=l:(t.push(l),s=0),(l===Ee||l===Ft)&&(i=!0,o=e.startsWith(ke,h+1)),i?o?l===Oe&&(i=!1,o=!1):l===Nt&&(i=!1):(s+=u,s===r&&!f.done&&(t.push(""),s=0)),p=f,f=n.next(),h+=l.length}a=t.at(-1),!s&&a!==void 0&&a.length&&t.length>1&&(t[t.length-2]+=t.pop())},Or=t=>{let e=t.split(" "),r=e.length;for(;r&&!K(e[r-1]);)r--;return r===e.length?t:e.slice(0,r).join(" ")+e.slice(r).join("")},kr=(t,e,r={})=>{if(r.trim!==!1&&t.trim()==="")return"";let n="",i,o,a=t.split(" "),s=[""],p=0;for(let l=0;l<a.length;l++){let u=a[l];if(r.trim!==!1){let d=s.at(-1)??"",m=d.trimStart();d.length!==m.length&&(s[s.length-1]=m,p=K(m))}l!==0&&(p>=e&&(r.wordWrap===!1||r.trim===!1)&&(s.push(""),p=0),(p||r.trim===!1)&&(s[s.length-1]+=" ",p++));let g=K(u);if(r.hard&&g>e){let d=e-p,m=1+Math.floor((g-d-1)/e);Math.floor((g-1)/e)<m&&s.push(""),Ae(s,u,e),p=K(s.at(-1)??"");continue}if(p+g>e&&p&&g){if(r.wordWrap===!1&&p<e){Ae(s,u,e),p=K(s.at(-1)??"");continue}s.push(""),p=0}if(p+g>e&&r.wordWrap===!1){Ae(s,u,e),p=K(s.at(-1)??"");continue}s[s.length-1]+=u,p+=g}r.trim!==!1&&(s=s.map(l=>Or(l)));let f=s.join(`
4
- `),h=!1;for(let l=0;l<f.length;l++){let u=f[l];if(n+=u,h)h=!1;else if(h=u>="\uD800"&&u<="\uDBFF",h)continue;if(u===Ee||u===Ft){Tt.lastIndex=l+1;let d=Tt.exec(f)?.groups;if(d?.code!==void 0){let m=Number.parseFloat(d.code);i=m===Nr?void 0:m}else d?.uri!==void 0&&(o=d.uri.length===0?void 0:d.uri)}if(f[l+1]===`
5
- `){o&&(n+=Bt(""));let g=i?_t(i):void 0;i&&g&&(n+=Ct(g))}else u===`
6
- `&&(i&&_t(i)&&(n+=Ct(i)),o&&(n+=Bt(o)))}return n},jr=/\r?\n/;function At(t,e,r){return String(t).normalize().split(jr).map(n=>kr(n,e,r)).join(`
7
- `)}function de(t,e){return t.split(`
8
- `).flatMap(r=>At(r,e,{trim:!1,wordWrap:!1}).split(`
2
+ "use strict";var rr=Object.create;var it=Object.defineProperty;var nr=Object.getOwnPropertyDescriptor;var ir=Object.getOwnPropertyNames;var or=Object.getPrototypeOf,sr=Object.prototype.hasOwnProperty;var ot=(t,e)=>()=>{try{return e||t((e={exports:{}}).exports,e),e.exports}catch(r){throw e=0,r}};var ar=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of ir(e))!sr.call(t,i)&&i!==r&&it(t,i,{get:()=>e[i],enumerable:!(n=nr(e,i))||n.enumerable});return t};var z=(t,e,r)=>(r=t!=null?rr(or(t)):{},ar(e||!t||!t.__esModule?it(r,"default",{value:t,enumerable:!0}):r,t));var Et=ot((zn,vt)=>{"use strict";vt.exports=Rr;function Pr(t){let e={defaultWidth:0,output:process.stdout,tty:require("tty")};return t?(Object.keys(e).forEach(function(r){t[r]||(t[r]=e[r])}),t):e}function Rr(t){let e=Pr(t);if(e.output.getWindowSize)return e.output.getWindowSize()[0]||e.defaultWidth;if(e.tty.getWindowSize)return e.tty.getWindowSize()[1]||e.defaultWidth;if(e.output.columns)return e.output.columns;if(process.env.CLI_WIDTH){let r=parseInt(process.env.CLI_WIDTH,10);if(!isNaN(r)&&r!==0)return r}return e.defaultWidth}});var $t=ot((ui,Vt)=>{var Kr=require("stream"),$e=class extends Kr{#r=null;constructor(e={}){super(e),this.writable=this.readable=!0,this.muted=!1,this.on("pipe",this._onpipe),this.replace=e.replace,this._prompt=e.prompt||null,this._hadControl=!1}#t(e,r){return this._dest?this._dest[e]:this._src?this._src[e]:r}#e(e,...r){typeof this._dest?.[e]=="function"&&this._dest[e](...r),typeof this._src?.[e]=="function"&&this._src[e](...r)}get isTTY(){return this.#r!==null?this.#r:this.#t("isTTY",!1)}set isTTY(e){this.#r=e}get rows(){return this.#t("rows")}get columns(){return this.#t("columns")}mute(){this.muted=!0}unmute(){this.muted=!1}_onpipe(e){this._src=e}pipe(e,r){return this._dest=e,super.pipe(e,r)}pause(){if(this._src)return this._src.pause()}resume(){if(this._src)return this._src.resume()}write(e){if(this.muted){if(!this.replace)return!0;if(e.match(/^\u001b/))return e.indexOf(this._prompt)===0&&(e=e.slice(this._prompt.length),e=e.replace(/./g,this.replace),e=this._prompt+e),this._hadControl=!0,this.emit("data",e);this._prompt&&this._hadControl&&e.indexOf(this._prompt)===0&&(this._hadControl=!1,this.emit("data",this._prompt),e=e.slice(this._prompt.length)),e=e.toString().replace(/./g,this.replace)}this.emit("data",e)}end(e){this.muted&&(e&&this.replace?e=e.toString().replace(/./g,this.replace):e=null),e&&this.emit("data",e),this.emit("end")}destroy(...e){return this.#e("destroy",...e)}destroySoon(...e){return this.#e("destroySoon",...e)}close(...e){return this.#e("close",...e)}};Vt.exports=$e});var q=z(require("path")),Be=require("fs/promises");var j=require("fs/promises");async function me(t){try{return await lr(t)?JSON.parse(await(0,j.readFile)(t,{encoding:"utf-8"})):void 0}catch(e){throw new Error(`Error reading JSON file ${t}: ${e}`,{cause:e})}}async function st(t,e){let r=JSON.stringify(e,null,4)+`
3
+ `,n=await cr(t,r);await(0,j.writeFile)(t,n,{encoding:"utf-8"})}async function lr(t){try{return await(0,j.access)(t,j.constants.F_OK),!0}catch{return!1}}async function cr(t,e){let r=await fr();if(!r)return e;let n=await r.resolveConfig(t);return n?await r.format(e,{...n,filepath:t}):e}var ur;function fr(){return ur??=import("prettier").catch(()=>{})}var k=["UNKNOWN","LOW","MEDIUM","HIGH","CRITICAL"];var Fe=class t{constructor(e){this.workingDir=e}workingDir;static DEFAULT_MAVEN_REPO="https://repository.conterra.de/repository/maven-mirror-ct";static DEFAULT_VEX_SUBDIR="input/vex";static DEFAULT_OUT_SUBDIR="output";static DEFAULT_CACHE_SUBDIR="cache";static DEFAULT_SCANNERS=["grype","trivy","ossindex"];normalize(e,r){let n=e.findNoLongerDetectedVulnerabilitiesOnlyForSnapshots??!1;return{projectConfigFileLocation:r,onNewVulnerabilities:e.onNewVulnerabilities??(e.failOnNewVulnerabilities?"fail":"warn"),onNoLongerDetectedVulnerabilities:e.onNoLongerDetectedVulnerabilities??"ignore",reportNoLongerDetectedVulnerabilities:e.reportNoLongerDetectedVulnerabilities??!0,consoleReport:e.consoleReport??"BY_PROJECT_DETAILED",createSubDirsForProject:e.createSubDirsForProject??!0,mavenRepo:e.mavenRepo??t.DEFAULT_MAVEN_REPO,vexUrls:e.vexUrls??[],vexDir:this.resolvePath(e.vexDir)??(0,q.resolve)(this.workingDir,t.DEFAULT_VEX_SUBDIR),outDir:this.resolvePath(e.outDir)??(0,q.resolve)(this.workingDir,t.DEFAULT_OUT_SUBDIR),cacheDir:this.resolvePath(e.cacheDir)??(0,q.resolve)(this.workingDir,t.DEFAULT_CACHE_SUBDIR),scanners:this.normalizeScanners(e.scanners,r),projects:this.normalizeProjects(e.projects??[],n)}}normalizeScanners(e,r){return(e??t.DEFAULT_SCANNERS).map(i=>{if(typeof i!="string")throw new Error(`Invalid scanner name '${String(i)}' in configuration file '${r}'`);let o=i.split("@");if(o.length>2)throw new Error(`Invalid scanner name '${i}' in configuration file '${r}'`);return{name:o[0],version:o[1]??""}})}normalizeProjects(e,r){return e.map(n=>{let i=n;if(!i.name)throw new Error("Project name is missing on entry: "+JSON.stringify(i));if(!i.version)throw new Error("Project version is missing on entry: "+JSON.stringify(i));if(!i.purl)throw new Error("Project purl is missing on entry: "+JSON.stringify(i));let o={...i,purlAliases:i.purlAliases??[],enabled:i.enabled??!0,silent:i.silent??!1,minimumSeverity:i.minimumSeverity??"UNKNOWN"};return o.sbomFile?{...o,sbomFile:this.resolvePath(o.sbomFile)??o.sbomFile}:{...o,detectNoLongerUsedVulnerabilities:r?o.purl.endsWith("-SNAPSHOT"):!0}})}resolvePath(e){if(e)return q.default.isAbsolute(e)?e:(0,q.resolve)(this.workingDir,e)}},he=class{constructor(e){this.workingDir=e;this.normalizer=new Fe(e)}workingDir;normalizer;projectConfigCache;async loadProjectConfig(){return this.projectConfigCache??=this.doLoadProjectConfig(),this.projectConfigCache}async doLoadProjectConfig(){let e=(0,q.resolve)(this.workingDir,"vuln-scan-conf.json"),r=await me(e);if(!r)throw new Error(`Missing project configuration file '${e}'`);return this.normalizer.normalize(r,e)}async loadJiraConfig(e){let r=await(0,Be.readFile)(e,"utf8"),n=JSON.parse(r);if(!n.issues&&n.issue&&(n.issues=n.issue),!n.jiraUrl||typeof n.jiraUrl!="string")throw new Error("jira-conf.json: missing or invalid 'jiraUrl' field");if(!Array.isArray(n.issues))throw new Error("jira-conf.json: missing or invalid 'issues' array");this.validateAutoCloseSeverity(n.autoCloseBelowSeverity,"jira-conf.json: invalid 'autoCloseBelowSeverity'");for(let[i,o]of n.issues.entries())if(o&&typeof o=="object"){let s=o;this.validateAutoCloseSeverity(s.autoCloseBelowSeverity,`jira-conf.json: invalid 'issues[${i}].autoCloseBelowSeverity'`),this.validateAutoCloseProjectOverrides(s.projectOverrides,`jira-conf.json: invalid 'issues[${i}].projectOverrides'`)}return n}validateAutoCloseSeverity(e,r){if(e!==void 0&&!k.includes(e))throw new Error(`${r} value '${String(e)}'. Must be one of: ${k.join(", ")}`)}validateAutoCloseProjectOverrides(e,r){if(e!==void 0){if(!Array.isArray(e))throw new Error(`${r}: must be an array`);for(let n=0;n<e.length;n++){let i=e[n],o=`${r}[${n}]`;if(i==null||typeof i!="object")throw new Error(`${o}: must be an object`);let s=i,a=s.projects;if(!Array.isArray(a)||a.length===0)throw new Error(`${o}.projects: must be a non-empty array of strings`);for(let p=0;p<a.length;p++){let u=a[p];if(typeof u!="string"||u.length===0)throw new Error(`${o}.projects[${p}]: must be a non-empty string`)}if(s.autoCloseBelowSeverity===void 0)throw new Error(`${o}.autoCloseBelowSeverity: is required`);if(this.validateAutoCloseSeverity(s.autoCloseBelowSeverity,`${o}.autoCloseBelowSeverity`),s.comment!==void 0&&typeof s.comment!="string")throw new Error(`${o}.comment: must be a string`)}}}async loadAutoVexConfig(e){let r=await(0,Be.readFile)(e,"utf8"),n=JSON.parse(r);if(!n.impactStatement||typeof n.impactStatement!="string")throw new Error("auto-vex-conf.json: missing or invalid 'impactStatement' field (must be a non-empty string)");if(n.maxSeverity!==void 0&&!k.includes(n.maxSeverity))throw new Error(`auto-vex-conf.json: invalid 'maxSeverity' value '${String(n.maxSeverity)}'. Must be one of: ${k.join(", ")}`);if(n.projectOverrides!==void 0){if(!Array.isArray(n.projectOverrides))throw new Error("auto-vex-conf.json: 'projectOverrides' must be an array");for(let[i,o]of n.projectOverrides.entries()){if(!o||typeof o!="object")throw new Error(`auto-vex-conf.json: 'projectOverrides[${i}]' must be an object`);let s=o;if(!Array.isArray(s.projects)||s.projects.length===0||!s.projects.every(a=>typeof a=="string"&&a.length>0))throw new Error(`auto-vex-conf.json: 'projectOverrides[${i}].projects' must be a non-empty array of non-empty strings`);if(!k.includes(s.maxSeverity))throw new Error(`auto-vex-conf.json: invalid 'projectOverrides[${i}].maxSeverity' value '${String(s.maxSeverity)}'. Must be one of: ${k.join(", ")}`)}}return n}};var tr=require("path");var at=require("crypto");var Ue="auto_vex_max_severity=";function dr(t){return`${Ue}${t}`}function ge(t){let e=t.status_notes;if(!e||!e.startsWith(Ue))return;let r=e.slice(Ue.length).trim();return k.includes(r)?r:void 0}function lt(t){let{cveName:e,purls:r,status:n,impactStatement:i,actionStatement:o,statusNotes:s,justification:a,timestamp:p=new Date().toISOString(),autoVexMaxSeverity:u}=t,h={vulnerability:{name:e},timestamp:p,products:r.map(l=>({"@id":l})),status:n};return i&&(h.impact_statement=i),o&&(h.action_statement=o),u?h.status_notes=dr(u):s&&(h.status_notes=s),a&&(h.justification=a),h}var pr="https://openvex.dev/ns/v0.2.0";function ct(t,e="conterra"){let n=`https://openvex.dev/docs/public/vex-${(0,at.randomUUID)()}`,i=t.timestamp??new Date().toISOString();return{"@context":pr,"@id":n,author:e,timestamp:i,last_updated:i,version:1,statements:[t]}}function ut(t,e){let r=e.timestamp??new Date().toISOString();return{...t,last_updated:r,version:t.version+1,statements:[...t.statements,e]}}var Se=require("fs/promises"),we=require("path");function ft(t){let e=t.vulnerability.name;return new Set([e,...t.vulnerability.aliases??[]])}var se=class{constructor(e){this.location=e}location;_content=void 0;_exists=!1;get exists(){return this._exists}get content(){return this._content}set content(e){this._content=e,this._exists=e!==void 0}async read(){let e=await me(this.location);this._content=e??void 0,this._exists=this._content!==void 0}async write(){if(this._content===void 0)throw new Error(`Cannot write VexFile: content is undefined (${this.location})`);await(0,Se.mkdir)((0,we.dirname)((0,we.resolve)(this.location)),{recursive:!0}),await st(this.location,this._content)}async delete(){await(0,Se.unlink)(this.location),this._exists=!1}upsert(e,r){if(this._content===void 0)return this._content=ct(e,r),this._exists=!0,{created:!0,changed:!0};let n=ge(e);if(n!==void 0){let i=this._content.statements.findIndex(o=>o.vulnerability.name===e.vulnerability.name&&o.status===e.status&&ge(o)===n);if(i!==-1){let o=this._content.statements[i];return mr(o,e)?{created:!1,changed:!1}:(o.products=e.products,o.impact_statement=e.impact_statement,o.action_statement=e.action_statement,o.justification=e.justification,o.status_notes=e.status_notes,o.timestamp=e.timestamp,this._content.version+=1,this._content.last_updated=e.timestamp??new Date().toISOString(),{created:!1,changed:!0})}}return this._content=ut(this._content,e),{created:!1,changed:!0}}addProductId(e,r){this.assertContentLoaded("addProductId");let n=!1;for(let i of this._content.statements){if(!i.products||i.products.some(s=>s["@id"]===r))continue;let o=i.products.findIndex(s=>s["@id"]===e);o!==-1&&(i.products.splice(o+1,0,{"@id":r}),n=!0)}return n}removeProductId(e,r){this.assertContentLoaded("removeProductId");let n=this._content.statements,i=[],o=!1;for(let s of n){if(r&&!ft(s).has(r)||!s.products)continue;let a=s.products.findIndex(p=>p["@id"]===e);a!==-1&&(s.products.splice(a,1),o=!0,s.products.length===0&&i.push(s))}if(!o)return"unchanged";for(let s of i)n.splice(n.indexOf(s),1);return n.length===0?"emptied":"changed"}hasStatementForProduct(e){return this.assertContentLoaded("hasStatementForProduct"),this._content.statements.some(r=>r.products?.some(n=>n["@id"]===e)??!1)}assertContentLoaded(e){if(this._content===void 0)throw new Error(`VexFile.${e}(): content is not loaded. Call read() first (${this.location})`)}};function mr(t,e){return t.impact_statement!==e.impact_statement||t.action_statement!==e.action_statement||t.justification!==e.justification||t.status_notes!==e.status_notes?!1:hr(t.products,e.products)}function hr(t,e){let r=o=>Array.from(new Set((o??[]).map(s=>s["@id"]).filter(s=>typeof s=="string"))).sort(),n=r(t),i=r(e);return n.length!==i.length?!1:n.every((o,s)=>o===i[s])}var gr=["emacs","vim"],Sr=new Set(gr);function wr(t){return Sr.has(t)}function dt(){let t=process.env.INQUIRER_KEYBINDINGS;return t?Array.from(new Set(t.toLowerCase().split(/[\s,]+/).filter(wr))):[]}var V=(t,e=[])=>t.name==="up"||e.includes("vim")&&t.name==="k"||e.includes("emacs")&&t.ctrl&&t.name==="p",Y=(t,e=[])=>t.name==="down"||e.includes("vim")&&t.name==="j"||e.includes("emacs")&&t.ctrl&&t.name==="n",je=t=>t.name==="space",ae=t=>t.name==="backspace",le=t=>t.name==="tab",ce=t=>"1234567890".includes(t.name),$=t=>t.name==="enter"||t.name==="return";var xe=class extends Error{name="AbortPromptError";message="Prompt was aborted";constructor(e){super(),this.cause=e?.cause}},be=class extends Error{name="CancelPromptError";message="Prompt was canceled"},ue=class extends Error{name="ExitPromptError"},ye=class extends Error{name="HookError"},J=class extends Error{name="ValidationError"};var gt=require("node:async_hooks");var ve=require("node:async_hooks");var pt=new ve.AsyncLocalStorage;function xr(t){return{rl:t,hooks:[],hooksCleanup:[],hooksEffect:[],index:0,handleChange(){}}}function mt(t,e){let r=xr(t);return pt.run(r,()=>{function n(i){r.handleChange=()=>{r.index=0,i()},r.handleChange()}return e(n)})}function Q(){let t=pt.getStore();if(!t)throw new ye("[Inquirer] Hook functions can only be called from within a prompt");return t}function Ne(){return Q().rl}function Ae(t){let e=(...r)=>{let n=Q(),i=!1,o=n.handleChange;n.handleChange=()=>{i=!0};let s=t(...r);return i&&o(),n.handleChange=o,s};return ve.AsyncResource.bind(e)}function ne(t){let e=Q(),{index:r}=e,n={get(){return e.hooks[r]},set(o){e.hooks[r]=o},initialized:r in e.hooks},i=t(n);return e.index++,i}function ht(){Q().handleChange()}var Z={queue(t){let e=Q(),{index:r}=e;e.hooksEffect.push(()=>{e.hooksCleanup[r]?.();let n=t(Ne());if(n!=null&&typeof n!="function")throw new J("useEffect return value must be a cleanup function or nothing.");e.hooksCleanup[r]=n})},run(){let t=Q();Ae(()=>{t.hooksEffect.forEach(e=>{e()}),t.hooksEffect.length=0})()},clearAll(){let t=Q();t.hooksCleanup.forEach(e=>{e?.()}),t.hooksEffect.length=0,t.hooksCleanup.length=0}};function br(t){return typeof t=="function"}function D(t){return ne(e=>{let r=gt.AsyncResource.bind(function(o){e.get()!==o&&(e.set(o),ht())});if(e.initialized)return[e.get(),r];let n=br(t)?t():t;return e.set(n),[n,r]})}function M(t,e){ne(r=>{let n=r.get();(!Array.isArray(n)||e.some((o,s)=>!Object.is(o,n[s])))&&Z.queue(t),r.set(e)})}var F=require("node:util");var B=z(require("node:process"),1);function yr(){return B.default.platform.startsWith("win")?!!B.default.env.CI||!!B.default.env.WT_SESSION||!!B.default.env.TERMINUS_SUBLIME||B.default.env.ConEmuTask==="{cmd::Cmder}"||B.default.env.TERM_PROGRAM==="Terminus-Sublime"||B.default.env.TERM_PROGRAM==="vscode"||B.default.env.TERM==="xterm-256color"||B.default.env.TERM==="alacritty"||B.default.env.TERMINAL_EMULATOR==="JetBrains-JediTerm":B.default.env.TERM!=="linux"}var St={circleQuestionMark:"(?)",questionMarkPrefix:"(?)",square:"\u2588",squareDarkShade:"\u2593",squareMediumShade:"\u2592",squareLightShade:"\u2591",squareTop:"\u2580",squareBottom:"\u2584",squareLeft:"\u258C",squareRight:"\u2590",squareCenter:"\u25A0",bullet:"\u25CF",dot:"\u2024",ellipsis:"\u2026",pointerSmall:"\u203A",triangleUp:"\u25B2",triangleUpSmall:"\u25B4",triangleDown:"\u25BC",triangleDownSmall:"\u25BE",triangleLeftSmall:"\u25C2",triangleRightSmall:"\u25B8",home:"\u2302",heart:"\u2665",musicNote:"\u266A",musicNoteBeamed:"\u266B",arrowUp:"\u2191",arrowDown:"\u2193",arrowLeft:"\u2190",arrowRight:"\u2192",arrowLeftRight:"\u2194",arrowUpDown:"\u2195",almostEqual:"\u2248",notEqual:"\u2260",lessOrEqual:"\u2264",greaterOrEqual:"\u2265",identical:"\u2261",infinity:"\u221E",subscriptZero:"\u2080",subscriptOne:"\u2081",subscriptTwo:"\u2082",subscriptThree:"\u2083",subscriptFour:"\u2084",subscriptFive:"\u2085",subscriptSix:"\u2086",subscriptSeven:"\u2087",subscriptEight:"\u2088",subscriptNine:"\u2089",oneHalf:"\xBD",oneThird:"\u2153",oneQuarter:"\xBC",oneFifth:"\u2155",oneSixth:"\u2159",oneEighth:"\u215B",twoThirds:"\u2154",twoFifths:"\u2156",threeQuarters:"\xBE",threeFifths:"\u2157",threeEighths:"\u215C",fourFifths:"\u2158",fiveSixths:"\u215A",fiveEighths:"\u215D",sevenEighths:"\u215E",line:"\u2500",lineBold:"\u2501",lineDouble:"\u2550",lineDashed0:"\u2504",lineDashed1:"\u2505",lineDashed2:"\u2508",lineDashed3:"\u2509",lineDashed4:"\u254C",lineDashed5:"\u254D",lineDashed6:"\u2574",lineDashed7:"\u2576",lineDashed8:"\u2578",lineDashed9:"\u257A",lineDashed10:"\u257C",lineDashed11:"\u257E",lineDashed12:"\u2212",lineDashed13:"\u2013",lineDashed14:"\u2010",lineDashed15:"\u2043",lineVertical:"\u2502",lineVerticalBold:"\u2503",lineVerticalDouble:"\u2551",lineVerticalDashed0:"\u2506",lineVerticalDashed1:"\u2507",lineVerticalDashed2:"\u250A",lineVerticalDashed3:"\u250B",lineVerticalDashed4:"\u254E",lineVerticalDashed5:"\u254F",lineVerticalDashed6:"\u2575",lineVerticalDashed7:"\u2577",lineVerticalDashed8:"\u2579",lineVerticalDashed9:"\u257B",lineVerticalDashed10:"\u257D",lineVerticalDashed11:"\u257F",lineDownLeft:"\u2510",lineDownLeftArc:"\u256E",lineDownBoldLeftBold:"\u2513",lineDownBoldLeft:"\u2512",lineDownLeftBold:"\u2511",lineDownDoubleLeftDouble:"\u2557",lineDownDoubleLeft:"\u2556",lineDownLeftDouble:"\u2555",lineDownRight:"\u250C",lineDownRightArc:"\u256D",lineDownBoldRightBold:"\u250F",lineDownBoldRight:"\u250E",lineDownRightBold:"\u250D",lineDownDoubleRightDouble:"\u2554",lineDownDoubleRight:"\u2553",lineDownRightDouble:"\u2552",lineUpLeft:"\u2518",lineUpLeftArc:"\u256F",lineUpBoldLeftBold:"\u251B",lineUpBoldLeft:"\u251A",lineUpLeftBold:"\u2519",lineUpDoubleLeftDouble:"\u255D",lineUpDoubleLeft:"\u255C",lineUpLeftDouble:"\u255B",lineUpRight:"\u2514",lineUpRightArc:"\u2570",lineUpBoldRightBold:"\u2517",lineUpBoldRight:"\u2516",lineUpRightBold:"\u2515",lineUpDoubleRightDouble:"\u255A",lineUpDoubleRight:"\u2559",lineUpRightDouble:"\u2558",lineUpDownLeft:"\u2524",lineUpBoldDownBoldLeftBold:"\u252B",lineUpBoldDownBoldLeft:"\u2528",lineUpDownLeftBold:"\u2525",lineUpBoldDownLeftBold:"\u2529",lineUpDownBoldLeftBold:"\u252A",lineUpDownBoldLeft:"\u2527",lineUpBoldDownLeft:"\u2526",lineUpDoubleDownDoubleLeftDouble:"\u2563",lineUpDoubleDownDoubleLeft:"\u2562",lineUpDownLeftDouble:"\u2561",lineUpDownRight:"\u251C",lineUpBoldDownBoldRightBold:"\u2523",lineUpBoldDownBoldRight:"\u2520",lineUpDownRightBold:"\u251D",lineUpBoldDownRightBold:"\u2521",lineUpDownBoldRightBold:"\u2522",lineUpDownBoldRight:"\u251F",lineUpBoldDownRight:"\u251E",lineUpDoubleDownDoubleRightDouble:"\u2560",lineUpDoubleDownDoubleRight:"\u255F",lineUpDownRightDouble:"\u255E",lineDownLeftRight:"\u252C",lineDownBoldLeftBoldRightBold:"\u2533",lineDownLeftBoldRightBold:"\u252F",lineDownBoldLeftRight:"\u2530",lineDownBoldLeftBoldRight:"\u2531",lineDownBoldLeftRightBold:"\u2532",lineDownLeftRightBold:"\u252E",lineDownLeftBoldRight:"\u252D",lineDownDoubleLeftDoubleRightDouble:"\u2566",lineDownDoubleLeftRight:"\u2565",lineDownLeftDoubleRightDouble:"\u2564",lineUpLeftRight:"\u2534",lineUpBoldLeftBoldRightBold:"\u253B",lineUpLeftBoldRightBold:"\u2537",lineUpBoldLeftRight:"\u2538",lineUpBoldLeftBoldRight:"\u2539",lineUpBoldLeftRightBold:"\u253A",lineUpLeftRightBold:"\u2536",lineUpLeftBoldRight:"\u2535",lineUpDoubleLeftDoubleRightDouble:"\u2569",lineUpDoubleLeftRight:"\u2568",lineUpLeftDoubleRightDouble:"\u2567",lineUpDownLeftRight:"\u253C",lineUpBoldDownBoldLeftBoldRightBold:"\u254B",lineUpDownBoldLeftBoldRightBold:"\u2548",lineUpBoldDownLeftBoldRightBold:"\u2547",lineUpBoldDownBoldLeftRightBold:"\u254A",lineUpBoldDownBoldLeftBoldRight:"\u2549",lineUpBoldDownLeftRight:"\u2540",lineUpDownBoldLeftRight:"\u2541",lineUpDownLeftBoldRight:"\u253D",lineUpDownLeftRightBold:"\u253E",lineUpBoldDownBoldLeftRight:"\u2542",lineUpDownLeftBoldRightBold:"\u253F",lineUpBoldDownLeftBoldRight:"\u2543",lineUpBoldDownLeftRightBold:"\u2544",lineUpDownBoldLeftBoldRight:"\u2545",lineUpDownBoldLeftRightBold:"\u2546",lineUpDoubleDownDoubleLeftDoubleRightDouble:"\u256C",lineUpDoubleDownDoubleLeftRight:"\u256B",lineUpDownLeftDoubleRightDouble:"\u256A",lineCross:"\u2573",lineBackslash:"\u2572",lineSlash:"\u2571"},wt={tick:"\u2714",info:"\u2139",warning:"\u26A0",cross:"\u2718",squareSmall:"\u25FB",squareSmallFilled:"\u25FC",circle:"\u25EF",circleFilled:"\u25C9",circleDotted:"\u25CC",circleDouble:"\u25CE",circleCircle:"\u24DE",circleCross:"\u24E7",circlePipe:"\u24BE",radioOn:"\u25C9",radioOff:"\u25EF",checkboxOn:"\u2612",checkboxOff:"\u2610",checkboxCircleOn:"\u24E7",checkboxCircleOff:"\u24BE",pointer:"\u276F",triangleUpOutline:"\u25B3",triangleLeft:"\u25C0",triangleRight:"\u25B6",lozenge:"\u25C6",lozengeOutline:"\u25C7",hamburger:"\u2630",smiley:"\u32E1",mustache:"\u0DF4",star:"\u2605",play:"\u25B6",nodejs:"\u2B22",oneSeventh:"\u2150",oneNinth:"\u2151",oneTenth:"\u2152"},vr={tick:"\u221A",info:"i",warning:"\u203C",cross:"\xD7",squareSmall:"\u25A1",squareSmallFilled:"\u25A0",circle:"( )",circleFilled:"(*)",circleDotted:"( )",circleDouble:"( )",circleCircle:"(\u25CB)",circleCross:"(\xD7)",circlePipe:"(\u2502)",radioOn:"(*)",radioOff:"( )",checkboxOn:"[\xD7]",checkboxOff:"[ ]",checkboxCircleOn:"(\xD7)",checkboxCircleOff:"( )",pointer:">",triangleUpOutline:"\u2206",triangleLeft:"\u25C4",triangleRight:"\u25BA",lozenge:"\u2666",lozengeOutline:"\u25CA",hamburger:"\u2261",smiley:"\u263A",mustache:"\u250C\u2500\u2510",star:"\u2736",play:"\u25BA",nodejs:"\u2666",oneSeventh:"1/7",oneNinth:"1/9",oneTenth:"1/10"},Er={...St,...wt},Dr={...St,...vr},Lr=yr(),Ir=Lr?Er:Dr,N=Ir,Cn=Object.entries(wt);var _r={prefix:{idle:(0,F.styleText)("blue","?"),done:(0,F.styleText)("green",N.tick)},spinner:{interval:80,frames:["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"].map(t=>(0,F.styleText)("yellow",t))},keybindings:[],style:{answer:t=>(0,F.styleText)("cyan",t),message:t=>(0,F.styleText)("bold",t),error:t=>(0,F.styleText)("red",`> ${t}`),defaultAnswer:t=>(0,F.styleText)("dim",`(${t})`),help:t=>(0,F.styleText)("dim",t),highlight:t=>(0,F.styleText)("cyan",t),key:t=>(0,F.styleText)("cyan",(0,F.styleText)("bold",`<${t}>`))}};function xt(){return{..._r,keybindings:dt()}}function bt(t){if(typeof t!="object"||t===null)return!1;let e=t;for(;Object.getPrototypeOf(e)!==null;)e=Object.getPrototypeOf(e);return Object.getPrototypeOf(t)===e}function yt(...t){let e={};for(let r of t)for(let[n,i]of Object.entries(r)){let o=e[n];e[n]=bt(o)&&bt(i)?yt(o,i):i}return e}function A(...t){let e=[xt(),...t.filter(r=>r!=null)];return yt(...e)}function W({status:t="idle",theme:e}){let[r,n]=D(!1),[i,o]=D(0),{prefix:s,spinner:a}=A(e);return M(()=>{if(t==="loading"){let u,h=-1,l=setTimeout(()=>{n(!0),u=setInterval(()=>{h=h+1,o(h%a.frames.length)},a.interval)},300);return()=>{clearTimeout(l),clearInterval(u)}}else n(!1)},[t]),r?a.frames[i]:typeof s=="string"?s:s[t==="loading"?"idle":t]??s.idle}function ee(t,e){return ne(r=>{let n=r.get();if(!n||n.dependencies.length!==e.length||n.dependencies.some((i,o)=>i!==e[o])){let i=t();return r.set({value:i,dependencies:e}),i}return n.value})}function te(t){return D({current:t})[0]}function K(t){let e=te(t);e.current=t,M(r=>{let n=!1,i=Ae((o,s)=>{n||e.current(s,r)});return r.input.on("keypress",i),()=>{n=!0,r.input.removeListener("keypress",i)}},[])}var kt=z(Et(),1);var Dt=(()=>{let t=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g;return e=>{let r=0;for(t.lastIndex=0;t.test(e);)r+=1;return e.length-r}})(),Lt=t=>t===12288||t>=65281&&t<=65376||t>=65504&&t<=65510,It=t=>t===8987||t===9001||t>=12272&&t<=12287||t>=12289&&t<=12350||t>=12441&&t<=12543||t>=12549&&t<=12591||t>=12593&&t<=12686||t>=12688&&t<=12771||t>=12783&&t<=12830||t>=12832&&t<=12871||t>=12880&&t<=19903||t>=65040&&t<=65049||t>=65072&&t<=65106||t>=65108&&t<=65126||t>=65128&&t<=65131||t>=127488&&t<=127490||t>=127504&&t<=127547||t>=127552&&t<=127560||t>=131072&&t<=196605||t>=196608&&t<=262141;var Tr=/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y,Cr=/[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y,_t=/(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu,Br=/\t{1,1000}/y,Pt=new RegExp("[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*","yu"),Fr=/(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y,Ur=new RegExp("\\p{M}+","gu"),jr={limit:1/0,ellipsis:""},Rt=(t,e={},r={})=>{let n=e.limit??1/0,i=e.ellipsis??"",o=e?.ellipsisWidth??(i?Rt(i,jr,r).width:0),s=0,a=r.controlWidth??0,p=r.tabWidth??8,u=r.emojiWidth??2,h=2,l=r.regularWidth??1,f=r.wideWidth??h,g=[[Fr,l],[Tr,s],[Cr,a],[Br,p],[Pt,u],[_t,f]],d=0,m=0,S=t.length,b=0,w=!1,v=S,L=Math.max(0,n-o),P=0,I=0,R=0,T=0;e:for(;;){if(I>P||m>=S&&m>d){let c=t.slice(P,I)||t.slice(d,m);b=0;for(let x of c.replaceAll(Ur,"")){let y=x.codePointAt(0)||0;if(Lt(y)?T=h:It(y)?T=f:T=l,R+T>L&&(v=Math.min(v,Math.max(P,d)+b)),R+T>n){w=!0;break e}b+=x.length,R+=T}P=I=0}if(m>=S)break e;for(let c=0,x=g.length;c<x;c++){let[y,E]=g[c];if(y.lastIndex=m,y.test(t)){if(b=y===_t?Dt(t.slice(m,y.lastIndex)):y===Pt?1:y.lastIndex-m,T=b*E,R+T>L&&(v=Math.min(v,m+Math.floor((L-R)/E))),R+T>n){w=!0;break e}R+=T,P=d,I=m,m=d=y.lastIndex;continue e}}m+=1}return{width:w?L:R,index:w?v:S,truncated:w,ellipsed:w&&n>=o}},Tt=Rt;var Nr={limit:1/0,ellipsis:"",ellipsisWidth:0},Ar=(t,e={})=>Tt(t,Nr,e).width,H=Ar;var Ee="\x1B",jt="\x9B",Or=39,ke="\x07",Nt="[",kr="]",At="m",Ve=`${kr}8;;`,Ct=new RegExp(`(?:\\${Nt}(?<code>\\d+)m|\\${Ve}(?<uri>.*)${ke})`,"y"),Bt=t=>{if(t>=30&&t<=37||t>=90&&t<=97)return 39;if(t>=40&&t<=47||t>=100&&t<=107)return 49;if(t===1||t===2)return 22;if(t===3)return 23;if(t===4)return 24;if(t===7)return 27;if(t===8)return 28;if(t===9)return 29;if(t===0)return 0},Ft=t=>`${Ee}${Nt}${t}${At}`,Ut=t=>`${Ee}${Ve}${t}${ke}`,Oe=(t,e,r)=>{let n=e[Symbol.iterator](),i=!1,o=!1,s=t.at(-1),a=s===void 0?0:H(s),p=n.next(),u=n.next(),h=0;for(;!p.done;){let l=p.value,f=H(l);a+f<=r?t[t.length-1]+=l:(t.push(l),a=0),(l===Ee||l===jt)&&(i=!0,o=e.startsWith(Ve,h+1)),i?o?l===ke&&(i=!1,o=!1):l===At&&(i=!1):(a+=f,a===r&&!u.done&&(t.push(""),a=0)),p=u,u=n.next(),h+=l.length}s=t.at(-1),!a&&s!==void 0&&s.length&&t.length>1&&(t[t.length-2]+=t.pop())},Vr=t=>{let e=t.split(" "),r=e.length;for(;r&&!H(e[r-1]);)r--;return r===e.length?t:e.slice(0,r).join(" ")+e.slice(r).join("")},$r=(t,e,r={})=>{if(r.trim!==!1&&t.trim()==="")return"";let n="",i,o,s=t.split(" "),a=[""],p=0;for(let l=0;l<s.length;l++){let f=s[l];if(r.trim!==!1){let d=a.at(-1)??"",m=d.trimStart();d.length!==m.length&&(a[a.length-1]=m,p=H(m))}l!==0&&(p>=e&&(r.wordWrap===!1||r.trim===!1)&&(a.push(""),p=0),(p||r.trim===!1)&&(a[a.length-1]+=" ",p++));let g=H(f);if(r.hard&&g>e){let d=e-p,m=1+Math.floor((g-d-1)/e);Math.floor((g-1)/e)<m&&a.push(""),Oe(a,f,e),p=H(a.at(-1)??"");continue}if(p+g>e&&p&&g){if(r.wordWrap===!1&&p<e){Oe(a,f,e),p=H(a.at(-1)??"");continue}a.push(""),p=0}if(p+g>e&&r.wordWrap===!1){Oe(a,f,e),p=H(a.at(-1)??"");continue}a[a.length-1]+=f,p+=g}r.trim!==!1&&(a=a.map(l=>Vr(l)));let u=a.join(`
4
+ `),h=!1;for(let l=0;l<u.length;l++){let f=u[l];if(n+=f,h)h=!1;else if(h=f>="\uD800"&&f<="\uDBFF",h)continue;if(f===Ee||f===jt){Ct.lastIndex=l+1;let d=Ct.exec(u)?.groups;if(d?.code!==void 0){let m=Number.parseFloat(d.code);i=m===Or?void 0:m}else d?.uri!==void 0&&(o=d.uri.length===0?void 0:d.uri)}if(u[l+1]===`
5
+ `){o&&(n+=Ut(""));let g=i?Bt(i):void 0;i&&g&&(n+=Ft(g))}else f===`
6
+ `&&(i&&Bt(i)&&(n+=Ft(i)),o&&(n+=Ut(o)))}return n},Mr=/\r?\n/;function Ot(t,e,r){return String(t).normalize().split(Mr).map(n=>$r(n,e,r)).join(`
7
+ `)}function fe(t,e){return t.split(`
8
+ `).flatMap(r=>Ot(r,e,{trim:!1,wordWrap:!1}).split(`
9
9
  `).map(n=>n.trimEnd())).join(`
10
- `)}function ve(){return(0,Ot.default)({defaultWidth:80,output:Ue().output})}function Vr({active:t,renderedItems:e,pageSize:r,loop:n}){let i=ee({lastPointer:t,lastActive:void 0}),{lastPointer:o,lastActive:a}=i.current,s=Math.floor(r/2),p=e.reduce((l,u)=>l+u.length,0),f=e.slice(0,t).reduce((l,u)=>l+u.length,0),h=f;if(p>r)if(n)h=o,a!=null&&a<t&&t-a<r&&(h=Math.min(s,Math.abs(t-a)===1?Math.min(o+(e[a]?.length??0),Math.max(f,o)):o+t-a));else{let l=e.slice(t).reduce((u,g)=>u+g.length,0);h=l<r-s?r-l:Math.min(f,s)}return i.current.lastPointer=h,i.current.lastActive=t,h}function fe({items:t,active:e,renderItem:r,pageSize:n,loop:i=!0}){let o=ve(),a=b=>(b%t.length+t.length)%t.length,s=t.map((b,w)=>b==null?[]:de(r({item:b,index:w,isActive:w===e}),o).split(`
11
- `)),p=s.reduce((b,w)=>b+w.length,0),f=b=>s[b]??[],h=Vr({active:e,renderedItems:s,pageSize:n,loop:i}),l=f(e).slice(0,n),u=h+l.length<=n?h:n-l.length,g=Array.from({length:n});g.splice(u,l.length,...l);let d=new Set([e]),m=u+l.length,S=a(e+1);for(;m<n&&!d.has(S)&&(i&&p>n?S!==e:S>e);){let w=f(S).slice(0,n-m);g.splice(m,w.length,...w),d.add(S),m+=w.length,S=a(S+1)}for(m=u-1,S=a(e-1);m>=0&&!d.has(S)&&(i&&p>n?S!==e:S<e);){let b=f(S),w=b.slice(Math.max(0,b.length-m-1));g.splice(m-w.length+1,w.length,...w),d.add(S),m-=w.length,S=a(S-1)}return g.filter(b=>typeof b=="string").join(`
12
- `)}var Ht=X(require("node:readline"),1),Gt=require("node:async_hooks"),qt=X(jt(),1);var te=[];te.push("SIGHUP","SIGINT","SIGTERM");process.platform!=="win32"&&te.push("SIGALRM","SIGABRT","SIGVTALRM","SIGXCPU","SIGXFSZ","SIGUSR2","SIGTRAP","SIGSYS","SIGQUIT","SIGIOT");process.platform==="linux"&&te.push("SIGIO","SIGPOLL","SIGPWR","SIGSTKFLT");var De=t=>!!t&&typeof t=="object"&&typeof t.removeListener=="function"&&typeof t.emit=="function"&&typeof t.reallyExit=="function"&&typeof t.listeners=="function"&&typeof t.kill=="function"&&typeof t.pid=="number"&&typeof t.on=="function",Ve=Symbol.for("signal-exit emitter"),$e=globalThis,Mr=Object.defineProperty.bind(Object),Me=class{emitted={afterExit:!1,exit:!1};listeners={afterExit:[],exit:[]};count=0;id=Math.random();constructor(){if($e[Ve])return $e[Ve];Mr($e,Ve,{value:this,writable:!1,enumerable:!1,configurable:!1})}on(e,r){this.listeners[e].push(r)}removeListener(e,r){let n=this.listeners[e],i=n.indexOf(r);i!==-1&&(i===0&&n.length===1?n.length=0:n.splice(i,1))}emit(e,r,n){if(this.emitted[e])return!1;this.emitted[e]=!0;let i=!1;for(let o of this.listeners[e])i=o(r,n)===!0||i;return e==="exit"&&(i=this.emit("afterExit",r,n)||i),i}},Le=class{},Wr=t=>({onExit(e,r){return t.onExit(e,r)},load(){return t.load()},unload(){return t.unload()}}),We=class extends Le{onExit(){return()=>{}}load(){}unload(){}},Ke=class extends Le{#r=He.platform==="win32"?"SIGINT":"SIGHUP";#t=new Me;#e;#o;#s;#i={};#n=!1;constructor(e){super(),this.#e=e,this.#i={};for(let r of te)this.#i[r]=()=>{let n=this.#e.listeners(r),{count:i}=this.#t,o=e;if(typeof o.__signal_exit_emitter__=="object"&&typeof o.__signal_exit_emitter__.count=="number"&&(i+=o.__signal_exit_emitter__.count),n.length===i){this.unload();let a=this.#t.emit("exit",null,r),s=r==="SIGHUP"?this.#r:r;a||e.kill(e.pid,s)}};this.#s=e.reallyExit,this.#o=e.emit}onExit(e,r){if(!De(this.#e))return()=>{};this.#n===!1&&this.load();let n=r?.alwaysLast?"afterExit":"exit";return this.#t.on(n,e),()=>{this.#t.removeListener(n,e),this.#t.listeners.exit.length===0&&this.#t.listeners.afterExit.length===0&&this.unload()}}load(){if(!this.#n){this.#n=!0,this.#t.count+=1;for(let e of te)try{let r=this.#i[e];r&&this.#e.on(e,r)}catch{}this.#e.emit=(e,...r)=>this.#l(e,...r),this.#e.reallyExit=e=>this.#a(e)}}unload(){this.#n&&(this.#n=!1,te.forEach(e=>{let r=this.#i[e];if(!r)throw new Error("Listener not defined for signal: "+e);try{this.#e.removeListener(e,r)}catch{}}),this.#e.emit=this.#o,this.#e.reallyExit=this.#s,this.#t.count-=1)}#a(e){return De(this.#e)?(this.#e.exitCode=e||0,this.#t.emit("exit",this.#e.exitCode,null),this.#s.call(this.#e,this.#e.exitCode)):0}#l(e,...r){let n=this.#o;if(e==="exit"&&De(this.#e)){typeof r[0]=="number"&&(this.#e.exitCode=r[0]);let i=n.call(this.#e,e,...r);return this.#t.emit("exit",this.#e.exitCode,null),i}else return n.call(this.#e,e,...r)}},He=globalThis.process,{onExit:Vt,load:di,unload:fi}=Wr(De(He)?new Ke(He):new We);var Kt=require("node:util");var Ie="\x1B[?25l",Mt="\x1B[?25h",Ge=(t=1)=>t>0?`\x1B[${t}A`:"",qe=(t=1)=>t>0?`\x1B[${t}B`:"",Je=(t,e)=>typeof e=="number"&&!Number.isNaN(e)?`\x1B[${e+1};${t+1}H`:`\x1B[${t+1}G`,$t="\x1B[2K",Xe=t=>t>0?($t+Ge(1)).repeat(t-1)+$t+"\x1B[G":"";var Wt=t=>t.split(`
13
- `).length,Hr=t=>t.split(`
14
- `).pop()??"",pe=class{height=0;extraLinesUnderPrompt=0;cursorPos;rl;constructor(e){this.rl=e,this.cursorPos=e.getCursorPos()}write(e){this.rl.output.unmute(),this.rl.output.write(e),this.rl.output.mute()}render(e,r=""){let n=Hr(e),i=(0,Kt.stripVTControlCharacters)(n),o=i;this.rl.line.length>0&&(o=o.slice(0,-this.rl.line.length)),this.rl.setPrompt(o),this.cursorPos=this.rl.getCursorPos();let a=ve();e=de(e,a),r=de(r,a),i.length%a===0&&(e+=`
15
- `);let s=e+(r?`
16
- `+r:""),f=Math.floor(i.length/a)-this.cursorPos.rows+(r?Wt(r):0);f>0&&(s+=Ge(f)),s+=Je(this.cursorPos.cols),this.write(qe(this.extraLinesUnderPrompt)+Xe(this.height)+s),this.extraLinesUnderPrompt=f,this.height=Wt(s)}checkCursorPos(){let e=this.rl.getCursorPos();e.cols!==this.cursorPos.cols&&(this.write(Je(e.cols)),this.cursorPos=e)}done({clearContent:e}){this.rl.setPrompt("");let r=qe(this.extraLinesUnderPrompt);r+=e?Xe(this.height):`
17
- `,r+="\x1B[G",r+=Mt,this.write(r),this.rl.close()}};var Pe=class extends Promise{static withResolver(){let e,r;return{promise:new Promise((i,o)=>{e=i,r=o}),resolve:e,reject:r}}};var Jt=X(require("node:path"),1),Gr=globalThis.setImmediate;function qr(){let t=Error.prepareStackTrace,e=[];try{Error.prepareStackTrace=(r,n)=>{let i=n.slice(1);return e=i,i},new Error().stack}catch{return e}return Error.prepareStackTrace=t,e}function H(t){let e=qr();return(n,i={})=>{let{input:o=process.stdin,signal:a}=i,s=new Set,p=new qt.default;p.pipe(i.output??process.stdout);let f=Ht.createInterface({terminal:!0,input:o,output:p});p.mute();let h=new pe(f),{promise:l,resolve:u,reject:g}=Pe.withResolver(),d=()=>g(new xe);if(a){let S=()=>g(new we({cause:a.reason}));if(a.aborted)return S(),Object.assign(l,{cancel:d});a.addEventListener("abort",S),s.add(()=>a.removeEventListener("abort",S))}s.add(Vt((S,b)=>{g(new ue(`User force closed the prompt with ${S} ${b}`))}));let m=()=>g(new ue("User force closed the prompt with SIGINT"));return f.on("SIGINT",m),s.add(()=>f.removeListener("SIGINT",m)),ft(f,S=>{let b=Gt.AsyncResource.bind(()=>Q.clearAll());f.on("close",b),s.add(()=>f.removeListener("close",b));let w=()=>{let E=()=>h.checkCursorPos();f.input.on("keypress",E),s.add(()=>f.input.removeListener("keypress",E));let L=null;S(()=>{let R=!1;try{let I=t(n,c=>{R?u(c):L={value:c}});if(I===void 0){let c=e[1]?.getFileName();throw c&&!c.startsWith("file://")&&(c=Jt.default.resolve(c)),new Error(`Prompt functions must return a string.
18
- at ${c}`)}let[T,_]=typeof I=="string"?[I]:I;h.render(T,_),Q.run()}catch(I){g(I)}if(R=!0,L!==null){let{value:I}=L;L=null,u(I)}})};return"readableFlowing"in o?Gr(w):w(),Object.assign(l.then(E=>(Q.clearAll(),E),E=>{throw Q.clearAll(),E}).finally(()=>{s.forEach(E=>E()),h.done({clearContent:!!i.clearPromptOnDone}),p.end()}).then(()=>l),{cancel:d})})}}var Xt=require("node:util");var P=class{separator=(0,Xt.styleText)("dim",Array.from({length:15}).join(A.line));type="separator";constructor(e){e&&(this.separator=e)}static isSeparator(e){return!!(e&&typeof e=="object"&&"type"in e&&e.type==="separator")}};var J=require("node:util");var Jr={icon:{checked:(0,J.styleText)("green",A.circleFilled),unchecked:A.circle,cursor:A.pointer,disabledChecked:(0,J.styleText)("green",A.circleDouble),disabledUnchecked:"-"},style:{disabled:t=>(0,J.styleText)("dim",t),renderSelectedChoices:t=>t.map(e=>e.short).join(", "),description:t=>(0,J.styleText)("cyan",t),keysHelpTip:t=>t.map(([e,r])=>`${(0,J.styleText)("bold",e)} ${(0,J.styleText)("dim",r)}`).join((0,J.styleText)("dim"," \u2022 "))},i18n:{disabledError:"This option is disabled and cannot be toggled."}};function Re(t){return!P.isSeparator(t)&&!t.disabled}function ze(t){return!P.isSeparator(t)}function zt(t){return!P.isSeparator(t)&&t.checked}function Ye(t){return Re(t)?{...t,checked:!t.checked}:t}function Xr(t){return function(e){return Re(e)?{...e,checked:t}:e}}function zr(t){return t.map(e=>{if(P.isSeparator(e))return e;if(typeof e!="object"||e===null||!("value"in e)){let i=String(e);return{value:e,name:i,short:i,checkedName:i,disabled:!1,checked:!1}}let r=e.name??String(e.value),n={value:e.value,name:r,short:e.short??r,checkedName:e.checkedName??r,disabled:e.disabled??!1,checked:e.checked??!1};return e.description&&(n.description=e.description),n})}var Qe=H((t,e)=>{let{pageSize:r=7,loop:n=!0,required:i,validate:o=()=>!0}=t,a={all:"a",invert:"i",...t.shortcuts},s=O(Jr,t.theme),{keybindings:p}=s,[f,h]=D("idle"),l=M({status:f,theme:s}),[u,g]=D(zr(t.choices)),d=Z(()=>{let c=u.findIndex(ze),x=u.findLastIndex(ze);if(c===-1)throw new q("[checkbox prompt] No selectable choices. All choices are disabled.");return{first:c,last:x}},[u]),[m,S]=D(d.first),[b,w]=D();W(async c=>{if(V(c)){let x=u.filter(zt),y=await o([...x]);i&&!x.length?w("At least one choice must be selected"):y===!0?(h("done"),e(x.map(v=>v.value))):w(y||"You must select a valid value")}else if(j(c,p)||z(c,p)){if(b&&w(void 0),n||j(c,p)&&m!==d.first||z(c,p)&&m!==d.last){let x=j(c,p)?-1:1,y=m;do y=(y+x+u.length)%u.length;while(!ze(u[y]));S(y)}}else if(Fe(c)){let x=u[m];x&&!P.isSeparator(x)&&(x.disabled?w(s.i18n.disabledError):(w(void 0),g(u.map((y,v)=>v===m?Ye(y):y))))}else if(c.name===a.all){let x=u.some(y=>Re(y)&&!y.checked);g(u.map(Xr(x)))}else if(c.name===a.invert)g(u.map(Ye));else if(ce(c)){let x=Number(c.name)-1,y=-1,v=u.findIndex(k=>P.isSeparator(k)?!1:(y++,y===x)),C=u[v];C&&Re(C)&&(S(v),g(u.map((k,U)=>U===v?Ye(k):k)))}});let E=s.style.message(t.message,f),L,R=fe({items:u,active:m,renderItem({item:c,isActive:x}){if(P.isSeparator(c))return` ${c.separator}`;let y=x?s.icon.cursor:" ";if(c.disabled){let U=typeof c.disabled=="string"?c.disabled:"(disabled)",_e=c.checked?s.icon.disabledChecked:s.icon.disabledUnchecked;return s.style.disabled(`${y}${_e} ${c.name} ${U}`)}x&&(L=c.description);let v=c.checked?s.icon.checked:s.icon.unchecked,C=c.checked?c.checkedName:c.name;return(x?s.style.highlight:U=>U)(`${y}${v} ${C}`)},pageSize:r,loop:n});if(f==="done"){let c=u.filter(zt),x=s.style.answer(s.style.renderSelectedChoices(c,u));return[l,E,x].filter(Boolean).join(" ")}let I=[["\u2191\u2193","navigate"],["space","select"]];a.all&&I.push([a.all,"all"]),a.invert&&I.push([a.invert,"invert"]),I.push(["\u23CE","submit"]);let T=s.style.keysHelpTip(I);return`${[[l,E].filter(Boolean).join(" "),R," ",L?s.style.description(L):"",b?s.style.error(b):"",T].filter(Boolean).join(`
19
- `).trimEnd()}${Ie}`});function Yt(t,e){let r=e!==!1;return/^(y|yes)/i.test(t)?r=!0:/^(n|no)/i.test(t)&&(r=!1),r}function Qt(t){return t?"Yes":"No"}var Ze=H((t,e)=>{let{transformer:r=Qt}=t,[n,i]=D("idle"),[o,a]=D(""),s=O(t.theme),p=M({status:n,theme:s});W((u,g)=>{if(n==="idle")if(V(u)){let d=Yt(o,t.default);a(r(d)),i("done"),e(d)}else if(le(u)){let d=Qt(!Yt(o,t.default));g.clearLine(0),g.write(d),a(d)}else a(g.line)});let f=o,h="";n==="done"?f=s.style.answer(o):h=` ${s.style.defaultAnswer(t.default===!1?"y/N":"Y/n")}`;let l=s.style.message(t.message,n);return`${p} ${l}${h} ${f}`});var Yr={validationFailureMode:"keep"},ie=H((t,e)=>{let{prefill:r="tab"}=t,n=O(Yr,t.theme),[i,o]=D("idle"),[a,s]=D(String(t.default??"")),[p,f]=D(),[h,l]=D(""),u=M({status:i,theme:n});async function g(w){let{required:E,pattern:L,patternError:R="Invalid input"}=t;return E&&!w?"You must provide a value":L&&!L.test(w)?R:typeof t.validate=="function"?await t.validate(w)||"You must provide a valid value":!0}W(async(w,E)=>{if(i==="idle")if(V(w)){let L=h||a;o("loading");let R=await g(L);R===!0?(l(L),o("done"),e(L)):(n.validationFailureMode==="clear"?l(""):E.write(h),f(R),o("idle"))}else ae(w)&&!h?s(""):le(w)&&!h?(s(""),E.clearLine(0),E.write(a),l(a)):(l(E.line),f(void 0))}),$(w=>{r==="editable"&&a&&(w.write(a),l(a))},[]);let d=n.style.message(t.message,i),m=h;typeof t.transformer=="function"?m=t.transformer(h,{isFinal:i==="done"}):i==="done"&&(m=n.style.answer(h));let S;a&&i!=="done"&&!h&&(S=n.style.defaultAnswer(a));let b="";return p&&(b=n.style.error(p)),[[u,d,S,m].filter(w=>w!==void 0).join(" "),b]});var oe=require("node:util");var Qr={icon:{cursor:A.pointer},style:{disabled:t=>(0,oe.styleText)("dim",t),description:t=>(0,oe.styleText)("cyan",t),keysHelpTip:t=>t.map(([e,r])=>`${(0,oe.styleText)("bold",e)} ${(0,oe.styleText)("dim",r)}`).join((0,oe.styleText)("dim"," \u2022 "))},i18n:{disabledError:"This option is disabled and cannot be selected."},indexMode:"hidden"};function et(t){return!P.isSeparator(t)&&!t.disabled}function tt(t){return!P.isSeparator(t)}function Zr(t){return t.map(e=>{if(P.isSeparator(e))return e;if(typeof e!="object"||e===null||!("value"in e)){let i=String(e);return{value:e,name:i,short:i,disabled:!1}}let r=e.name??String(e.value),n={value:e.value,name:r,short:e.short??r,disabled:e.disabled??!1};return e.description&&(n.description=e.description),n})}var Te=H((t,e)=>{let{loop:r=!0,pageSize:n=7}=t,i=O(Qr,t.theme),{keybindings:o}=i,[a,s]=D("idle"),p=M({status:a,theme:i}),f=ee(),h=!o.includes("vim"),l=Z(()=>Zr(t.choices),[t.choices]),u=Z(()=>{let c=l.findIndex(tt),x=l.findLastIndex(tt);if(c===-1)throw new q("[select prompt] No selectable choices. All choices are disabled.");return{first:c,last:x}},[l]),g=Z(()=>"default"in t?l.findIndex(c=>et(c)&&c.value===t.default):-1,[t.default,l]),[d,m]=D(g===-1?u.first:g),S=l[d];if(S==null||P.isSeparator(S))throw new Error("Active index does not point to a choice");let[b,w]=D();W((c,x)=>{if(clearTimeout(f.current),b&&w(void 0),V(c))S.disabled?w(i.i18n.disabledError):(s("done"),e(S.value));else if(j(c,o)||z(c,o)){if(x.clearLine(0),r||j(c,o)&&d!==u.first||z(c,o)&&d!==u.last){let y=j(c,o)?-1:1,v=d;do v=(v+y+l.length)%l.length;while(!tt(l[v]));m(v)}}else if(ce(c)&&!Number.isNaN(Number(x.line))){let y=Number(x.line)-1,v=-1,C=l.findIndex(U=>P.isSeparator(U)?!1:(v++,v===y)),k=l[C];k!=null&&et(k)&&m(C),f.current=setTimeout(()=>{x.clearLine(0)},700)}else if(ae(c))x.clearLine(0);else if(h){let y=x.line.toLowerCase(),v=l.findIndex(C=>P.isSeparator(C)||!et(C)?!1:C.name.toLowerCase().startsWith(y));v!==-1&&m(v),f.current=setTimeout(()=>{x.clearLine(0)},700)}}),$(()=>()=>{clearTimeout(f.current)},[]);let E=i.style.message(t.message,a),L=i.style.keysHelpTip([["\u2191\u2193","navigate"],["\u23CE","select"]]),R=0,I=fe({items:l,active:d,renderItem({item:c,isActive:x,index:y}){if(P.isSeparator(c))return R++,` ${c.separator}`;let v=x?i.icon.cursor:" ",C=i.indexMode==="number"?`${y+1-R}. `:"";if(c.disabled){let U=typeof c.disabled=="string"?c.disabled:"(disabled)",_e=x?i.icon.cursor:"-";return i.style.disabled(`${_e} ${C}${c.name} ${U}`)}return(x?i.style.highlight:U=>U)(`${v} ${C}${c.name}`)},pageSize:n,loop:r});if(a==="done")return[p,E,i.style.answer(S.short)].filter(Boolean).join(" ");let{description:T}=S;return`${[[p,E].filter(Boolean).join(" "),I," ",T?i.style.description(T):"",b?i.style.error(b):"",L].filter(Boolean).join(`
20
- `).trimEnd()}${Ie}`});(async()=>{let e=!process.argv.slice(2).includes("--no-project-filter");try{let r=await new he(process.cwd()).loadProjectConfig();console.info("## Add New VEX Statement ##");let n=await ie({message:"CVE name (e.g. CVE-2023-52070)",required:!0}),i=r.projects.filter(d=>!e||d.enabled&&!d.silent).map(d=>({name:`${d.name}@${d.version}`,value:d.purl}));i.sort((d,m)=>d.name.localeCompare(m.name));let o=await Qe({message:"Projects to add",choices:i,required:!0,pageSize:15}),a=(0,Zt.resolve)(r.vexDir,`${n}.json`),s=["under_investigation","affected","fixed","not_affected"],p=await Te({message:"Status?",choices:s.map(d=>({name:d,value:d})),default:s[s.length-1]}),f={};switch(p){case"affected":{let d=await ie({message:"Action statement?",required:!0});f.actionStatement=d;break}case"not_affected":{let m=await Te({message:"Justification?",choices:["none","component_not_present","vulnerable_code_not_present","vulnerable_code_not_in_execute_path","vulnerable_code_cannot_be_controlled_by_adversary","inline_mitigations_already_exist"].map(b=>({name:b,value:b}))});m!=="none"&&(f.justification=m);let S=await ie({message:"Impact statement?",required:m==="none"});S&&(f.impactStatement=S);break}case"fixed":{let d=await ie({message:"Status note?"});d&&(f.statusNotes=d);break}}let h=new Date().toISOString(),l=st({cveName:n,purls:Array.from(o),status:p,timestamp:h,...f});await Ze({message:`Following statement will be added to ${a}:
10
+ `)}function De(){return(0,kt.default)({defaultWidth:80,output:Ne().output})}function Wr({active:t,renderedItems:e,pageSize:r,loop:n}){let i=te({lastPointer:t,lastActive:void 0}),{lastPointer:o,lastActive:s}=i.current,a=Math.floor(r/2),p=e.reduce((l,f)=>l+f.length,0),u=e.slice(0,t).reduce((l,f)=>l+f.length,0),h=u;if(p>r)if(n)h=o,s!=null&&s<t&&t-s<r&&(h=Math.min(a,Math.abs(t-s)===1?Math.min(o+(e[s]?.length??0),Math.max(u,o)):o+t-s));else{let l=e.slice(t).reduce((f,g)=>f+g.length,0);h=l<r-a?r-l:Math.min(u,a)}return i.current.lastPointer=h,i.current.lastActive=t,h}function de({items:t,active:e,renderItem:r,pageSize:n,loop:i=!0}){let o=De(),s=b=>(b%t.length+t.length)%t.length,a=t.map((b,w)=>b==null?[]:fe(r({item:b,index:w,isActive:w===e}),o).split(`
11
+ `)),p=a.reduce((b,w)=>b+w.length,0),u=b=>a[b]??[],h=Wr({active:e,renderedItems:a,pageSize:n,loop:i}),l=u(e).slice(0,n),f=h+l.length<=n?h:n-l.length,g=Array.from({length:n});g.splice(f,l.length,...l);let d=new Set([e]),m=f+l.length,S=s(e+1);for(;m<n&&!d.has(S)&&(i&&p>n?S!==e:S>e);){let w=u(S).slice(0,n-m);g.splice(m,w.length,...w),d.add(S),m+=w.length,S=s(S+1)}for(m=f-1,S=s(e-1);m>=0&&!d.has(S)&&(i&&p>n?S!==e:S<e);){let b=u(S),w=b.slice(Math.max(0,b.length-m-1));g.splice(m-w.length+1,w.length,...w),d.add(S),m-=w.length,S=s(S-1)}return g.filter(b=>typeof b=="string").join(`
12
+ `)}var qt=z(require("node:readline"),1),Jt=require("node:async_hooks"),Xt=z($t(),1);var re=[];re.push("SIGHUP","SIGINT","SIGTERM");process.platform!=="win32"&&re.push("SIGALRM","SIGABRT","SIGVTALRM","SIGXCPU","SIGXFSZ","SIGUSR2","SIGTRAP","SIGSYS","SIGQUIT","SIGIOT");process.platform==="linux"&&re.push("SIGIO","SIGPOLL","SIGPWR","SIGSTKFLT");var Le=t=>!!t&&typeof t=="object"&&typeof t.removeListener=="function"&&typeof t.emit=="function"&&typeof t.reallyExit=="function"&&typeof t.listeners=="function"&&typeof t.kill=="function"&&typeof t.pid=="number"&&typeof t.on=="function",Me=Symbol.for("signal-exit emitter"),We=globalThis,Hr=Object.defineProperty.bind(Object),Ke=class{emitted={afterExit:!1,exit:!1};listeners={afterExit:[],exit:[]};count=0;id=Math.random();constructor(){if(We[Me])return We[Me];Hr(We,Me,{value:this,writable:!1,enumerable:!1,configurable:!1})}on(e,r){this.listeners[e].push(r)}removeListener(e,r){let n=this.listeners[e],i=n.indexOf(r);i!==-1&&(i===0&&n.length===1?n.length=0:n.splice(i,1))}emit(e,r,n){if(this.emitted[e])return!1;this.emitted[e]=!0;let i=!1;for(let o of this.listeners[e])i=o(r,n)===!0||i;return e==="exit"&&(i=this.emit("afterExit",r,n)||i),i}},Ie=class{},Gr=t=>({onExit(e,r){return t.onExit(e,r)},load(){return t.load()},unload(){return t.unload()}}),He=class extends Ie{onExit(){return()=>{}}load(){}unload(){}},Ge=class extends Ie{#r=qe.platform==="win32"?"SIGINT":"SIGHUP";#t=new Ke;#e;#o;#s;#i={};#n=!1;constructor(e){super(),this.#e=e,this.#i={};for(let r of re)this.#i[r]=()=>{let n=this.#e.listeners(r),{count:i}=this.#t,o=e;if(typeof o.__signal_exit_emitter__=="object"&&typeof o.__signal_exit_emitter__.count=="number"&&(i+=o.__signal_exit_emitter__.count),n.length===i){this.unload();let s=this.#t.emit("exit",null,r),a=r==="SIGHUP"?this.#r:r;s||e.kill(e.pid,a)}};this.#s=e.reallyExit,this.#o=e.emit}onExit(e,r){if(!Le(this.#e))return()=>{};this.#n===!1&&this.load();let n=r?.alwaysLast?"afterExit":"exit";return this.#t.on(n,e),()=>{this.#t.removeListener(n,e),this.#t.listeners.exit.length===0&&this.#t.listeners.afterExit.length===0&&this.unload()}}load(){if(!this.#n){this.#n=!0,this.#t.count+=1;for(let e of re)try{let r=this.#i[e];r&&this.#e.on(e,r)}catch{}this.#e.emit=(e,...r)=>this.#l(e,...r),this.#e.reallyExit=e=>this.#a(e)}}unload(){this.#n&&(this.#n=!1,re.forEach(e=>{let r=this.#i[e];if(!r)throw new Error("Listener not defined for signal: "+e);try{this.#e.removeListener(e,r)}catch{}}),this.#e.emit=this.#o,this.#e.reallyExit=this.#s,this.#t.count-=1)}#a(e){return Le(this.#e)?(this.#e.exitCode=e||0,this.#t.emit("exit",this.#e.exitCode,null),this.#s.call(this.#e,this.#e.exitCode)):0}#l(e,...r){let n=this.#o;if(e==="exit"&&Le(this.#e)){typeof r[0]=="number"&&(this.#e.exitCode=r[0]);let i=n.call(this.#e,e,...r);return this.#t.emit("exit",this.#e.exitCode,null),i}else return n.call(this.#e,e,...r)}},qe=globalThis.process,{onExit:Mt,load:pi,unload:mi}=Gr(Le(qe)?new Ge(qe):new He);var Gt=require("node:util");var _e="\x1B[?25l",Kt="\x1B[?25h",Je=(t=1)=>t>0?`\x1B[${t}A`:"",Xe=(t=1)=>t>0?`\x1B[${t}B`:"",ze=(t,e)=>typeof e=="number"&&!Number.isNaN(e)?`\x1B[${e+1};${t+1}H`:`\x1B[${t+1}G`,Wt="\x1B[2K",Ye=t=>t>0?(Wt+Je(1)).repeat(t-1)+Wt+"\x1B[G":"";var Ht=t=>t.split(`
13
+ `).length,Jr=t=>t.split(`
14
+ `).pop()??"",pe=class{height=0;extraLinesUnderPrompt=0;cursorPos;rl;constructor(e){this.rl=e,this.cursorPos=e.getCursorPos()}write(e){this.rl.output.unmute(),this.rl.output.write(e),this.rl.output.mute()}render(e,r=""){let n=Jr(e),i=(0,Gt.stripVTControlCharacters)(n),o=i;this.rl.line.length>0&&(o=o.slice(0,-this.rl.line.length)),this.rl.setPrompt(o),this.cursorPos=this.rl.getCursorPos();let s=De();e=fe(e,s),r=fe(r,s),i.length%s===0&&(e+=`
15
+ `);let a=e+(r?`
16
+ `+r:""),u=Math.floor(i.length/s)-this.cursorPos.rows+(r?Ht(r):0);u>0&&(a+=Je(u)),a+=ze(this.cursorPos.cols),this.write(Xe(this.extraLinesUnderPrompt)+Ye(this.height)+a),this.extraLinesUnderPrompt=u,this.height=Ht(a)}checkCursorPos(){let e=this.rl.getCursorPos();e.cols!==this.cursorPos.cols&&(this.write(ze(e.cols)),this.cursorPos=e)}done({clearContent:e}){this.rl.setPrompt("");let r=Xe(this.extraLinesUnderPrompt);r+=e?Ye(this.height):`
17
+ `,r+="\x1B[G",r+=Kt,this.write(r),this.rl.close()}};var Pe=class extends Promise{static withResolver(){let e,r;return{promise:new Promise((i,o)=>{e=i,r=o}),resolve:e,reject:r}}};var zt=z(require("node:path"),1),Xr=globalThis.setImmediate;function zr(){let t=Error.prepareStackTrace,e=[];try{Error.prepareStackTrace=(r,n)=>{let i=n.slice(1);return e=i,i},new Error().stack}catch{return e}return Error.prepareStackTrace=t,e}function G(t){let e=zr();return(n,i={})=>{let{input:o=process.stdin,signal:s}=i,a=new Set,p=new Xt.default;p.pipe(i.output??process.stdout);let u=qt.createInterface({terminal:!0,input:o,output:p});p.mute();let h=new pe(u),{promise:l,resolve:f,reject:g}=Pe.withResolver(),d=()=>g(new be);if(s){let S=()=>g(new xe({cause:s.reason}));if(s.aborted)return S(),Object.assign(l,{cancel:d});s.addEventListener("abort",S),a.add(()=>s.removeEventListener("abort",S))}a.add(Mt((S,b)=>{g(new ue(`User force closed the prompt with ${S} ${b}`))}));let m=()=>g(new ue("User force closed the prompt with SIGINT"));return u.on("SIGINT",m),a.add(()=>u.removeListener("SIGINT",m)),mt(u,S=>{let b=Jt.AsyncResource.bind(()=>Z.clearAll());u.on("close",b),a.add(()=>u.removeListener("close",b));let w=()=>{let v=()=>h.checkCursorPos();u.input.on("keypress",v),a.add(()=>u.input.removeListener("keypress",v));let L=null;S(()=>{let P=!1;try{let I=t(n,c=>{P?f(c):L={value:c}});if(I===void 0){let c=e[1]?.getFileName();throw c&&!c.startsWith("file://")&&(c=zt.default.resolve(c)),new Error(`Prompt functions must return a string.
18
+ at ${c}`)}let[R,T]=typeof I=="string"?[I]:I;h.render(R,T),Z.run()}catch(I){g(I)}if(P=!0,L!==null){let{value:I}=L;L=null,f(I)}})};return"readableFlowing"in o?Xr(w):w(),Object.assign(l.then(v=>(Z.clearAll(),v),v=>{throw Z.clearAll(),v}).finally(()=>{a.forEach(v=>v()),h.done({clearContent:!!i.clearPromptOnDone}),p.end()}).then(()=>l),{cancel:d})})}}var Yt=require("node:util");var _=class{separator=(0,Yt.styleText)("dim",Array.from({length:15}).join(N.line));type="separator";constructor(e){e&&(this.separator=e)}static isSeparator(e){return!!(e&&typeof e=="object"&&"type"in e&&e.type==="separator")}};var X=require("node:util");var Yr={icon:{checked:(0,X.styleText)("green",N.circleFilled),unchecked:N.circle,cursor:N.pointer,disabledChecked:(0,X.styleText)("green",N.circleDouble),disabledUnchecked:"-"},style:{disabled:t=>(0,X.styleText)("dim",t),renderSelectedChoices:t=>t.map(e=>e.short).join(", "),description:t=>(0,X.styleText)("cyan",t),keysHelpTip:t=>t.map(([e,r])=>`${(0,X.styleText)("bold",e)} ${(0,X.styleText)("dim",r)}`).join((0,X.styleText)("dim"," \u2022 "))},i18n:{disabledError:"This option is disabled and cannot be toggled."}};function Re(t){return!_.isSeparator(t)&&!t.disabled}function Qe(t){return!_.isSeparator(t)}function Qt(t){return!_.isSeparator(t)&&t.checked}function Ze(t){return Re(t)?{...t,checked:!t.checked}:t}function Qr(t){return function(e){return Re(e)?{...e,checked:t}:e}}function Zr(t){return t.map(e=>{if(_.isSeparator(e))return e;if(typeof e!="object"||e===null||!("value"in e)){let i=String(e);return{value:e,name:i,short:i,checkedName:i,disabled:!1,checked:!1}}let r=e.name??String(e.value),n={value:e.value,name:r,short:e.short??r,checkedName:e.checkedName??r,disabled:e.disabled??!1,checked:e.checked??!1};return e.description&&(n.description=e.description),n})}var et=G((t,e)=>{let{pageSize:r=7,loop:n=!0,required:i,validate:o=()=>!0}=t,s={all:"a",invert:"i",...t.shortcuts},a=A(Yr,t.theme),{keybindings:p}=a,[u,h]=D("idle"),l=W({status:u,theme:a}),[f,g]=D(Zr(t.choices)),d=ee(()=>{let c=f.findIndex(Qe),x=f.findLastIndex(Qe);if(c===-1)throw new J("[checkbox prompt] No selectable choices. All choices are disabled.");return{first:c,last:x}},[f]),[m,S]=D(d.first),[b,w]=D();K(async c=>{if($(c)){let x=f.filter(Qt),y=await o([...x]);i&&!x.length?w("At least one choice must be selected"):y===!0?(h("done"),e(x.map(E=>E.value))):w(y||"You must select a valid value")}else if(V(c,p)||Y(c,p)){if(b&&w(void 0),n||V(c,p)&&m!==d.first||Y(c,p)&&m!==d.last){let x=V(c,p)?-1:1,y=m;do y=(y+x+f.length)%f.length;while(!Qe(f[y]));S(y)}}else if(je(c)){let x=f[m];x&&!_.isSeparator(x)&&(x.disabled?w(a.i18n.disabledError):(w(void 0),g(f.map((y,E)=>E===m?Ze(y):y))))}else if(c.name===s.all){let x=f.some(y=>Re(y)&&!y.checked);g(f.map(Qr(x)))}else if(c.name===s.invert)g(f.map(Ze));else if(ce(c)){let x=Number(c.name)-1,y=-1,E=f.findIndex(O=>_.isSeparator(O)?!1:(y++,y===x)),C=f[E];C&&Re(C)&&(S(E),g(f.map((O,U)=>U===E?Ze(O):O)))}});let v=a.style.message(t.message,u),L,P=de({items:f,active:m,renderItem({item:c,isActive:x}){if(_.isSeparator(c))return` ${c.separator}`;let y=x?a.icon.cursor:" ";if(c.disabled){let U=typeof c.disabled=="string"?c.disabled:"(disabled)",Ce=c.checked?a.icon.disabledChecked:a.icon.disabledUnchecked;return a.style.disabled(`${y}${Ce} ${c.name} ${U}`)}x&&(L=c.description);let E=c.checked?a.icon.checked:a.icon.unchecked,C=c.checked?c.checkedName:c.name;return(x?a.style.highlight:U=>U)(`${y}${E} ${C}`)},pageSize:r,loop:n});if(u==="done"){let c=f.filter(Qt),x=a.style.answer(a.style.renderSelectedChoices(c,f));return[l,v,x].filter(Boolean).join(" ")}let I=[["\u2191\u2193","navigate"],["space","select"]];s.all&&I.push([s.all,"all"]),s.invert&&I.push([s.invert,"invert"]),I.push(["\u23CE","submit"]);let R=a.style.keysHelpTip(I);return`${[[l,v].filter(Boolean).join(" "),P," ",L?a.style.description(L):"",b?a.style.error(b):"",R].filter(Boolean).join(`
19
+ `).trimEnd()}${_e}`});function Zt(t,e){let r=e!==!1;return/^(y|yes)/i.test(t)?r=!0:/^(n|no)/i.test(t)&&(r=!1),r}function er(t){return t?"Yes":"No"}var tt=G((t,e)=>{let{transformer:r=er}=t,[n,i]=D("idle"),[o,s]=D(""),a=A(t.theme),p=W({status:n,theme:a});K((f,g)=>{if(n==="idle")if($(f)){let d=Zt(o,t.default);s(r(d)),i("done"),e(d)}else if(le(f)){let d=er(!Zt(o,t.default));g.clearLine(0),g.write(d),s(d)}else s(g.line)});let u=o,h="";n==="done"?u=a.style.answer(o):h=` ${a.style.defaultAnswer(t.default===!1?"y/N":"Y/n")}`;let l=a.style.message(t.message,n);return`${p} ${l}${h} ${u}`});var en={validationFailureMode:"keep"},ie=G((t,e)=>{let{prefill:r="tab"}=t,n=A(en,t.theme),[i,o]=D("idle"),[s,a]=D(String(t.default??"")),[p,u]=D(),[h,l]=D(""),f=W({status:i,theme:n});async function g(w){let{required:v,pattern:L,patternError:P="Invalid input"}=t;return v&&!w?"You must provide a value":L&&!L.test(w)?P:typeof t.validate=="function"?await t.validate(w)||"You must provide a valid value":!0}K(async(w,v)=>{if(i==="idle")if($(w)){let L=h||s;o("loading");let P=await g(L);P===!0?(l(L),o("done"),e(L)):(n.validationFailureMode==="clear"?l(""):v.write(h),u(P),o("idle"))}else ae(w)&&!h?a(""):le(w)&&!h?(a(""),v.clearLine(0),v.write(s),l(s)):(l(v.line),u(void 0))}),M(w=>{r==="editable"&&s&&(w.write(s),l(s))},[]);let d=n.style.message(t.message,i),m=h;typeof t.transformer=="function"?m=t.transformer(h,{isFinal:i==="done"}):i==="done"&&(m=n.style.answer(h));let S;s&&i!=="done"&&!h&&(S=n.style.defaultAnswer(s));let b="";return p&&(b=n.style.error(p)),[[f,d,S,m].filter(w=>w!==void 0).join(" "),b]});var oe=require("node:util");var tn={icon:{cursor:N.pointer},style:{disabled:t=>(0,oe.styleText)("dim",t),description:t=>(0,oe.styleText)("cyan",t),keysHelpTip:t=>t.map(([e,r])=>`${(0,oe.styleText)("bold",e)} ${(0,oe.styleText)("dim",r)}`).join((0,oe.styleText)("dim"," \u2022 "))},i18n:{disabledError:"This option is disabled and cannot be selected."},indexMode:"hidden"};function rt(t){return!_.isSeparator(t)&&!t.disabled}function nt(t){return!_.isSeparator(t)}function rn(t){return t.map(e=>{if(_.isSeparator(e))return e;if(typeof e!="object"||e===null||!("value"in e)){let i=String(e);return{value:e,name:i,short:i,disabled:!1}}let r=e.name??String(e.value),n={value:e.value,name:r,short:e.short??r,disabled:e.disabled??!1};return e.description&&(n.description=e.description),n})}var Te=G((t,e)=>{let{loop:r=!0,pageSize:n=7}=t,i=A(tn,t.theme),{keybindings:o}=i,[s,a]=D("idle"),p=W({status:s,theme:i}),u=te(),h=!o.includes("vim"),l=ee(()=>rn(t.choices),[t.choices]),f=ee(()=>{let c=l.findIndex(nt),x=l.findLastIndex(nt);if(c===-1)throw new J("[select prompt] No selectable choices. All choices are disabled.");return{first:c,last:x}},[l]),g=ee(()=>"default"in t?l.findIndex(c=>rt(c)&&c.value===t.default):-1,[t.default,l]),[d,m]=D(g===-1?f.first:g),S=l[d];if(S==null||_.isSeparator(S))throw new Error("Active index does not point to a choice");let[b,w]=D();K((c,x)=>{if(clearTimeout(u.current),b&&w(void 0),$(c))S.disabled?w(i.i18n.disabledError):(a("done"),e(S.value));else if(V(c,o)||Y(c,o)){if(x.clearLine(0),r||V(c,o)&&d!==f.first||Y(c,o)&&d!==f.last){let y=V(c,o)?-1:1,E=d;do E=(E+y+l.length)%l.length;while(!nt(l[E]));m(E)}}else if(ce(c)&&!Number.isNaN(Number(x.line))){let y=Number(x.line)-1,E=-1,C=l.findIndex(U=>_.isSeparator(U)?!1:(E++,E===y)),O=l[C];O!=null&&rt(O)&&m(C),u.current=setTimeout(()=>{x.clearLine(0)},700)}else if(ae(c))x.clearLine(0);else if(h){let y=x.line.toLowerCase(),E=l.findIndex(C=>_.isSeparator(C)||!rt(C)?!1:C.name.toLowerCase().startsWith(y));E!==-1&&m(E),u.current=setTimeout(()=>{x.clearLine(0)},700)}}),M(()=>()=>{clearTimeout(u.current)},[]);let v=i.style.message(t.message,s),L=i.style.keysHelpTip([["\u2191\u2193","navigate"],["\u23CE","select"]]),P=0,I=de({items:l,active:d,renderItem({item:c,isActive:x,index:y}){if(_.isSeparator(c))return P++,` ${c.separator}`;let E=x?i.icon.cursor:" ",C=i.indexMode==="number"?`${y+1-P}. `:"";if(c.disabled){let U=typeof c.disabled=="string"?c.disabled:"(disabled)",Ce=x?i.icon.cursor:"-";return i.style.disabled(`${Ce} ${C}${c.name} ${U}`)}return(x?i.style.highlight:U=>U)(`${E} ${C}${c.name}`)},pageSize:n,loop:r});if(s==="done")return[p,v,i.style.answer(S.short)].filter(Boolean).join(" ");let{description:R}=S;return`${[[p,v].filter(Boolean).join(" "),I," ",R?i.style.description(R):"",b?i.style.error(b):"",L].filter(Boolean).join(`
20
+ `).trimEnd()}${_e}`});(async()=>{let e=!process.argv.slice(2).includes("--no-project-filter");try{let r=await new he(process.cwd()).loadProjectConfig();console.info("## Add New VEX Statement ##");let n=await ie({message:"CVE name (e.g. CVE-2023-52070)",required:!0}),i=r.projects.filter(d=>!e||d.enabled&&!d.silent).map(d=>({name:`${d.name}@${d.version}`,value:d.purl}));i.sort((d,m)=>d.name.localeCompare(m.name));let o=await et({message:"Projects to add",choices:i,required:!0,pageSize:15}),s=(0,tr.resolve)(r.vexDir,`${n}.json`),a=["under_investigation","affected","fixed","not_affected"],p=await Te({message:"Status?",choices:a.map(d=>({name:d,value:d})),default:a[a.length-1]}),u={};switch(p){case"affected":{let d=await ie({message:"Action statement?",required:!0});u.actionStatement=d;break}case"not_affected":{let m=await Te({message:"Justification?",choices:["none","component_not_present","vulnerable_code_not_present","vulnerable_code_not_in_execute_path","vulnerable_code_cannot_be_controlled_by_adversary","inline_mitigations_already_exist"].map(b=>({name:b,value:b}))});m!=="none"&&(u.justification=m);let S=await ie({message:"Impact statement?",required:m==="none"});S&&(u.impactStatement=S);break}case"fixed":{let d=await ie({message:"Status note?"});d&&(u.statusNotes=d);break}}let h=new Date().toISOString(),l=lt({cveName:n,purls:Array.from(o),status:p,timestamp:h,...u});await tt({message:`Following statement will be added to ${s}:
21
21
  ${JSON.stringify(l,null,2)}
22
22
 
23
- Do you want to proceed?`})||(console.log("Aborted."),process.exit(0));let g=new se(a);await g.read(),g.upsert(l),await g.write()}catch(r){console.error(`Error: ${r}`),process.exitCode=1}})();
23
+ Do you want to proceed?`})||(console.log("Aborted."),process.exit(0));let g=new se(s);await g.read(),g.upsert(l),await g.write()}catch(r){console.error(`Error: ${r}`),process.exitCode=1}})();
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var it=Object.create;var J=Object.defineProperty;var ot=Object.getOwnPropertyDescriptor;var st=Object.getOwnPropertyNames;var at=Object.getPrototypeOf,ct=Object.prototype.hasOwnProperty;var ut=(n,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of st(t))!ct.call(n,i)&&i!==e&&J(n,i,{get:()=>t[i],enumerable:!(r=ot(t,i))||r.enumerable});return n};var z=(n,t,e)=>(e=n!=null?it(at(n)):{},ut(t||!n||!n.__esModule?J(e,"default",{value:n,enumerable:!0}):e,n));var k=require("path");var y=z(require("path")),F=require("fs/promises");var g=require("fs/promises");async function C(n){try{return await lt(n)?JSON.parse(await(0,g.readFile)(n,{encoding:"utf-8"})):void 0}catch(t){throw new Error(`Error reading JSON file ${n}: ${t}`,{cause:t})}}async function G(n,t){let e=JSON.stringify(t,null,4)+`
3
- `,r=await dt(n,e);await(0,g.writeFile)(n,r,{encoding:"utf-8"})}async function lt(n){try{return await(0,g.access)(n,g.constants.F_OK),!0}catch{return!1}}async function dt(n,t){let e=await ft();if(!e)return t;let r=await e.resolveConfig(n);return r?await e.format(t,{...r,filepath:n}):t}var mt;function ft(){return mt??=import("prettier").catch(()=>{})}var K={UNKNOWN:0,LOW:1,MEDIUM:2,HIGH:3,CRITICAL:4},w=["UNKNOWN","LOW","MEDIUM","HIGH","CRITICAL"];function N(n,t){return K[n]<K[t]}var T=class n{constructor(t){this.workingDir=t}workingDir;static DEFAULT_MAVEN_REPO="https://repository.conterra.de/repository/maven-mirror-ct";static DEFAULT_VEX_SUBDIR="input/vex";static DEFAULT_OUT_SUBDIR="output";static DEFAULT_CACHE_SUBDIR="cache";static DEFAULT_SCANNERS=["grype","trivy","ossindex"];normalize(t,e){let r=t.findNoLongerDetectedVulnerabilitiesOnlyForSnapshots??!1;return{projectConfigFileLocation:e,onNewVulnerabilities:t.onNewVulnerabilities??(t.failOnNewVulnerabilities?"fail":"warn"),onNoLongerDetectedVulnerabilities:t.onNoLongerDetectedVulnerabilities??"ignore",reportNoLongerDetectedVulnerabilities:t.reportNoLongerDetectedVulnerabilities??!0,consoleReport:t.consoleReport??"BY_PROJECT_DETAILED",createSubDirsForProject:t.createSubDirsForProject??!0,mavenRepo:t.mavenRepo??n.DEFAULT_MAVEN_REPO,vexUrls:t.vexUrls??[],vexDir:this.resolvePath(t.vexDir)??(0,y.resolve)(this.workingDir,n.DEFAULT_VEX_SUBDIR),outDir:this.resolvePath(t.outDir)??(0,y.resolve)(this.workingDir,n.DEFAULT_OUT_SUBDIR),cacheDir:this.resolvePath(t.cacheDir)??(0,y.resolve)(this.workingDir,n.DEFAULT_CACHE_SUBDIR),scanners:this.normalizeScanners(t.scanners,e),projects:this.normalizeProjects(t.projects??[],r)}}normalizeScanners(t,e){return(t??n.DEFAULT_SCANNERS).map(i=>{if(typeof i!="string")throw new Error(`Invalid scanner name '${String(i)}' in configuration file '${e}'`);let o=i.split("@");if(o.length>2)throw new Error(`Invalid scanner name '${i}' in configuration file '${e}'`);return{name:o[0],version:o[1]??""}})}normalizeProjects(t,e){return t.map(r=>{let i=r;if(!i.name)throw new Error("Project name is missing on entry: "+JSON.stringify(i));if(!i.version)throw new Error("Project version is missing on entry: "+JSON.stringify(i));if(!i.purl)throw new Error("Project purl is missing on entry: "+JSON.stringify(i));let o={...i,purlAliases:i.purlAliases??[],enabled:i.enabled??!0,silent:i.silent??!1,minimumSeverity:i.minimumSeverity??"UNKNOWN"};return o.sbomFile?{...o,sbomFile:this.resolvePath(o.sbomFile)??o.sbomFile}:{...o,detectNoLongerUsedVulnerabilities:e?o.purl.endsWith("-SNAPSHOT"):!0}})}resolvePath(t){if(t)return y.default.isAbsolute(t)?t:(0,y.resolve)(this.workingDir,t)}},P=class{constructor(t){this.workingDir=t;this.normalizer=new T(t)}workingDir;normalizer;projectConfigCache;async loadProjectConfig(){return this.projectConfigCache??=this.doLoadProjectConfig(),this.projectConfigCache}async doLoadProjectConfig(){let t=(0,y.resolve)(this.workingDir,"vuln-scan-conf.json"),e=await C(t);if(!e)throw new Error(`Missing project configuration file '${t}'`);return this.normalizer.normalize(e,t)}async loadJiraConfig(t){let e=await(0,F.readFile)(t,"utf8"),r=JSON.parse(e);if(!r.issues&&r.issue&&(r.issues=r.issue),!r.jiraUrl||typeof r.jiraUrl!="string")throw new Error("jira-conf.json: missing or invalid 'jiraUrl' field");if(!Array.isArray(r.issues))throw new Error("jira-conf.json: missing or invalid 'issues' array");this.validateAutoCloseSeverity(r.autoCloseBelowSeverity,"jira-conf.json: invalid 'autoCloseBelowSeverity'");for(let[i,o]of r.issues.entries())o&&typeof o=="object"&&this.validateAutoCloseSeverity(o.autoCloseBelowSeverity,`jira-conf.json: invalid 'issues[${i}].autoCloseBelowSeverity'`);return r}validateAutoCloseSeverity(t,e){if(t!==void 0&&!w.includes(t))throw new Error(`${e} value '${String(t)}'. Must be one of: ${w.join(", ")}`)}async loadAutoVexConfig(t){let e=await(0,F.readFile)(t,"utf8"),r=JSON.parse(e);if(!r.impactStatement||typeof r.impactStatement!="string")throw new Error("auto-vex-conf.json: missing or invalid 'impactStatement' field (must be a non-empty string)");if(r.maxSeverity!==void 0&&!w.includes(r.maxSeverity))throw new Error(`auto-vex-conf.json: invalid 'maxSeverity' value '${String(r.maxSeverity)}'. Must be one of: ${w.join(", ")}`);return r}};var rt=require("fs/promises"),M=require("path");var Y=require("crypto");var _="auto_vex_max_severity=";function R(n){return`${_}${n}`}function $(n){let t=n.status_notes;if(!t||!t.startsWith(_))return;let e=t.slice(_.length).trim();return w.includes(e)?e:void 0}function q(n){let{cveName:t,purls:e,status:r,impactStatement:i,actionStatement:o,statusNotes:s,justification:a,timestamp:c=new Date().toISOString(),autoVexMaxSeverity:u}=n,d={vulnerability:{name:t},timestamp:c,products:e.map(f=>({"@id":f})),status:r};return i&&(d.impact_statement=i),o&&(d.action_statement=o),u?d.status_notes=R(u):s&&(d.status_notes=s),a&&(d.justification=a),d}var pt="https://openvex.dev/ns/v0.2.0";function Q(n,t="conterra"){let r=`https://openvex.dev/docs/public/vex-${(0,Y.randomUUID)()}`,i=n.timestamp??new Date().toISOString();return{"@context":pt,"@id":r,author:t,timestamp:i,last_updated:i,version:1,statements:[n]}}function Z(n,t){let e=t.timestamp??new Date().toISOString();return{...n,last_updated:e,version:n.version+1,statements:[...n.statements,t]}}var I=require("fs/promises"),O=require("path");var tt=require("fs/promises"),L=require("path");async function A(n,t){for(let e of await(0,tt.readdir)(n,{withFileTypes:!0}))e.name.endsWith(".json")?await t(new V((0,L.resolve)(e.parentPath,e.name))):e.isDirectory()&&await A((0,L.resolve)(e.parentPath,e.name),t)}function et(n){let t=n.vulnerability.name;return new Set([t,...n.vulnerability.aliases??[]])}var V=class{constructor(t){this.location=t}location;_content=void 0;_exists=!1;get exists(){return this._exists}get content(){return this._content}set content(t){this._content=t,this._exists=t!==void 0}async read(){let t=await C(this.location);this._content=t??void 0,this._exists=this._content!==void 0}async write(){if(this._content===void 0)throw new Error(`Cannot write VexFile: content is undefined (${this.location})`);await(0,I.mkdir)((0,O.dirname)((0,O.resolve)(this.location)),{recursive:!0}),await G(this.location,this._content)}async delete(){await(0,I.unlink)(this.location),this._exists=!1}upsert(t,e){return this._content===void 0?(this._content=Q(t,e),this._exists=!0,{created:!0}):(this._content=Z(this._content,t),{created:!1})}addProductId(t,e){this.assertContentLoaded("addProductId");let r=!1;for(let i of this._content.statements){if(!i.products||i.products.some(s=>s["@id"]===e))continue;let o=i.products.findIndex(s=>s["@id"]===t);o!==-1&&(i.products.splice(o+1,0,{"@id":e}),r=!0)}return r}removeProductId(t,e){this.assertContentLoaded("removeProductId");let r=this._content.statements,i=[],o=!1;for(let s of r){if(e&&!et(s).has(e)||!s.products)continue;let a=s.products.findIndex(c=>c["@id"]===t);a!==-1&&(s.products.splice(a,1),o=!0,s.products.length===0&&i.push(s))}if(!o)return"unchanged";for(let s of i)r.splice(r.indexOf(s),1);return r.length===0?"emptied":"changed"}hasStatementForProduct(t){return this.assertContentLoaded("hasStatementForProduct"),this._content.statements.some(e=>e.products?.some(r=>r["@id"]===t)??!1)}assertContentLoaded(t){if(this._content===void 0)throw new Error(`VexFile.${t}(): content is not loaded. Call read() first (${this.location})`)}};var gt="HIGH";async function nt(n){let{scanSummaryPath:t,autoVexConfigPath:e,vexDir:r,dryRun:i=!1,writeMissingMarker:o=!1}=n,s=new P(process.cwd()),[a,c,u]=await Promise.all([vt(t),s.loadProjectConfig(),s.loadAutoVexConfig(e)]),d=new Map(c.projects.map(l=>[`${l.name}@${l.version}`,l.purl])),f=u.maxSeverity??gt,b=u.subDir??"auto",v=(0,M.resolve)(r,b),m={created:[],updated:[],invalidated:[],markersWritten:[],errors:[]};if(o)return await yt(v,f,i,m),m;await ht(v,a,d,f,i,m);for(let[l,x]of Object.entries(a.vulnerabilities))try{if(!N(x.severity,f)){console.log(`[skip] ${l}: severity ${x.severity} is not below ${f}`);continue}let h=(0,M.resolve)(v,`${l}.json`),S=a.vulnerabilityToProject[l]??[];if(S.length===0){console.warn(`[warn] ${l}: no affected projects found in summary, skipping`);continue}let p=[];for(let W of S){let H=d.get(W);H===void 0?console.warn(`[warn] ${l}: project "${W}" not found in vuln-scan-conf.json, skipping product`):p.push(H)}if(p.length===0){console.warn(`[warn] ${l}: no resolvable project PURLs, skipping`);continue}if(i){console.log(`[dry-run] Would write auto VEX for ${l} (severity: ${x.severity}) \u2192 ${h}`),console.log(` Affected projects: ${p.join(", ")}`),m.created.push(l);continue}let E=new Date().toISOString(),X=q({cveName:l,purls:p,status:"not_affected",impactStatement:u.impactStatement,timestamp:E,autoVexMaxSeverity:f}),D=new V(h);await D.read();let{created:B}=D.upsert(X,u.author);await D.write(),console.log(`${B?"[created]":"[updated]"} Auto VEX for ${l} -> ${h}`),B?m.created.push(l):m.updated.push(l)}catch(h){let S=`Failed to process ${l}: ${String(h)}`;console.error(`[error] ${S}`),m.errors.push(S)}return m}async function vt(n){let t=await(0,rt.readFile)(n,"utf8");return JSON.parse(t)}async function ht(n,t,e,r,i,o){let s=St(t,e);try{await A(n,async a=>{if(await a.read(),!a.content)return;let u=a.content.statements.slice(),d=new Set,f=!1,b=!1;for(let v of u){if(b)break;let m=$(v)??r,l=v.vulnerability.name,x=s.get(l);if(!x)continue;let h=[];for(let S of v.products??[]){let p=S["@id"];if(!p)continue;let E=x.get(p);E!==void 0&&(N(E,m)||(h.push(p),console.log(`${i?"[dry-run]":"[invalidated]"} ${l}: severity ${E} on ${p} is not below recorded ${m}`)))}if(h.length!==0){if(d.add(l),i){f=!0;continue}for(let S of h){let p=a.removeProductId(S,l);p==="emptied"?(b=!0,f=!0):p==="changed"&&(f=!0)}}}if(d.size>0){let v=new Set(o.invalidated);for(let m of d)v.has(m)||o.invalidated.push(m)}i||!f||(b?(await a.delete(),console.log(`[invalidated] removed empty auto VEX file ${a.location}`)):await a.write())})}catch(a){if(a.code!=="ENOENT"){let c=`Auto-VEX invalidation pass failed: ${String(a)}`;console.error(`[error] ${c}`),o.errors.push(c)}}}function St(n,t){let e=new Map;for(let[r,i]of Object.entries(n.vulnerabilities)){let o=n.vulnerabilityToProject[r]??[],s=new Map;for(let a of o){let c=t.get(a);c&&s.set(c,i.severity)}s.size>0&&e.set(r,s)}return e}async function yt(n,t,e,r){let i=R(t);try{await A(n,async o=>{if(await o.read(),!o.content)return;let s=!1,a=0,c=0;for(let d of o.content.statements)if($(d)===void 0){if(d.status_notes){c++;continue}e||(d.status_notes=i),a++,s=!0}c>0&&console.warn(`[warn] ${o.location}: skipped ${c} statement(s) with non-marker status_notes`),!(!s||(r.markersWritten.push(o.location),console.log(`${e?"[dry-run]":"[marker-added]"} ${o.location}: stamped ${a} statement(s) with ${i}`),e))&&(o.content.version+=1,o.content.last_updated=new Date().toISOString(),await o.write())})}catch(o){if(o.code!=="ENOENT"){let s=`Auto-VEX marker backfill failed: ${String(o)}`;console.error(`[error] ${s}`),r.errors.push(s)}}}var U={flag:"--dry-run",description:"Print what would happen without making changes"},j=class{specs;booleanSpecs;commandName;helpLines;constructor(t,e,r=[],i=[]){this.commandName=t,this.specs=e;let o=i.some(s=>s.flag===U.flag);this.booleanSpecs=o?i:[...i,U],this.helpLines=r}parse(t){let e=t.slice(2),r=new Map(this.specs.map(o=>[o.flag,o.defaultValue])),i=new Map(this.booleanSpecs.map(o=>[o.flag,!1]));for(let o=0;o<e.length;o++){let s=e[o];(s==="--help"||s==="-h")&&(this.printHelp(),process.exit(0));let a=this.booleanSpecs.find(u=>u.flag===s||u.alias===s);if(a){i.set(a.flag,!0);continue}let c=this.specs.find(u=>u.flag===s||u.alias===s);c&&e[o+1]?r.set(c.flag,e[++o]):(console.error(`Unknown argument: ${s}`),this.printHelp(),process.exit(1))}return{values:r,dryRun:i.get(U.flag)===!0,booleans:i}}printHelp(){let t=this.specs.map(r=>` ${(r.alias?`${r.alias}, ${r.flag} <path>`:` ${r.flag} <path>`).padEnd(38)}${r.description}
4
- ${"".padEnd(42)}(default: ${r.defaultValue})`),e=this.booleanSpecs.map(r=>` ${(r.alias?`${r.alias}, ${r.flag}`:` ${r.flag}`).padEnd(38)}${r.description}`);console.log([`Usage: ${this.commandName} [options]`,"","Options:",...t,...e," -h, --help"+" ".repeat(32)+"Show this help message",...this.helpLines].join(`
5
- `))}};var wt=new j("ct-vuln-auto-vex",[{flag:"--auto-vex-config",alias:"-c",description:"Path to auto-vex-conf.json configuration file",defaultValue:(0,k.join)(process.cwd(),"auto-vex-conf.json")},{flag:"--summary",alias:"-s",description:"Path to scan-summary.json produced by ct-vuln-scan",defaultValue:(0,k.join)(process.cwd(),"output","scan-summary.json")}],["","Configuration (auto-vex-conf.json):"," impactStatement Required. Text written as impact_statement in each VEX statement."," maxSeverity Optional. Exclusive severity threshold. CVEs with a severity"," strictly below this level receive an auto-generated statement."," Values: UNKNOWN | LOW | MEDIUM | HIGH | CRITICAL (default: HIGH)"," author Optional. Author field in the OpenVEX document (default: conterra)"," subDir Optional. Sub-directory of vexDir for auto files (default: auto)"],[{flag:"--write-missing-marker",description:"Backfill auto_vex_max_severity into auto VEX statements that lack it, then exit"}]);(async()=>{let{values:n,dryRun:t,booleans:e}=wt.parse(process.argv),r=n.get("--auto-vex-config"),i=n.get("--summary"),o=e.get("--write-missing-marker")===!0,s=process.cwd();console.log(`Auto VEX Creator${o?" [write-missing-marker]":t?" [dry-run]":""}`),console.log(` auto-vex-config: ${r}`),console.log(` summary: ${i}`),console.log("");try{let c=await new P(s).loadProjectConfig(),u=await nt({scanSummaryPath:i,autoVexConfigPath:r,vexDir:c.vexDir,dryRun:t,writeMissingMarker:o});console.log(""),console.log("=== Auto VEX Creator Summary ==="),o?console.log(` Files stamped : ${u.markersWritten.length}`):(console.log(` Created : ${u.created.length}`),console.log(` Updated : ${u.updated.length}`),console.log(` Invalidated : ${u.invalidated.length}`)),console.log(` Errors : ${u.errors.length}`),u.errors.length>0&&(process.exitCode=1)}catch(c){console.error(`Fatal error: ${String(c)}`),process.exit(1)}})();
2
+ "use strict";var Ce=Object.create;var pe=Object.defineProperty;var Oe=Object.getOwnPropertyDescriptor;var ke=Object.getOwnPropertyNames;var Ne=Object.getPrototypeOf,Ie=Object.prototype.hasOwnProperty;var Te=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of ke(e))!Ie.call(t,o)&&o!==r&&pe(t,o,{get:()=>e[o],enumerable:!(n=Oe(e,o))||n.enumerable});return t};var me=(t,e,r)=>(r=t!=null?Ce(Ne(t)):{},Te(e||!t||!t.__esModule?pe(r,"default",{value:t,enumerable:!0}):r,t));var ue=require("path");var C=me(require("path")),ne=require("fs/promises");var w=require("fs/promises");async function H(t){try{return await _e(t)?JSON.parse(await(0,w.readFile)(t,{encoding:"utf-8"})):void 0}catch(e){throw new Error(`Error reading JSON file ${t}: ${e}`,{cause:e})}}async function ge(t,e){let r=JSON.stringify(e,null,4)+`
3
+ `,n=await De(t,r);await(0,w.writeFile)(t,n,{encoding:"utf-8"})}async function _e(t){try{return await(0,w.access)(t,w.constants.F_OK),!0}catch{return!1}}async function De(t,e){let r=await Re();if(!r)return e;let n=await r.resolveConfig(t);return n?await r.format(e,{...n,filepath:t}):e}var Fe;function Re(){return Fe??=import("prettier").catch(()=>{})}var W={UNKNOWN:0,LOW:1,MEDIUM:2,HIGH:3,CRITICAL:4},P=["UNKNOWN","LOW","MEDIUM","HIGH","CRITICAL"];function U(t,e){return W[t]-W[e]}function J(t,e){return W[t]<W[e]}var ie=class t{constructor(e){this.workingDir=e}workingDir;static DEFAULT_MAVEN_REPO="https://repository.conterra.de/repository/maven-mirror-ct";static DEFAULT_VEX_SUBDIR="input/vex";static DEFAULT_OUT_SUBDIR="output";static DEFAULT_CACHE_SUBDIR="cache";static DEFAULT_SCANNERS=["grype","trivy","ossindex"];normalize(e,r){let n=e.findNoLongerDetectedVulnerabilitiesOnlyForSnapshots??!1;return{projectConfigFileLocation:r,onNewVulnerabilities:e.onNewVulnerabilities??(e.failOnNewVulnerabilities?"fail":"warn"),onNoLongerDetectedVulnerabilities:e.onNoLongerDetectedVulnerabilities??"ignore",reportNoLongerDetectedVulnerabilities:e.reportNoLongerDetectedVulnerabilities??!0,consoleReport:e.consoleReport??"BY_PROJECT_DETAILED",createSubDirsForProject:e.createSubDirsForProject??!0,mavenRepo:e.mavenRepo??t.DEFAULT_MAVEN_REPO,vexUrls:e.vexUrls??[],vexDir:this.resolvePath(e.vexDir)??(0,C.resolve)(this.workingDir,t.DEFAULT_VEX_SUBDIR),outDir:this.resolvePath(e.outDir)??(0,C.resolve)(this.workingDir,t.DEFAULT_OUT_SUBDIR),cacheDir:this.resolvePath(e.cacheDir)??(0,C.resolve)(this.workingDir,t.DEFAULT_CACHE_SUBDIR),scanners:this.normalizeScanners(e.scanners,r),projects:this.normalizeProjects(e.projects??[],n)}}normalizeScanners(e,r){return(e??t.DEFAULT_SCANNERS).map(o=>{if(typeof o!="string")throw new Error(`Invalid scanner name '${String(o)}' in configuration file '${r}'`);let i=o.split("@");if(i.length>2)throw new Error(`Invalid scanner name '${o}' in configuration file '${r}'`);return{name:i[0],version:i[1]??""}})}normalizeProjects(e,r){return e.map(n=>{let o=n;if(!o.name)throw new Error("Project name is missing on entry: "+JSON.stringify(o));if(!o.version)throw new Error("Project version is missing on entry: "+JSON.stringify(o));if(!o.purl)throw new Error("Project purl is missing on entry: "+JSON.stringify(o));let i={...o,purlAliases:o.purlAliases??[],enabled:o.enabled??!0,silent:o.silent??!1,minimumSeverity:o.minimumSeverity??"UNKNOWN"};return i.sbomFile?{...i,sbomFile:this.resolvePath(i.sbomFile)??i.sbomFile}:{...i,detectNoLongerUsedVulnerabilities:r?i.purl.endsWith("-SNAPSHOT"):!0}})}resolvePath(e){if(e)return C.default.isAbsolute(e)?e:(0,C.resolve)(this.workingDir,e)}},T=class{constructor(e){this.workingDir=e;this.normalizer=new ie(e)}workingDir;normalizer;projectConfigCache;async loadProjectConfig(){return this.projectConfigCache??=this.doLoadProjectConfig(),this.projectConfigCache}async doLoadProjectConfig(){let e=(0,C.resolve)(this.workingDir,"vuln-scan-conf.json"),r=await H(e);if(!r)throw new Error(`Missing project configuration file '${e}'`);return this.normalizer.normalize(r,e)}async loadJiraConfig(e){let r=await(0,ne.readFile)(e,"utf8"),n=JSON.parse(r);if(!n.issues&&n.issue&&(n.issues=n.issue),!n.jiraUrl||typeof n.jiraUrl!="string")throw new Error("jira-conf.json: missing or invalid 'jiraUrl' field");if(!Array.isArray(n.issues))throw new Error("jira-conf.json: missing or invalid 'issues' array");this.validateAutoCloseSeverity(n.autoCloseBelowSeverity,"jira-conf.json: invalid 'autoCloseBelowSeverity'");for(let[o,i]of n.issues.entries())if(i&&typeof i=="object"){let s=i;this.validateAutoCloseSeverity(s.autoCloseBelowSeverity,`jira-conf.json: invalid 'issues[${o}].autoCloseBelowSeverity'`),this.validateAutoCloseProjectOverrides(s.projectOverrides,`jira-conf.json: invalid 'issues[${o}].projectOverrides'`)}return n}validateAutoCloseSeverity(e,r){if(e!==void 0&&!P.includes(e))throw new Error(`${r} value '${String(e)}'. Must be one of: ${P.join(", ")}`)}validateAutoCloseProjectOverrides(e,r){if(e!==void 0){if(!Array.isArray(e))throw new Error(`${r}: must be an array`);for(let n=0;n<e.length;n++){let o=e[n],i=`${r}[${n}]`;if(o==null||typeof o!="object")throw new Error(`${i}: must be an object`);let s=o,u=s.projects;if(!Array.isArray(u)||u.length===0)throw new Error(`${i}.projects: must be a non-empty array of strings`);for(let l=0;l<u.length;l++){let c=u[l];if(typeof c!="string"||c.length===0)throw new Error(`${i}.projects[${l}]: must be a non-empty string`)}if(s.autoCloseBelowSeverity===void 0)throw new Error(`${i}.autoCloseBelowSeverity: is required`);if(this.validateAutoCloseSeverity(s.autoCloseBelowSeverity,`${i}.autoCloseBelowSeverity`),s.comment!==void 0&&typeof s.comment!="string")throw new Error(`${i}.comment: must be a string`)}}}async loadAutoVexConfig(e){let r=await(0,ne.readFile)(e,"utf8"),n=JSON.parse(r);if(!n.impactStatement||typeof n.impactStatement!="string")throw new Error("auto-vex-conf.json: missing or invalid 'impactStatement' field (must be a non-empty string)");if(n.maxSeverity!==void 0&&!P.includes(n.maxSeverity))throw new Error(`auto-vex-conf.json: invalid 'maxSeverity' value '${String(n.maxSeverity)}'. Must be one of: ${P.join(", ")}`);if(n.projectOverrides!==void 0){if(!Array.isArray(n.projectOverrides))throw new Error("auto-vex-conf.json: 'projectOverrides' must be an array");for(let[o,i]of n.projectOverrides.entries()){if(!i||typeof i!="object")throw new Error(`auto-vex-conf.json: 'projectOverrides[${o}]' must be an object`);let s=i;if(!Array.isArray(s.projects)||s.projects.length===0||!s.projects.every(u=>typeof u=="string"&&u.length>0))throw new Error(`auto-vex-conf.json: 'projectOverrides[${o}].projects' must be a non-empty array of non-empty strings`);if(!P.includes(s.maxSeverity))throw new Error(`auto-vex-conf.json: invalid 'projectOverrides[${o}].maxSeverity' value '${String(s.maxSeverity)}'. Must be one of: ${P.join(", ")}`)}}return n}};var Pe=require("fs/promises"),B=require("path");var ve=require("crypto");var oe="auto_vex_max_severity=";function se(t){return`${oe}${t}`}function k(t){let e=t.status_notes;if(!e||!e.startsWith(oe))return;let r=e.slice(oe.length).trim();return P.includes(r)?r:void 0}function he(t){let{cveName:e,purls:r,status:n,impactStatement:o,actionStatement:i,statusNotes:s,justification:u,timestamp:l=new Date().toISOString(),autoVexMaxSeverity:c}=t,g={vulnerability:{name:e},timestamp:l,products:r.map(y=>({"@id":y})),status:n};return o&&(g.impact_statement=o),i&&(g.action_statement=i),c?g.status_notes=se(c):s&&(g.status_notes=s),u&&(g.justification=u),g}var Me="https://openvex.dev/ns/v0.2.0";function ye(t,e="conterra"){let n=`https://openvex.dev/docs/public/vex-${(0,ve.randomUUID)()}`,o=t.timestamp??new Date().toISOString();return{"@context":Me,"@id":n,author:e,timestamp:o,last_updated:o,version:1,statements:[t]}}function Se(t,e){let r=e.timestamp??new Date().toISOString();return{...t,last_updated:r,version:t.version+1,statements:[...t.statements,e]}}var K=require("fs/promises"),G=require("path");var we=require("fs/promises"),ae=require("path");async function z(t,e){for(let r of await(0,we.readdir)(t,{withFileTypes:!0}))r.name.endsWith(".json")?await e(new _((0,ae.resolve)(r.parentPath,r.name))):r.isDirectory()&&await z((0,ae.resolve)(r.parentPath,r.name),e)}function xe(t){let e=t.vulnerability.name;return new Set([e,...t.vulnerability.aliases??[]])}var _=class{constructor(e){this.location=e}location;_content=void 0;_exists=!1;get exists(){return this._exists}get content(){return this._content}set content(e){this._content=e,this._exists=e!==void 0}async read(){let e=await H(this.location);this._content=e??void 0,this._exists=this._content!==void 0}async write(){if(this._content===void 0)throw new Error(`Cannot write VexFile: content is undefined (${this.location})`);await(0,K.mkdir)((0,G.dirname)((0,G.resolve)(this.location)),{recursive:!0}),await ge(this.location,this._content)}async delete(){await(0,K.unlink)(this.location),this._exists=!1}upsert(e,r){if(this._content===void 0)return this._content=ye(e,r),this._exists=!0,{created:!0,changed:!0};let n=k(e);if(n!==void 0){let o=this._content.statements.findIndex(i=>i.vulnerability.name===e.vulnerability.name&&i.status===e.status&&k(i)===n);if(o!==-1){let i=this._content.statements[o];return Le(i,e)?{created:!1,changed:!1}:(i.products=e.products,i.impact_statement=e.impact_statement,i.action_statement=e.action_statement,i.justification=e.justification,i.status_notes=e.status_notes,i.timestamp=e.timestamp,this._content.version+=1,this._content.last_updated=e.timestamp??new Date().toISOString(),{created:!1,changed:!0})}}return this._content=Se(this._content,e),{created:!1,changed:!0}}addProductId(e,r){this.assertContentLoaded("addProductId");let n=!1;for(let o of this._content.statements){if(!o.products||o.products.some(s=>s["@id"]===r))continue;let i=o.products.findIndex(s=>s["@id"]===e);i!==-1&&(o.products.splice(i+1,0,{"@id":r}),n=!0)}return n}removeProductId(e,r){this.assertContentLoaded("removeProductId");let n=this._content.statements,o=[],i=!1;for(let s of n){if(r&&!xe(s).has(r)||!s.products)continue;let u=s.products.findIndex(l=>l["@id"]===e);u!==-1&&(s.products.splice(u,1),i=!0,s.products.length===0&&o.push(s))}if(!i)return"unchanged";for(let s of o)n.splice(n.indexOf(s),1);return n.length===0?"emptied":"changed"}hasStatementForProduct(e){return this.assertContentLoaded("hasStatementForProduct"),this._content.statements.some(r=>r.products?.some(n=>n["@id"]===e)??!1)}assertContentLoaded(e){if(this._content===void 0)throw new Error(`VexFile.${e}(): content is not loaded. Call read() first (${this.location})`)}};function Le(t,e){return t.impact_statement!==e.impact_statement||t.action_statement!==e.action_statement||t.justification!==e.justification||t.status_notes!==e.status_notes?!1:Ue(t.products,e.products)}function Ue(t,e){let r=i=>Array.from(new Set((i??[]).map(s=>s["@id"]).filter(s=>typeof s=="string"))).sort(),n=r(t),o=r(e);return n.length!==o.length?!1:n.every((i,s)=>i===o[s])}function Be(t){return t.replace(/[.+?^${}()|[\]\\]/g,"\\$&")}function Xe(t,e){let r=e.split("*").map(Be).join(".*");return new RegExp(`^${r}$`).test(t)}function be(t,e){return e.some(r=>Xe(t,r))}function Ee(t){return t.created.length===0&&t.updated.length===0&&t.invalidated.length===0&&t.revokedProducts===0&&t.filesRemoved===0&&t.skipped.atOrAboveThreshold.length===0&&t.skipped.noEligibleProject.length===0&&t.skipped.partial.length===0&&t.markersWritten.length===0&&t.warnings.length===0&&t.errors.length===0}var He="HIGH";function je(t){if(t.kind==="default")return"default";let e=t.override,r=e.projects.join(", "),n=e.comment?`, comment: "${e.comment}"`:"";return`override [${r}]${n}`}var $e=10,We=" ".repeat($e);function Je(t){return`[${t}]`.padEnd($e," ")}function E(t,e,r=[]){let n=`${Je(t)}${e}`,o=t==="warn"||t==="error"?console.error:console.log;o(n);for(let i of r)o(`${We}${i}`)}var f={info(t,e=[]){E("info",t,e)},create(t,e=[]){E("create",t,e)},update(t,e=[]){E("update",t,e)},revoke(t,e=[]){E("revoke",t,e)},skip(t,e=[]){E("skip",t,e)},dryRun(t,e=[]){E("dry-run",t,e)},backfill(t,e=[]){E("backfill",t,e)},warn(t,e=[]){E("warn",t,e)},error(t,e=[]){E("error",t,e)},banner(t){let e="\u2500".repeat(Math.max(0,62-t.length-4));console.log(""),console.log(`\u2500\u2500 ${t} ${e}`)}};function N(t){let e=(0,B.relative)(process.cwd(),t);return e===""?".":e.startsWith("..")?t:e.split(/[\\/]/).join("/")}async function Ve(t){let{scanSummaryPath:e,autoVexConfigPath:r,vexDir:n,dryRun:o=!1,writeMissingMarker:i=!1}=t,s=new T(process.cwd()),[u,l,c]=await Promise.all([ze(e),s.loadProjectConfig(),s.loadAutoVexConfig(r)]),g=new Map(l.projects.map(a=>[`${a.name}@${a.version}`,a.purl])),y=c.maxSeverity??He,D=c.subDir??"auto",$=(0,B.resolve)(n,D),F=c.projectOverrides??[],V=a=>{let v={severity:y,source:{kind:"default"}};for(let p of F)be(a,p.projects)&&U(p.maxSeverity,v.severity)<0&&(v={severity:p.maxSeverity,source:{kind:"override",override:p}});return v},x=a=>V(a).severity,m={created:[],updated:[],invalidated:[],markersWritten:[],errors:[],warnings:[],skipped:{atOrAboveThreshold:[],noEligibleProject:[],partial:[]},revokedProducts:0,filesRemoved:0},R=(a,v=[])=>{f.warn(a,v),m.warnings.push(a)};if(i)return f.banner("Marker backfill"),await Ye($,y,o,m,R),m;f.banner("Invalidation pass"),await Ke($,u,g,y,x,o,m),f.banner("Statement creation");for(let[a,v]of Object.entries(u.vulnerabilities))try{let p=(0,B.resolve)($,`${a}.json`),b=u.vulnerabilityToProject[a]??[];if(b.length===0){f.skip(`${a}: no affected projects found in summary`),m.skipped.noEligibleProject.push(a);continue}let A=new Map,I=[],h=[],M=!1;for(let d of b){let S=g.get(d);if(S===void 0){R(`${a}: project "${d}" not found in vuln-scan-conf.json, skipping product`),M=!0;continue}let j=V(d);if(!J(v.severity,j.severity)){h.push({projectId:d,effective:j});continue}I.push({projectId:d,purl:S,effective:j});let O=A.get(j.severity);O===void 0?A.set(j.severity,[S]):O.includes(S)||O.push(S)}if(A.size===0){h.length>0?(f.skip(`${a}: severity ${v.severity} meets or exceeds threshold for every eligible project`,h.map(d=>`${d.projectId} -> ${d.effective.severity} (${je(d.effective.source)})`)),m.skipped.atOrAboveThreshold.push(a)):M?(f.skip(`${a}: no resolvable project PURLs (see [warn] above)`),m.skipped.noEligibleProject.push(a)):(f.skip(`${a}: no eligible projects`),m.skipped.noEligibleProject.push(a));continue}h.length>0&&m.skipped.partial.push(a);let le=Array.from(A.entries()).sort(([d],[S])=>U(d,S)),Y=le.map(([d,S])=>{let j=new Set(I.filter(L=>L.effective.severity===d).map(L=>L.effective.source.kind)),O=j.size===1?j.has("default")?" (default)":" (override)":" (mixed)";return`\u2022 max severity ${d}${O}: ${S.join(", ")}`}),Q=h.map(d=>`excluded: ${d.projectId} -> ${d.effective.severity} (${je(d.effective.source)})`);if(o){let d=h.length>0?` (partial: ${h.length} project(s) excluded)`:"";f.dryRun(`${a}${d} -> ${N(p)}`,[`severity=${v.severity}`,...Y,...Q]),m.created.push(a);continue}let Z=new _(p);await Z.read();let X=!1,ee=!1,de=!1,Ae=new Date().toISOString();for(let[d,S]of le){let j=he({cveName:a,purls:S,status:"not_affected",impactStatement:c.impactStatement,timestamp:Ae,autoVexMaxSeverity:d}),{created:O,changed:L}=Z.upsert(j,c.author);L&&(de=!0,O?X=!0:ee=!0)}let fe=h.length>0?` (partial: ${h.length} project(s) excluded)`:"";if(!de){f.skip(`${a}${fe} -> ${N(p)}: unchanged`,[`severity=${v.severity}`,...Y,...Q]);continue}await Z.write();let te=`${a}${fe} -> ${N(p)}`,re=[`severity=${v.severity}`,...Y,...Q];X&&ee?(f.create(te,re),f.update(`${a}: also updated existing statement(s)`)):X?f.create(te,re):f.update(te,re),X?m.created.push(a):ee&&m.updated.push(a)}catch(p){let b=`Failed to process ${a}: ${String(p)}`;f.error(b),m.errors.push(b)}return m}async function ze(t){let e=await(0,Pe.readFile)(t,"utf8");return JSON.parse(e)}async function Ke(t,e,r,n,o,i,s){let u=qe(e,r),l=Ge(r,o);try{await z(t,async c=>{if(await c.read(),!c.content)return;let y=c.content.statements.slice(),D=new Set,$=!1,F=!1;for(let V of y){if(F)break;let x=k(V)??n,m=V.vulnerability.name,R=u.get(m);if(!R)continue;let a=[];for(let v of V.products??[]){let p=v["@id"];if(!p)continue;let b=R.get(p);if(b===void 0)continue;let A=l.get(p),I=A!==void 0&&U(A,x)<0?A:x;if(!J(b,I)){a.push(p);let h=I===x?`severity ${b} meets or exceeds recorded threshold ${x}`:`severity ${b} meets or exceeds effective threshold ${I} (override stricter than recorded ${x})`,M=i?`would revoke ${m} on ${p}`:`revoked ${m} on ${p}`;i?f.dryRun(M,[h]):f.revoke(M,[h]),s.revokedProducts++}}if(a.length!==0){if(D.add(m),i){$=!0;continue}for(let v of a){let p=c.removeProductId(v,m);p==="emptied"?(F=!0,$=!0):p==="changed"&&($=!0)}}}if(D.size>0){let V=new Set(s.invalidated);for(let x of D)V.has(x)||s.invalidated.push(x)}i||!$||(F?(await c.delete(),s.filesRemoved++,f.revoke(`removed empty auto VEX file ${N(c.location)}`)):await c.write())})}catch(c){if(c.code!=="ENOENT"){let g=`Auto-VEX invalidation pass failed: ${String(c)}`;f.error(g),s.errors.push(g)}}}function Ge(t,e){let r=new Map;for(let[n,o]of t){let i=e(n),s=r.get(o);(s===void 0||U(i,s)<0)&&r.set(o,i)}return r}function qe(t,e){let r=new Map;for(let[n,o]of Object.entries(t.vulnerabilities)){let i=t.vulnerabilityToProject[n]??[],s=new Map;for(let u of i){let l=e.get(u);l&&s.set(l,o.severity)}s.size>0&&r.set(n,s)}return r}async function Ye(t,e,r,n,o){let i=se(e);try{await z(t,async s=>{if(await s.read(),!s.content)return;let u=!1,l=0,c=0;for(let y of s.content.statements)if(k(y)===void 0){if(y.status_notes){c++;continue}r||(y.status_notes=i),l++,u=!0}if(c>0&&o(`${N(s.location)}: skipped ${c} statement(s) that already have manual status notes`),!u)return;n.markersWritten.push(s.location);let g=r?`would stamp ${l} statement(s) in ${N(s.location)} with ${i}`:`${N(s.location)}: stamped ${l} statement(s) with ${i}`;r?f.dryRun(g):f.backfill(g),!r&&(s.content.version+=1,s.content.last_updated=new Date().toISOString(),await s.write())})}catch(s){if(s.code!=="ENOENT"){let u=`Auto-VEX marker backfill failed: ${String(s)}`;f.error(u),n.errors.push(u)}}}var ce={flag:"--dry-run",description:"Print what would happen without making changes"},q=class{specs;booleanSpecs;commandName;helpLines;constructor(e,r,n=[],o=[]){this.commandName=e,this.specs=r;let i=o.some(s=>s.flag===ce.flag);this.booleanSpecs=i?o:[...o,ce],this.helpLines=n}parse(e){let r=e.slice(2),n=new Map(this.specs.map(i=>[i.flag,i.defaultValue])),o=new Map(this.booleanSpecs.map(i=>[i.flag,!1]));for(let i=0;i<r.length;i++){let s=r[i];(s==="--help"||s==="-h")&&(this.printHelp(),process.exit(0));let u=this.booleanSpecs.find(c=>c.flag===s||c.alias===s);if(u){o.set(u.flag,!0);continue}let l=this.specs.find(c=>c.flag===s||c.alias===s);l&&r[i+1]?n.set(l.flag,r[++i]):(console.error(`Unknown argument: ${s}`),this.printHelp(),process.exit(1))}return{values:n,dryRun:o.get(ce.flag)===!0,booleans:o}}printHelp(){let e=this.specs.map(n=>` ${(n.alias?`${n.alias}, ${n.flag} <path>`:` ${n.flag} <path>`).padEnd(38)}${n.description}
4
+ ${"".padEnd(42)}(default: ${n.defaultValue})`),r=this.booleanSpecs.map(n=>` ${(n.alias?`${n.alias}, ${n.flag}`:` ${n.flag}`).padEnd(38)}${n.description}`);console.log([`Usage: ${this.commandName} [options]`,"","Options:",...e,...r," -h, --help"+" ".repeat(32)+"Show this help message",...this.helpLines].join(`
5
+ `))}};var Qe=new q("ct-vuln-auto-vex",[{flag:"--auto-vex-config",alias:"-c",description:"Path to auto-vex-conf.json configuration file",defaultValue:(0,ue.join)(process.cwd(),"auto-vex-conf.json")},{flag:"--summary",alias:"-s",description:"Path to scan-summary.json produced by ct-vuln-scan",defaultValue:(0,ue.join)(process.cwd(),"output","scan-summary.json")}],["","Configuration (auto-vex-conf.json):"," impactStatement Required. Text written as impact_statement in each VEX statement."," maxSeverity Optional. Exclusive severity threshold. CVEs with a severity"," strictly below this level receive an auto-generated statement."," Values: UNKNOWN | LOW | MEDIUM | HIGH | CRITICAL (default: HIGH)"," author Optional. Author field in the OpenVEX document (default: conterra)"," subDir Optional. Sub-directory of vexDir for auto files (default: auto)"],[{flag:"--write-missing-marker",description:"Backfill auto_vex_max_severity into auto VEX statements that lack it, then exit"}]);(async()=>{let{values:t,dryRun:e,booleans:r}=Qe.parse(process.argv),n=t.get("--auto-vex-config"),o=t.get("--summary"),i=r.get("--write-missing-marker")===!0,s=process.cwd();console.log(`Auto VEX Creator${i?" [write-missing-marker]":e?" [dry-run]":""}`);try{let l=await new T(s).loadProjectConfig(),c=await Ve({scanSummaryPath:o,autoVexConfigPath:n,vexDir:l.vexDir,dryRun:e,writeMissingMarker:i});Ee(c)&&console.log("[info] nothing to do"),e&&(console.log(""),console.log("No files were written (dry-run). Re-run without --dry-run to apply.")),c.errors.length>0&&(process.exitCode=1)}catch(l){console.error(`Fatal error: ${String(l)}`),process.exit(1)}})();
@@ -1,9 +1,14 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var fe=Object.create;var W=Object.defineProperty;var me=Object.getOwnPropertyDescriptor;var ge=Object.getOwnPropertyNames;var he=Object.getPrototypeOf,ye=Object.prototype.hasOwnProperty;var we=(o,e,n,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of ge(e))!ye.call(o,r)&&r!==n&&W(o,r,{get:()=>e[r],enumerable:!(t=me(e,r))||t.enumerable});return o};var Se=(o,e,n)=>(n=o!=null?fe(he(o)):{},we(e||!o||!o.__esModule?W(n,"default",{value:o,enumerable:!0}):n,o));var V=require("path"),le=require("zx");var ie=require("fs/promises");var H={UNKNOWN:0,LOW:1,MEDIUM:2,HIGH:3,CRITICAL:4},v=["UNKNOWN","LOW","MEDIUM","HIGH","CRITICAL"];function E(o,e){return H[o]<H[e]}function b(...o){return{type:"doc",version:1,content:o}}function h(o,e){return{type:"heading",attrs:{level:o},content:[{type:"text",text:e}]}}function T(o,e="text"){return{type:"codeBlock",attrs:{language:e},content:[{type:"text",text:o}]}}function z(o){return{type:"bulletList",content:o.map(e=>({type:"listItem",content:[{type:"paragraph",content:[{type:"text",text:e}]}]}))}}function G(o){return{type:"bulletList",content:o.map(e=>({type:"listItem",content:[{type:"paragraph",content:[{type:"text",text:e,marks:[{type:"link",attrs:{href:e}}]}]}]}))}}function I(o,...e){return{type:"expand",attrs:{title:o},content:e}}function p(o){return{type:"paragraph",content:[{type:"text",text:o,marks:[{type:"em"}]}]}}var u=require("fs/promises");async function X(o){try{return await ve(o)?JSON.parse(await(0,u.readFile)(o,{encoding:"utf-8"})):void 0}catch(e){throw new Error(`Error reading JSON file ${o}: ${e}`,{cause:e})}}async function ve(o){try{return await(0,u.access)(o,u.constants.F_OK),!0}catch{return!1}}function q(o,e){return`Basic ${Buffer.from(`${o}:${e}`).toString("base64")}`}var N=class{authHeader;baseUrl;constructor(e,n,t){this.baseUrl=e.replace(/\/$/,""),this.authHeader=q(n,t)}get headers(){return{Authorization:this.authHeader,"Content-Type":"application/json",Accept:"application/json"}}async safeJson(e,n){let t=await e.text();try{return JSON.parse(t)}catch{let r=t.slice(0,500).replace(/\s+/g," ").trim();throw new Error(`${n}: expected JSON but got (HTTP ${e.status}): ${r}`)}}async findExistingIssue(e,n){let t=e.replace(/"/g,'\\"'),r=n.replace(/"/g,'\\"'),s=`project = "${t}" AND summary ~ "\\"${r}\\""`,a=`${this.baseUrl}/rest/api/3/search/jql?jql=${encodeURIComponent(s)}&maxResults=1&fields=summary,labels,status`,i=await fetch(a,{method:"GET",headers:this.headers});if(!i.ok){let d=await i.text();throw new Error(`Jira search failed (${i.status}): ${d}`)}let c=(await this.safeJson(i,"Jira search")).issues[0];return c?{key:c.key,summary:c.fields?.summary??"",labels:c.fields?.labels??[],statusCategory:c.fields?.status?.statusCategory?.key??"new"}:null}async createIssue(e){let n={project:{key:e.projectKey},issuetype:{name:e.issueType},summary:e.summary,description:e.description};e.labels&&e.labels.length>0&&(n.labels=e.labels),e.sprintId!=null&&(n.customfield_10020=e.sprintId);let t={fields:n},r=await fetch(`${this.baseUrl}/rest/api/3/issue`,{method:"POST",headers:this.headers,body:JSON.stringify(t)});if(!r.ok){let a=await r.text();throw new Error(`Jira create issue failed (${r.status}): ${a}`)}return(await this.safeJson(r,"Jira create issue")).key}async addLabels(e,n){if(n.length===0)return;let t={update:{labels:n.map(s=>({add:s}))}},r=await fetch(`${this.baseUrl}/rest/api/3/issue/${e}`,{method:"PUT",headers:this.headers,body:JSON.stringify(t)});if(!r.ok){let s=await r.text();throw new Error(`Jira add labels failed (${r.status}): ${s}`)}}async updateIssueSummary(e,n){let t={fields:{summary:n}},r=await fetch(`${this.baseUrl}/rest/api/3/issue/${e}`,{method:"PUT",headers:this.headers,body:JSON.stringify(t)});if(!r.ok){let s=await r.text();throw new Error(`Jira update summary failed (${r.status}): ${s}`)}}async setSprint(e,n){let t={fields:{customfield_10020:n}},r=await fetch(`${this.baseUrl}/rest/api/3/issue/${e}`,{method:"PUT",headers:this.headers,body:JSON.stringify(t)});if(!r.ok){let s=await r.text();throw new Error(`Jira set sprint failed (${r.status}): ${s}`)}}async addComment(e,n){let t=await fetch(`${this.baseUrl}/rest/api/3/issue/${e}/comment`,{method:"POST",headers:this.headers,body:JSON.stringify({body:n})});if(!t.ok){let r=await t.text();throw new Error(`Jira add comment failed (${t.status}): ${r}`)}}async getTransitions(e){let n=await fetch(`${this.baseUrl}/rest/api/3/issue/${e}/transitions`,{method:"GET",headers:this.headers});if(!n.ok){let r=await n.text();throw new Error(`Jira get transitions failed (${n.status}): ${r}`)}return(await this.safeJson(n,"Jira transitions lookup")).transitions.map(r=>({id:r.id,name:r.name,toStatusName:r.to?.name??"",toStatusCategory:r.to?.statusCategory?.key??""}))}async transitionIssue(e,n){let t=await fetch(`${this.baseUrl}/rest/api/3/issue/${e}/transitions`,{method:"POST",headers:this.headers,body:JSON.stringify({transition:{id:n}})});if(!t.ok){let r=await t.text();throw new Error(`Jira transition issue failed (${t.status}): ${r}`)}}async attachMarkdown(e,n,t){let r=`${this.baseUrl}/rest/api/3/issue/${e}/attachments`,s=new FormData;s.append("file",new Blob([t],{type:"text/markdown"}),n);let a=await fetch(r,{method:"POST",headers:{Authorization:this.authHeader,"X-Atlassian-Token":"no-check"},body:s});if(!a.ok){let i=await a.text();throw new Error(`Jira attach file failed (${a.status}): ${i}`)}}async getActiveSprintId(e){let n=`${this.baseUrl}/rest/agile/1.0/board/${e}/sprint?state=active&maxResults=1`,t=await fetch(n,{method:"GET",headers:this.headers});if(!t.ok){let s=await t.text();throw new Error(`Jira agile sprint lookup failed (${t.status}): ${s}`)}return(await this.safeJson(t,"Jira sprint lookup")).values[0]?.id??null}};function be(o){return o.replace(/[.+?^${}()|[\]\\]/g,"\\$&")}function Ce(o,e){let n=e.split("*").map(be).join(".*");return new RegExp(`^${n}$`).test(o)}function J(o,e){return e.some(n=>Ce(o,n))}function Y(o,e=""){return Z(o,e,new Set,new Set)}function Z(o,e="",n,t){let r=`${e}- ${o.purl}`;if(n.has(o.purl))return r+=" (cycle detected)",r;if(t.has(o.purl))return r+=" (deduplicated)",r;t.add(o.purl),n.add(o.purl);let s=n.size===1;for(let a of o.usedBy){let i=Z(a,e+(s?" ":" "),n,t);i!==""&&(r+=`
3
- `,r+=i)}return n.delete(o.purl),r}function K(o){let e=o.split(/\r?\n/),n=[],t=0;for(;t<e.length;){let r=e[t],s=r.match(/^```(\w*)$/);if(s){let l=s[1]??"text",c=[];for(t++;t<e.length&&!e[t].startsWith("```");)c.push(e[t]),t++;t++,n.push(T(c.join(`
4
- `),l));continue}let a=r.match(/^(#{1,3})\s+(.+)$/);if(a){let l=Math.min(a[1].length,3);n.push({type:"heading",attrs:{level:l},content:[{type:"text",text:a[2].trim()}]}),t++;continue}if(/^[-*]\s/.test(r)){let l=[];for(;t<e.length&&/^[-*]\s/.test(e[t]);){let c=e[t].replace(/^[-*]\s+/,"");l.push({type:"listItem",content:[{type:"paragraph",content:L(c)}]}),t++}n.push({type:"bulletList",content:l});continue}if(/^\d+\.\s/.test(r)){let l=[];for(;t<e.length&&/^\d+\.\s/.test(e[t]);){let c=e[t].replace(/^\d+\.\s+/,"");l.push({type:"listItem",content:[{type:"paragraph",content:L(c)}]}),t++}n.push({type:"orderedList",content:l});continue}if(r.trim()===""){t++;continue}let i=[];for(;t<e.length&&e[t].trim()!==""&&!/^(#{1,3}\s|[-*]\s|\d+\.\s|```)/.test(e[t]);)i.push(e[t]),t++;if(i.length>0){let l=[];for(let c=0;c<i.length;c++)l.push(...L(i[c])),c<i.length-1&&l.push({type:"hardBreak"});n.push({type:"paragraph",content:l})}}return n}function L(o){let e=[],n=/(\*\*(.+?)\*\*|\*(.+?)\*|`(.+?)`|_(.+?)_)/g,t=0,r;for(;(r=n.exec(o))!==null;)r.index>t&&e.push({type:"text",text:o.slice(t,r.index)}),r[2]!==void 0?e.push({type:"text",text:r[2],marks:[{type:"strong"}]}):r[3]!==void 0?e.push({type:"text",text:r[3],marks:[{type:"em"}]}):r[4]!==void 0?e.push({type:"text",text:r[4],marks:[{type:"code"}]}):r[5]!==void 0&&e.push({type:"text",text:r[5],marks:[{type:"em"}]}),t=r.index+r[0].length;return t<o.length&&e.push({type:"text",text:o.slice(t)}),e.length>0?e:[{type:"text",text:o}]}var $e=2e4;function B(o){let e=o.title?`: ${o.title}`:"";return`[${o.severity}] ${o.id}${e}`}function Q(o){let e=o.match(/^\[([A-Z]+)\]\s+(\S+?)(?::\s*(.*))?$/);if(!e)return;let[,n,t,r]=e;if(!(!n||!t)&&v.includes(n))return{severity:n,vulnId:t,title:r??""}}function ee(o,e,n=new Map){let t=[];if(t.push(h(1,"Informationen zur Schwachstelle")),t.push(p("Diese Informationen wurden automatisch generiert.")),o.refs&&o.refs.length>0&&t.push(G(o.refs)),o.description){let r=K(o.description);t.push(I("Beschreibung",...r))}return t.push(h(2,"Betroffene Artefakte")),o.components&&o.components.length>0?t.push(z(o.components)):t.push(p("Keine Komponenten bekannt.")),t.push(h(2,"Gemeldet f\xFCr")),re(t,e,n),t.push(h(1,"Einwertung")),t.push(p("Einwertung des CVE in Bezug auf die gemeldeten Projekte/Produkte. Dies kann eine Bewertung der Schwere, der Auswirkungen und der Wahrscheinlichkeit eines Angriffs umfassen.")),t.push(h(1,"Betroffen sind")),t.push(p("Abschlie\xDFende Darstellung, welche Projekte/Produkte tats\xE4chlich betroffen oder nicht betroffen sind.")),t.push(h(1,"Ma\xDFnahmen")),t.push(p("\xDCbersicht der zu ergreifenden Ma\xDFnahmen, um den CVE zu beheben oder zu mitigieren. Dies kann Patches, Updates oder Konfigurations\xE4nderungen umfassen.")),b(...t)}function te(o,e=new Map){let n=[];return n.push(p("Diese Projekte sind ebenfalls von dieser Schwachstelle betroffen und wurden automatisch erg\xE4nzt.")),n.push(h(2,"Zus\xE4tzlich gemeldet f\xFCr")),re(n,o,e),b(...n)}function re(o,e,n){let t=0;for(let r of e.slice().sort()){o.push({type:"paragraph",content:[{type:"text",text:r,marks:[{type:"strong"}]}]});let s=n.get(r);if(s&&s.length>0){let a=oe(s);a&&(t+=a.length,t>$e?o.push(I("Verwendungsbaum",p("Gesamtgr\xF6\xDFe der Verwendungsb\xE4ume \xFCberschreitet Limit. Siehe Issue-Attachments f\xFCr vollst\xE4ndige B\xE4ume."))):o.push(I("Verwendungsbaum",T(a))))}}}function ne(o,e){if(e.size===0)return"";let n=[`# Verwendungsb\xE4ume f\xFCr ${o}`,""];for(let[t,r]of[...e.entries()].sort(([s],[a])=>s.localeCompare(a))){n.push(`## ${t}`,"");let s=oe(r);s&&n.push("```",s,"```"),n.push("")}return n.join(`
5
- `)}function oe(o){return!o||o.length===0?"":o.map(e=>Y(e,"")).join(`
2
+ "use strict";var Ne=Object.create;var re=Object.defineProperty;var Ee=Object.getOwnPropertyDescriptor;var Le=Object.getOwnPropertyNames;var Je=Object.getPrototypeOf,Be=Object.prototype.hasOwnProperty;var Oe=(o,e,r,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Le(e))!Be.call(o,n)&&n!==r&&re(o,n,{get:()=>e[n],enumerable:!(t=Ee(e,n))||t.enumerable});return o};var De=(o,e,r)=>(r=o!=null?Ne(Je(o)):{},Oe(e||!o||!o.__esModule?re(r,"default",{value:o,enumerable:!0}):r,o));var Q=require("path"),Te=require("zx");var be=require("fs/promises");var I={UNKNOWN:0,LOW:1,MEDIUM:2,HIGH:3,CRITICAL:4},y=["UNKNOWN","LOW","MEDIUM","HIGH","CRITICAL"];function V(o,e){return I[o]-I[e]}function k(o,e){return I[o]<I[e]}function C(...o){return{type:"doc",version:1,content:o}}function j(o,e){return{type:"heading",attrs:{level:o},content:[{type:"text",text:e}]}}function N(o,e="text"){return{type:"codeBlock",attrs:{language:e},content:[{type:"text",text:o}]}}function ne(o){return{type:"bulletList",content:o.map(e=>({type:"listItem",content:[{type:"paragraph",content:[{type:"text",text:e}]}]}))}}function oe(o){return{type:"bulletList",content:o.map(e=>({type:"listItem",content:[{type:"paragraph",content:[{type:"text",text:e,marks:[{type:"link",attrs:{href:e}}]}]}]}))}}function E(o,...e){return{type:"expand",attrs:{title:o},content:e}}function h(o){return{type:"paragraph",content:[{type:"text",text:o,marks:[{type:"em"}]}]}}var m=require("fs/promises");async function se(o){try{return await Ue(o)?JSON.parse(await(0,m.readFile)(o,{encoding:"utf-8"})):void 0}catch(e){throw new Error(`Error reading JSON file ${o}: ${e}`,{cause:e})}}async function Ue(o){try{return await(0,m.access)(o,m.constants.F_OK),!0}catch{return!1}}function ie(o,e){return`Basic ${Buffer.from(`${o}:${e}`).toString("base64")}`}var L=class{authHeader;baseUrl;constructor(e,r,t){this.baseUrl=e.replace(/\/$/,""),this.authHeader=ie(r,t)}get headers(){return{Authorization:this.authHeader,"Content-Type":"application/json",Accept:"application/json"}}async safeJson(e,r){let t=await e.text();try{return JSON.parse(t)}catch{let n=t.slice(0,500).replace(/\s+/g," ").trim();throw new Error(`${r}: expected JSON but got (HTTP ${e.status}): ${n}`)}}async findExistingIssue(e,r){let t=e.replace(/"/g,'\\"'),n=r.replace(/"/g,'\\"'),s=`project = "${t}" AND summary ~ "\\"${n}\\""`,i=`${this.baseUrl}/rest/api/3/search/jql?jql=${encodeURIComponent(s)}&maxResults=1&fields=summary,labels,status`,c=await fetch(i,{method:"GET",headers:this.headers});if(!c.ok){let d=await c.text();throw new Error(`Jira search failed (${c.status}): ${d}`)}let l=(await this.safeJson(c,"Jira search")).issues[0];return l?{key:l.key,summary:l.fields?.summary??"",labels:l.fields?.labels??[],statusCategory:l.fields?.status?.statusCategory?.key??"new"}:null}async createIssue(e){let r={project:{key:e.projectKey},issuetype:{name:e.issueType},summary:e.summary,description:e.description};e.labels&&e.labels.length>0&&(r.labels=e.labels),e.sprintId!=null&&(r.customfield_10020=e.sprintId);let t={fields:r},n=await fetch(`${this.baseUrl}/rest/api/3/issue`,{method:"POST",headers:this.headers,body:JSON.stringify(t)});if(!n.ok){let i=await n.text();throw new Error(`Jira create issue failed (${n.status}): ${i}`)}return(await this.safeJson(n,"Jira create issue")).key}async addLabels(e,r){if(r.length===0)return;let t={update:{labels:r.map(s=>({add:s}))}},n=await fetch(`${this.baseUrl}/rest/api/3/issue/${e}`,{method:"PUT",headers:this.headers,body:JSON.stringify(t)});if(!n.ok){let s=await n.text();throw new Error(`Jira add labels failed (${n.status}): ${s}`)}}async updateIssueSummary(e,r){let t={fields:{summary:r}},n=await fetch(`${this.baseUrl}/rest/api/3/issue/${e}`,{method:"PUT",headers:this.headers,body:JSON.stringify(t)});if(!n.ok){let s=await n.text();throw new Error(`Jira update summary failed (${n.status}): ${s}`)}}async setSprint(e,r){let t={fields:{customfield_10020:r}},n=await fetch(`${this.baseUrl}/rest/api/3/issue/${e}`,{method:"PUT",headers:this.headers,body:JSON.stringify(t)});if(!n.ok){let s=await n.text();throw new Error(`Jira set sprint failed (${n.status}): ${s}`)}}async addComment(e,r){let t=await fetch(`${this.baseUrl}/rest/api/3/issue/${e}/comment`,{method:"POST",headers:this.headers,body:JSON.stringify({body:r})});if(!t.ok){let n=await t.text();throw new Error(`Jira add comment failed (${t.status}): ${n}`)}}async getTransitions(e){let r=await fetch(`${this.baseUrl}/rest/api/3/issue/${e}/transitions`,{method:"GET",headers:this.headers});if(!r.ok){let n=await r.text();throw new Error(`Jira get transitions failed (${r.status}): ${n}`)}return(await this.safeJson(r,"Jira transitions lookup")).transitions.map(n=>({id:n.id,name:n.name,toStatusName:n.to?.name??"",toStatusCategory:n.to?.statusCategory?.key??""}))}async transitionIssue(e,r){let t=await fetch(`${this.baseUrl}/rest/api/3/issue/${e}/transitions`,{method:"POST",headers:this.headers,body:JSON.stringify({transition:{id:r}})});if(!t.ok){let n=await t.text();throw new Error(`Jira transition issue failed (${t.status}): ${n}`)}}async attachMarkdown(e,r,t){let n=`${this.baseUrl}/rest/api/3/issue/${e}/attachments`,s=new FormData;s.append("file",new Blob([t],{type:"text/markdown"}),r);let i=await fetch(n,{method:"POST",headers:{Authorization:this.authHeader,"X-Atlassian-Token":"no-check"},body:s});if(!i.ok){let c=await i.text();throw new Error(`Jira attach file failed (${i.status}): ${c}`)}}async getActiveSprintId(e){let r=`${this.baseUrl}/rest/agile/1.0/board/${e}/sprint?state=active&maxResults=1`,t=await fetch(r,{method:"GET",headers:this.headers});if(!t.ok){let s=await t.text();throw new Error(`Jira agile sprint lookup failed (${t.status}): ${s}`)}return(await this.safeJson(t,"Jira sprint lookup")).values[0]?.id??null}};function Me(o){return o.replace(/[.+?^${}()|[\]\\]/g,"\\$&")}function Fe(o,e){let r=e.split("*").map(Me).join(".*");return new RegExp(`^${r}$`).test(o)}function J(o,e){return e.some(r=>Fe(o,r))}function ae(o,e=""){return ce(o,e,new Set,new Set)}function ce(o,e="",r,t){let n=`${e}- ${o.purl}`;if(r.has(o.purl))return n+=" (cycle detected)",n;if(t.has(o.purl))return n+=" (deduplicated)",n;t.add(o.purl),r.add(o.purl);let s=r.size===1;for(let i of o.usedBy){let c=ce(i,e+(s?" ":" "),r,t);c!==""&&(n+=`
3
+ `,n+=c)}return r.delete(o.purl),n}function le(o){let e=o.split(/\r?\n/),r=[],t=0;for(;t<e.length;){let n=e[t],s=n.match(/^```(\w*)$/);if(s){let a=s[1]??"text",l=[];for(t++;t<e.length&&!e[t].startsWith("```");)l.push(e[t]),t++;t++,r.push(N(l.join(`
4
+ `),a));continue}let i=n.match(/^(#{1,3})\s+(.+)$/);if(i){let a=Math.min(i[1].length,3);r.push({type:"heading",attrs:{level:a},content:[{type:"text",text:i[2].trim()}]}),t++;continue}if(/^[-*]\s/.test(n)){let a=[];for(;t<e.length&&/^[-*]\s/.test(e[t]);){let l=e[t].replace(/^[-*]\s+/,"");a.push({type:"listItem",content:[{type:"paragraph",content:_(l)}]}),t++}r.push({type:"bulletList",content:a});continue}if(/^\d+\.\s/.test(n)){let a=[];for(;t<e.length&&/^\d+\.\s/.test(e[t]);){let l=e[t].replace(/^\d+\.\s+/,"");a.push({type:"listItem",content:[{type:"paragraph",content:_(l)}]}),t++}r.push({type:"orderedList",content:a});continue}if(n.trim()===""){t++;continue}let c=[];for(;t<e.length&&e[t].trim()!==""&&!/^(#{1,3}\s|[-*]\s|\d+\.\s|```)/.test(e[t]);)c.push(e[t]),t++;if(c.length>0){let a=[];for(let l=0;l<c.length;l++)a.push(..._(c[l])),l<c.length-1&&a.push({type:"hardBreak"});r.push({type:"paragraph",content:a})}}return r}function _(o){let e=[],r=/(\*\*(.+?)\*\*|\*(.+?)\*|`(.+?)`|_(.+?)_)/g,t=0,n;for(;(n=r.exec(o))!==null;)n.index>t&&e.push({type:"text",text:o.slice(t,n.index)}),n[2]!==void 0?e.push({type:"text",text:n[2],marks:[{type:"strong"}]}):n[3]!==void 0?e.push({type:"text",text:n[3],marks:[{type:"em"}]}):n[4]!==void 0?e.push({type:"text",text:n[4],marks:[{type:"code"}]}):n[5]!==void 0&&e.push({type:"text",text:n[5],marks:[{type:"em"}]}),t=n.index+n[0].length;return t<o.length&&e.push({type:"text",text:o.slice(t)}),e.length>0?e:[{type:"text",text:o}]}var Ve=2e4;function z(o){let e=o.title?`: ${o.title}`:"";return`[${o.severity}] ${o.id}${e}`}function de(o){let e=o.match(/^\[([A-Z]+)\]\s+(\S+?)(?::\s*(.*))?$/);if(!e)return;let[,r,t,n]=e;if(!(!r||!t)&&y.includes(r))return{severity:r,vulnId:t,title:n??""}}function ue(o,e,r=new Map){let t=[];if(t.push(j(1,"Informationen zur Schwachstelle")),t.push(h("Diese Informationen wurden automatisch generiert.")),o.refs&&o.refs.length>0&&t.push(oe(o.refs)),o.description){let n=le(o.description);t.push(E("Beschreibung",...n))}return t.push(j(2,"Betroffene Artefakte")),o.components&&o.components.length>0?t.push(ne(o.components)):t.push(h("Keine Komponenten bekannt.")),t.push(j(2,"Gemeldet f\xFCr")),ge(t,e,r),t.push(j(1,"Einwertung")),t.push(h("Einwertung des CVE in Bezug auf die gemeldeten Projekte/Produkte. Dies kann eine Bewertung der Schwere, der Auswirkungen und der Wahrscheinlichkeit eines Angriffs umfassen.")),t.push(j(1,"Betroffen sind")),t.push(h("Abschlie\xDFende Darstellung, welche Projekte/Produkte tats\xE4chlich betroffen oder nicht betroffen sind.")),t.push(j(1,"Ma\xDFnahmen")),t.push(h("\xDCbersicht der zu ergreifenden Ma\xDFnahmen, um den CVE zu beheben oder zu mitigieren. Dies kann Patches, Updates oder Konfigurations\xE4nderungen umfassen.")),C(...t)}function pe(o,e=new Map){let r=[];return r.push(h("Diese Projekte sind ebenfalls von dieser Schwachstelle betroffen und wurden automatisch erg\xE4nzt.")),r.push(j(2,"Zus\xE4tzlich gemeldet f\xFCr")),ge(r,o,e),C(...r)}function T(o){return o.slice().sort((e,r)=>e.projectId.localeCompare(r.projectId)).map(e=>` - ${e.projectId} (Schwelle ${e.threshold})`).join(`
5
+ `)}function fe(o,e){let r=[`Automatisch geschlossen: Schwere ${o} liegt unterhalb der konfigurierten Auto-Close-Schwelle.`];return e.length>0&&(r.push("Auto-akzeptiert f\xFCr:"),r.push(T(e))),C(h(r.join(`
6
+ `)))}function H(o,e,r){let t=[`Teilweise auto-akzeptiert. Schwere ${o}.`];return e.length>0&&(t.push("Auto-akzeptiert f\xFCr:"),t.push(T(e))),r.length>0&&(t.push("Manuelle Bewertung erforderlich f\xFCr:"),t.push(T(r))),C(h(t.join(`
7
+ `)))}function he(o,e){let r=[];return o.length>0&&(r.push("Auto-akzeptiert f\xFCr:"),r.push(T(o))),e.length>0&&(r.push("Manuelle Bewertung erforderlich f\xFCr:"),r.push(T(e))),r.join(`
8
+ `)}function ge(o,e,r){let t=0;for(let n of e.slice().sort()){o.push({type:"paragraph",content:[{type:"text",text:n,marks:[{type:"strong"}]}]});let s=r.get(n);if(s&&s.length>0){let i=ye(s);i&&(t+=i.length,t>Ve?o.push(E("Verwendungsbaum",h("Gesamtgr\xF6\xDFe der Verwendungsb\xE4ume \xFCberschreitet Limit. Siehe Issue-Attachments f\xFCr vollst\xE4ndige B\xE4ume."))):o.push(E("Verwendungsbaum",N(i))))}}}function me(o,e){if(e.size===0)return"";let r=[`# Verwendungsb\xE4ume f\xFCr ${o}`,""];for(let[t,n]of[...e.entries()].sort(([s],[i])=>s.localeCompare(i))){r.push(`## ${t}`,"");let s=ye(n);s&&r.push("```",s,"```"),r.push("")}return r.join(`
9
+ `)}function ye(o){return!o||o.length===0?"":o.map(e=>ae(e,"")).join(`
6
10
 
7
- `)}var U="proj:";function D(o){let e=o.replace(/@/g,"_v").replace(/\s+/g,"_");return`${U}${e}`}function Pe(o){if(!o.startsWith(U))return null;let e=o.slice(U.length),n=e.lastIndexOf("_v");return n<0?e:e.slice(0,n)+"@"+e.slice(n+2)}function se(o){let e=new Set;if(!o)return e;for(let n of o){let t=Pe(n);t!==null&&e.add(t)}return e}var A=class{constructor(e,n,t){this.config=e;this.client=new N(e.jiraUrl,n,t)}config;client;activeSprintCache=new Map;async report(e,n){let t={created:[],updated:[],skipped:[],errors:[]};for(let[r,s]of Object.entries(e.vulnerabilities)){let a=e.vulnerabilityToProject[r]??[];for(let i of this.config.issues){let l=a.filter(c=>J(c,i.reportProjects));if(l.length!==0)try{let c=await this.client.findExistingIssue(i.jiraProject,r);c?await this.handleExistingIssue(e,s,c,i,l,n,t):await this.handleNewIssue(e,r,s,i,l,n,t)}catch(c){let d=`Failed to process ${r} for project ${i.jiraProject}: ${String(c)}`;console.error(`[error] ${d}`),t.errors.push(d)}}}return t}async handleNewIssue(e,n,t,r,s,a,i){let l=B(t),c=this.resolveAutoCloseThreshold(r),d=c!=null&&E(t.severity,c);if(a){console.log(`[dry-run] Would create issue in ${r.jiraProject}: "${l}"`),console.log(` Matching projects: ${s.join(", ")}`),d&&console.log(`[dry-run] Would auto-close ${r.jiraProject}::${n} (severity=${t.severity} below ${c})`),i.created.push(`${r.jiraProject}::${n}`);return}let{activeSprintId:f,allLabels:w}=await this.resolveBoardRouting(r,s),g=this.collectProjectComponentTrees(e,s,t.components),C=ee(t,s,g),$=[...w,...s.map(D)],S=await this.client.createIssue({projectKey:r.jiraProject,issueType:r.issueType,summary:l,description:C,labels:$.length>0?$:void 0,sprintId:f});if(g.size>0){let j=ne(n,g);if(j){let x=`${n}-dependency-trees.md`;await this.client.attachMarkdown(S,x,j),console.log(`[attached] ${x} to ${S}`)}}console.log(`[created] ${S} in ${r.jiraProject}: "${l}"`),i.created.push(S),d&&await this.autoCloseIssue(S,t.severity,c)}async handleExistingIssue(e,n,t,r,s,a,i){let l=se(t.labels),c=s.filter(m=>!l.has(m)),f=Q(t.summary)?.severity,w=f!==void 0&&f!==n.severity;if(c.length===0&&!w){console.log(`[skip] ${t.key} already covers all matching projects`),i.skipped.push(t.key);return}let g=t.statusCategory==="done",C=this.resolveAutoCloseThreshold(r),$=C!=null&&E(n.severity,C),S=g&&!$;if(a){let m=[];w&&m.push(`retitle severity ${f} -> ${n.severity}`),c.length>0&&m.push(`add project tag(s) ${c.join(", ")}`);let P=S?" and re-open + re-add to active sprint":g?" (kept closed: sub-threshold)":"";console.log(`[dry-run] Would update ${t.key}: ${m.join("; ")}`+P),i.updated.push(t.key);return}let{activeSprintId:j,allLabels:x}=await this.resolveBoardRouting(r,s);if(w){let m=B(n);try{await this.client.updateIssueSummary(t.key,m),console.log(`[retitled] ${t.key}: ${f} -> ${n.severity}`)}catch(P){console.warn(`[warn] Could not update summary of ${t.key}: ${String(P)}`)}await this.postSeverityChangeComment(t.key,f,n.severity)}if(c.length>0){let m=this.collectProjectComponentTrees(e,c,n.components),P=[...x,...c.map(D)],de=new Set(t.labels),_=P.filter(ue=>!de.has(ue));_.length>0&&await this.client.addLabels(t.key,_);let pe=te(c,m);await this.client.addComment(t.key,pe),console.log(`[updated] ${t.key}: added project(s) ${c.join(", ")}`)}else console.log(`[updated] ${t.key}: severity changed without new projects`);g&&$?console.log(`[kept-closed] ${t.key} (severity ${n.severity} below auto-close threshold ${C})`):g&&await this.reopenAndReassignSprint(t.key,j),i.updated.push(t.key)}async postSeverityChangeComment(e,n,t){try{let r=b(p(`Schweregrad ge\xE4ndert von ${n} auf ${t}. Falls eine automatisch erstellte VEX-Ausnahme bestand, ist sie nicht mehr g\xFCltig.`));await this.client.addComment(e,r)}catch(r){console.warn(`[warn] Could not post severity-change comment on ${e}: ${String(r)}`)}}async reopenAndReassignSprint(e,n){let t;try{t=await this.client.getTransitions(e)}catch(s){console.warn(`[warn] Could not list transitions for ${e}: ${String(s)}`);return}let r=t.find(s=>s.toStatusCategory==="new");if(!r){console.warn(`[warn] ${e} is closed but no transition leading to a non-done status is available; leaving status unchanged`);return}try{await this.client.transitionIssue(e,r.id),console.log(`[reopened] ${e} via transition "${r.name}"`)}catch(s){console.warn(`[warn] Could not transition ${e} to a non-done status: ${String(s)}`);return}if(n!=null)try{await this.client.setSprint(e,n),console.log(`[sprint] ${e} added to active sprint ${n}`)}catch(s){console.warn(`[warn] Could not set sprint for ${e}: ${String(s)}`)}}resolveAutoCloseThreshold(e){return e.autoCloseBelowSeverity??this.config.autoCloseBelowSeverity}async autoCloseIssue(e,n,t){let r;try{r=await this.client.getTransitions(e)}catch(i){console.warn(`[warn] Could not list transitions for ${e} (auto-close): ${String(i)}`);return}let s=r.filter(i=>i.toStatusCategory==="done"),a=s.find(i=>i.toStatusName.toLowerCase()==="closed")??s.find(i=>{let l=i.name.toLowerCase();return l==="close"||l==="closed"})??s[0];if(!a){console.warn(`[warn] ${e} has no transition leading to a done status; cannot auto-close`);return}try{await this.client.transitionIssue(e,a.id),console.log(`[auto-closed] ${e} (severity=${n}, threshold=${t}) via transition "${a.name}"`)}catch(i){console.warn(`[warn] Could not transition ${e} to a done status: ${String(i)}`);return}try{let i=b(p(`Automatisch geschlossen: Schwere ${n} liegt unterhalb der konfigurierten Auto-Close-Schwelle ${t}.`));await this.client.addComment(e,i)}catch(i){console.warn(`[warn] Could not post auto-close comment on ${e}: ${String(i)}`)}}async resolveBoardRouting(e,n){let t,r=[],s=!1;for(let i of e.addToBoard??[]){let l=i.matchProjects??["*"];if(n.some(d=>J(d,l)))if(i.sprintBoardId!=null){if(!s){s=!0;let d=i.sprintBoardId;if(!this.activeSprintCache.has(d)){let f=await this.client.getActiveSprintId(d).catch(w=>(console.warn(`[warn] Could not resolve active sprint for boardId ${d}: ${String(w)}`),null));this.activeSprintCache.set(d,f)}t=this.activeSprintCache.get(d)??void 0,i.issueLabels&&r.push(...i.issueLabels)}}else i.issueLabels&&r.push(...i.issueLabels)}let a=[...e.issueLabels??[],...r];return{activeSprintId:t,allLabels:a}}collectProjectComponentTrees(e,n,t){let r=new Map;if(!e.projectsToComponents)return r;for(let s of n){let a=e.projectsToComponents[s]??{},i=[];for(let l of t){let c=a[l];c&&i.push(c)}i.length>0&&r.set(s,i)}return r}};var y=Se(require("path")),O=require("fs/promises");var M=class o{constructor(e){this.workingDir=e}workingDir;static DEFAULT_MAVEN_REPO="https://repository.conterra.de/repository/maven-mirror-ct";static DEFAULT_VEX_SUBDIR="input/vex";static DEFAULT_OUT_SUBDIR="output";static DEFAULT_CACHE_SUBDIR="cache";static DEFAULT_SCANNERS=["grype","trivy","ossindex"];normalize(e,n){let t=e.findNoLongerDetectedVulnerabilitiesOnlyForSnapshots??!1;return{projectConfigFileLocation:n,onNewVulnerabilities:e.onNewVulnerabilities??(e.failOnNewVulnerabilities?"fail":"warn"),onNoLongerDetectedVulnerabilities:e.onNoLongerDetectedVulnerabilities??"ignore",reportNoLongerDetectedVulnerabilities:e.reportNoLongerDetectedVulnerabilities??!0,consoleReport:e.consoleReport??"BY_PROJECT_DETAILED",createSubDirsForProject:e.createSubDirsForProject??!0,mavenRepo:e.mavenRepo??o.DEFAULT_MAVEN_REPO,vexUrls:e.vexUrls??[],vexDir:this.resolvePath(e.vexDir)??(0,y.resolve)(this.workingDir,o.DEFAULT_VEX_SUBDIR),outDir:this.resolvePath(e.outDir)??(0,y.resolve)(this.workingDir,o.DEFAULT_OUT_SUBDIR),cacheDir:this.resolvePath(e.cacheDir)??(0,y.resolve)(this.workingDir,o.DEFAULT_CACHE_SUBDIR),scanners:this.normalizeScanners(e.scanners,n),projects:this.normalizeProjects(e.projects??[],t)}}normalizeScanners(e,n){return(e??o.DEFAULT_SCANNERS).map(r=>{if(typeof r!="string")throw new Error(`Invalid scanner name '${String(r)}' in configuration file '${n}'`);let s=r.split("@");if(s.length>2)throw new Error(`Invalid scanner name '${r}' in configuration file '${n}'`);return{name:s[0],version:s[1]??""}})}normalizeProjects(e,n){return e.map(t=>{let r=t;if(!r.name)throw new Error("Project name is missing on entry: "+JSON.stringify(r));if(!r.version)throw new Error("Project version is missing on entry: "+JSON.stringify(r));if(!r.purl)throw new Error("Project purl is missing on entry: "+JSON.stringify(r));let s={...r,purlAliases:r.purlAliases??[],enabled:r.enabled??!0,silent:r.silent??!1,minimumSeverity:r.minimumSeverity??"UNKNOWN"};return s.sbomFile?{...s,sbomFile:this.resolvePath(s.sbomFile)??s.sbomFile}:{...s,detectNoLongerUsedVulnerabilities:n?s.purl.endsWith("-SNAPSHOT"):!0}})}resolvePath(e){if(e)return y.default.isAbsolute(e)?e:(0,y.resolve)(this.workingDir,e)}},k=class{constructor(e){this.workingDir=e;this.normalizer=new M(e)}workingDir;normalizer;projectConfigCache;async loadProjectConfig(){return this.projectConfigCache??=this.doLoadProjectConfig(),this.projectConfigCache}async doLoadProjectConfig(){let e=(0,y.resolve)(this.workingDir,"vuln-scan-conf.json"),n=await X(e);if(!n)throw new Error(`Missing project configuration file '${e}'`);return this.normalizer.normalize(n,e)}async loadJiraConfig(e){let n=await(0,O.readFile)(e,"utf8"),t=JSON.parse(n);if(!t.issues&&t.issue&&(t.issues=t.issue),!t.jiraUrl||typeof t.jiraUrl!="string")throw new Error("jira-conf.json: missing or invalid 'jiraUrl' field");if(!Array.isArray(t.issues))throw new Error("jira-conf.json: missing or invalid 'issues' array");this.validateAutoCloseSeverity(t.autoCloseBelowSeverity,"jira-conf.json: invalid 'autoCloseBelowSeverity'");for(let[r,s]of t.issues.entries())s&&typeof s=="object"&&this.validateAutoCloseSeverity(s.autoCloseBelowSeverity,`jira-conf.json: invalid 'issues[${r}].autoCloseBelowSeverity'`);return t}validateAutoCloseSeverity(e,n){if(e!==void 0&&!v.includes(e))throw new Error(`${n} value '${String(e)}'. Must be one of: ${v.join(", ")}`)}async loadAutoVexConfig(e){let n=await(0,O.readFile)(e,"utf8"),t=JSON.parse(n);if(!t.impactStatement||typeof t.impactStatement!="string")throw new Error("auto-vex-conf.json: missing or invalid 'impactStatement' field (must be a non-empty string)");if(t.maxSeverity!==void 0&&!v.includes(t.maxSeverity))throw new Error(`auto-vex-conf.json: invalid 'maxSeverity' value '${String(t.maxSeverity)}'. Must be one of: ${v.join(", ")}`);return t}};async function ae(o){let{scanSummaryPath:e,jiraConfigPath:n,jiraUser:t,jiraApiToken:r,dryRun:s=!1}=o,a=new k(process.cwd()),[i,l]=await Promise.all([je(e),a.loadJiraConfig(n)]);return new A(l,t,r).report(i,s)}async function je(o){let e=await(0,ie.readFile)(o,"utf8");return JSON.parse(e)}var F={flag:"--dry-run",description:"Print what would happen without making changes"},R=class{specs;booleanSpecs;commandName;helpLines;constructor(e,n,t=[],r=[]){this.commandName=e,this.specs=n;let s=r.some(a=>a.flag===F.flag);this.booleanSpecs=s?r:[...r,F],this.helpLines=t}parse(e){let n=e.slice(2),t=new Map(this.specs.map(s=>[s.flag,s.defaultValue])),r=new Map(this.booleanSpecs.map(s=>[s.flag,!1]));for(let s=0;s<n.length;s++){let a=n[s];(a==="--help"||a==="-h")&&(this.printHelp(),process.exit(0));let i=this.booleanSpecs.find(c=>c.flag===a||c.alias===a);if(i){r.set(i.flag,!0);continue}let l=this.specs.find(c=>c.flag===a||c.alias===a);l&&n[s+1]?t.set(l.flag,n[++s]):(console.error(`Unknown argument: ${a}`),this.printHelp(),process.exit(1))}return{values:t,dryRun:r.get(F.flag)===!0,booleans:r}}printHelp(){let e=this.specs.map(t=>` ${(t.alias?`${t.alias}, ${t.flag} <path>`:` ${t.flag} <path>`).padEnd(38)}${t.description}
8
- ${"".padEnd(42)}(default: ${t.defaultValue})`),n=this.booleanSpecs.map(t=>` ${(t.alias?`${t.alias}, ${t.flag}`:` ${t.flag}`).padEnd(38)}${t.description}`);console.log([`Usage: ${this.commandName} [options]`,"","Options:",...e,...n," -h, --help"+" ".repeat(32)+"Show this help message",...this.helpLines].join(`
9
- `))}};le.dotenv.config();var ce=process.env,xe=new R("ct-vuln-jira-report",[{flag:"--jira-config",alias:"-c",description:"Path to jira-conf.json configuration file",defaultValue:(0,V.join)(process.cwd(),"jira-conf.json")},{flag:"--summary",alias:"-s",description:"Path to scan-summary.json produced by ct-vuln-scan",defaultValue:(0,V.join)(process.cwd(),"output","scan-summary.json")}],["","Required environment variables:"," JIRA_USER Jira account e-mail address"," JIRA_API_TOKEN Jira API token (see https://id.atlassian.com/manage-profile/security/api-tokens)"]);(async()=>{let{values:o,dryRun:e}=xe.parse(process.argv),n=o.get("--jira-config"),t=o.get("--summary"),r=ce.JIRA_USER,s=ce.JIRA_API_TOKEN;(!r||!s)&&(console.error("Error: JIRA_USER and JIRA_API_TOKEN environment variables must be set."),process.exit(1)),console.log(`Jira reporter${e?" [dry-run]":""}`),console.log(` config: ${n}`),console.log(` summary: ${t}`),console.log("");try{let a=await ae({scanSummaryPath:t,jiraConfigPath:n,jiraUser:r,jiraApiToken:s,dryRun:e});console.log(""),console.log("=== Jira Report Summary ==="),console.log(` Created : ${a.created.length}`),console.log(` Updated : ${a.updated.length}`),console.log(` Skipped : ${a.skipped.length}`),console.log(` Errors : ${a.errors.length}`),a.errors.length>0&&(process.exitCode=1)}catch(a){console.error(`Fatal error: ${String(a)}`),process.exit(1)}})();
11
+ `)}var W="proj:";function G(o){let e=o.replace(/@/g,"_v").replace(/\s+/g,"_");return`${W}${e}`}function _e(o){if(!o.startsWith(W))return null;let e=o.slice(W.length),r=e.lastIndexOf("_v");return r<0?e:e.slice(0,r)+"@"+e.slice(r+2)}function we(o){let e=new Set;if(!o)return e;for(let r of o){let t=_e(r);t!==null&&e.add(t)}return e}function ve(o){let e=o.severityChange,r=o.newProjects;return e&&r&&r.length>0?`Issue wieder ge\xF6ffnet, da sich der Schweregrad von ${e.from} auf ${e.to} ge\xE4ndert hat und zus\xE4tzlich neue betroffene Projekte gefunden wurden: ${r.join(", ")}.`:e?`Issue wieder ge\xF6ffnet: Schweregrad hat sich von ${e.from} auf ${e.to} ge\xE4ndert. Eine ggf. bestehende automatische VEX-Ausnahme ist nicht mehr g\xFCltig und sollte erneut bewertet werden.`:r&&r.length>0?`Issue wieder ge\xF6ffnet, da die Schwachstelle nun zus\xE4tzlich folgende Projekte betrifft: ${r.join(", ")}. Bitte erneut bewerten, ob die urspr\xFCngliche L\xF6sung/Mitigation weiterhin ausreicht.`:"Issue wieder ge\xF6ffnet."}function Se(o){let e=[];return o.severityChange&&e.push(`severity ${o.severityChange.from}->${o.severityChange.to}`),o.newProjects&&o.newProjects.length>0&&e.push(`new projects: ${o.newProjects.join(", ")}`),e.join(" + ")||"unspecified"}function w(o){return o.length===0?"-":o.map(e=>e.projectId).slice().sort((e,r)=>e.localeCompare(r)).join(", ")}function ze(o){let e=[];return o.autoAcknowledged.length>0&&e.push(`auto-ack: ${w(o.autoAcknowledged)}`),o.manualEvaluation.length>0&&e.push(`manual: ${w(o.manualEvaluation)}`),e.join("; ")}var Ce=10,je=" ".repeat(Ce);function K(o){return`[${o}]`.padEnd(Ce," ")}function $e(o){return o==="warn"?console.warn:o==="error"?console.error:console.log}function He(o,e,r=[]){let t=$e(o);t(`${K(o)}${e}`);for(let n of r)t(`${je}${n}`)}function We(o){let e="\u2500".repeat(Math.max(0,62-o.length-4));console.log(""),console.log(`\u2500\u2500 ${o} ${e}`)}var X=class{vulnId;jiraProject;severity;issueKey;kind="skip";header="";details=[];constructor(e,r,t){this.vulnId=e,this.jiraProject=r,this.severity=t}setOutcome(e,r){this.kind=e,this.header=this.composeHeader(r)}detail(e,r){this.details.push(`${e.padEnd(9," ")}: ${r}`)}note(e){this.details.push(e)}warn(e,r){console.warn(`${K("warn")}${e}`),this.detail("warn",e),r.warnings.push(e)}flush(){let e=$e(this.kind);e(`${K(this.kind)}${this.header}`);for(let r of this.details)e(`${je}${r}`)}composeHeader(e){let r=this.issueKey??"<new>",t=e?` ${e}`:"",n=r.padEnd(12," ");return`${this.vulnId} -> ${n} in ${this.jiraProject}, severity=${this.severity}${t}`}},B=class{constructor(e,r,t){this.config=e;this.client=new L(e.jiraUrl,r,t)}config;client;activeSprintCache=new Map;async report(e,r){let t={created:[],updated:[],skipped:[],errors:[],warnings:[],noMatchingRule:[],reopened:[],autoClosed:[],keptClosed:[]};We("Issue processing");for(let[n,s]of Object.entries(e.vulnerabilities)){let i=e.vulnerabilityToProject[n]??[],c=!1;for(let a of this.config.issues){let l=i.filter(u=>J(u,a.reportProjects));if(l.length===0)continue;c=!0;let d=new X(n,a.jiraProject,s.severity);try{let u=await this.client.findExistingIssue(a.jiraProject,n);u?(d.issueKey=u.key,await this.handleExistingIssue(e,s,u,a,l,r,t,d)):await this.handleNewIssue(e,n,s,a,l,r,t,d)}catch(u){let p=`Failed to process ${n} for project ${a.jiraProject}: ${String(u)}`;t.errors.push(p),d.setOutcome("error"),d.note(`error : ${String(u)}`)}d.flush()}c||(t.noMatchingRule.push(n),He("skip",`${n} (no matching jira-project rule, severity=${s.severity})`))}return t}async handleNewIssue(e,r,t,n,s,i,c,a){let l=z(t),d=this.bucketProjects(s,t.severity,n),u=d.shouldAutoClose,p=!u&&d.autoAcknowledged.length>0&&d.manualEvaluation.length>0;if(i){a.setOutcome("dry-run"),a.detail("would",`create issue with title "${l}"`),a.detail("projects",s.join(", "));let f=`${n.jiraProject}::${r}`;u?(a.detail("would",`auto-close (severity ${t.severity} below threshold ${d.strictestThreshold}; auto-ack: ${w(d.autoAcknowledged)})`),c.autoClosed.push(f)):p&&a.detail("would",`post partial-ack comment (auto: ${w(d.autoAcknowledged)}; manual: ${w(d.manualEvaluation)})`),c.created.push(f);return}let{activeSprintId:v,allLabels:S}=await this.resolveBoardRouting(n,s,a,c),P=this.collectProjectComponentTrees(e,s,t.components),R=ue(t,s,P),A=[...S,...s.map(G)],g=await this.client.createIssue({projectKey:n.jiraProject,issueType:n.issueType,summary:l,description:R,labels:A.length>0?A:void 0,sprintId:v});if(a.issueKey=g,a.setOutcome("create"),a.detail("title",l),a.detail("projects",s.join(", ")),c.created.push(g),P.size>0){let f=me(r,P);if(f){let x=`${r}-dependency-trees.md`;await this.client.attachMarkdown(g,x,f),a.detail("attach",x)}}u?await this.autoCloseIssue(g,t.severity,d,a,c):p&&await this.postPartialAckComment(g,t.severity,d,a,c)}async handleExistingIssue(e,r,t,n,s,i,c,a){let l=we(t.labels),d=s.filter(b=>!l.has(b)),p=de(t.summary)?.severity,v=p!==void 0&&p!==r.severity;if(d.length===0&&!v){a.setOutcome("skip"),a.detail("reason",`already covers all matching projects (${s.join(", ")})`),c.skipped.push(t.key);return}let S=t.statusCategory==="done",P=this.bucketProjects(s,r.severity,n),R=P.strictestThreshold,A=P.shouldAutoClose,g=S&&!A,f=this.bucketProjects(d,r.severity,n),x=g?he(f.autoAcknowledged,f.manualEvaluation):"",ee=!g&&d.length>0&&f.autoAcknowledged.length>0&&f.manualEvaluation.length>0,U=g?{severityChange:v?{from:p,to:r.severity}:void 0,newProjects:d.length>0?d:void 0}:void 0;if(i){if(a.setOutcome("dry-run"),v&&a.detail("would",`retitle severity ${p} -> ${r.severity}`),d.length>0&&a.detail("would",`add project tag(s) ${d.join(", ")}`),g){a.note("would re-open + re-add to active sprint");let b=x?`${Se(U)}; ${ze(f)}`:Se(U);a.detail("would",`post reopen-reason comment (${b})`),c.reopened.push(t.key)}else S&&(a.note(`would keep closed (severity ${r.severity} below auto-close threshold ${R})`),c.keptClosed.push(t.key));ee&&a.detail("would",`post partial-ack comment (auto: ${w(f.autoAcknowledged)}; manual: ${w(f.manualEvaluation)})`),c.updated.push(t.key);return}let{activeSprintId:Re,allLabels:Ie}=await this.resolveBoardRouting(n,s,a,c);if(v){let b=z(r);try{await this.client.updateIssueSummary(t.key,b),a.detail("retitle",`${p} -> ${r.severity}`)}catch(M){a.warn(`Could not update summary of ${t.key}: ${String(M)}`,c)}g||await this.postSeverityChangeComment(t.key,p,r.severity,a,c)}if(d.length>0){let b=this.collectProjectComponentTrees(e,d,r.components),M=[...Ie,...d.map(G)],ke=new Set(t.labels),te=M.filter(F=>!ke.has(F));if(te.length>0&&await this.client.addLabels(t.key,te),!g){let F=ee?H(r.severity,f.autoAcknowledged,f.manualEvaluation):pe(d,b);await this.client.addComment(t.key,F)}a.setOutcome("update"),a.detail("projects",`added ${d.join(", ")}`)}else a.setOutcome("update"),a.detail("reason","severity changed (no new projects)");S&&A?(a.note(`kept closed: severity ${r.severity} below auto-close threshold ${R}`),c.keptClosed.push(t.key)):S&&await this.reopenAndReassignSprint(t.key,Re,U,x,a,c),c.updated.push(t.key)}async postSeverityChangeComment(e,r,t,n,s){try{let i=C(h(`Schweregrad ge\xE4ndert von ${r} auf ${t}. Falls eine automatisch erstellte VEX-Ausnahme bestand, ist sie nicht mehr g\xFCltig.`));await this.client.addComment(e,i)}catch(i){n.warn(`Could not post severity-change comment on ${e}: ${String(i)}`,s)}}async reopenAndReassignSprint(e,r,t,n,s,i){let c;try{c=await this.client.getTransitions(e)}catch(l){s.warn(`Could not list transitions for ${e}: ${String(l)}`,i);return}let a=c.find(l=>l.toStatusCategory==="new");if(!a){s.warn(`${e} is closed but no transition leading to a non-done status is available; leaving status unchanged`,i);return}try{await this.client.transitionIssue(e,a.id),s.detail("reopen",`via "${a.name}"`),i.reopened.push(e)}catch(l){s.warn(`Could not transition ${e} to a non-done status: ${String(l)}`,i);return}if(await this.postReopenReasonComment(e,t,n,s,i),r!=null)try{await this.client.setSprint(e,r),s.detail("sprint",`added to active sprint ${r}`)}catch(l){s.warn(`Could not set sprint for ${e}: ${String(l)}`,i)}}async postReopenReasonComment(e,r,t,n,s){try{let i=t?`${ve(r)}
12
+ ${t}`:ve(r),c=C(h(i));await this.client.addComment(e,c),n.detail("comment","reopen-reason posted")}catch(i){n.warn(`Could not post reopen-reason comment on ${e}: ${String(i)}`,s)}}resolveAutoCloseThreshold(e){return e.autoCloseBelowSeverity??this.config.autoCloseBelowSeverity}effectiveProjectThreshold(e,r){let t;for(let n of r.projectOverrides??[])J(e,n.projects)&&(t==null||V(n.autoCloseBelowSeverity,t)<0)&&(t=n.autoCloseBelowSeverity);return t??this.resolveAutoCloseThreshold(r)}bucketProjects(e,r,t){if(e.length===0){let l=this.resolveAutoCloseThreshold(t);return{strictestThreshold:l,autoAcknowledged:[],manualEvaluation:[],shouldAutoClose:l!=null&&k(r,l)}}let n=[],s=[],i,c=!1;for(let l of e){let d=this.effectiveProjectThreshold(l,t);if(d==null){c=!0;continue}(i==null||V(d,i)<0)&&(i=d);let u={projectId:l,threshold:d};k(r,d)?n.push(u):s.push(u)}let a=!c&&s.length===0&&n.length>0&&i!=null&&k(r,i);return{strictestThreshold:i,autoAcknowledged:n,manualEvaluation:s,shouldAutoClose:a}}async autoCloseIssue(e,r,t,n,s){let i=t.strictestThreshold,c;try{c=await this.client.getTransitions(e)}catch(d){n.warn(`Could not list transitions for ${e} (auto-close): ${String(d)}`,s);return}let a=c.filter(d=>d.toStatusCategory==="done"),l=a.find(d=>d.toStatusName.toLowerCase()==="closed")??a.find(d=>{let u=d.name.toLowerCase();return u==="close"||u==="closed"})??a[0];if(!l){n.warn(`${e} has no transition leading to a done status; cannot auto-close`,s);return}try{await this.client.transitionIssue(e,l.id),n.detail("close",`auto-closed (severity ${r} below ${i}) via "${l.name}"`),s.autoClosed.push(e)}catch(d){n.warn(`Could not transition ${e} to a done status: ${String(d)}`,s);return}try{let d=fe(r,t.autoAcknowledged);await this.client.addComment(e,d)}catch(d){n.warn(`Could not post auto-close comment on ${e}: ${String(d)}`,s)}}async postPartialAckComment(e,r,t,n,s){try{let i=H(r,t.autoAcknowledged,t.manualEvaluation);await this.client.addComment(e,i),n.detail("comment",`partial-ack posted (auto: ${w(t.autoAcknowledged)}; manual: ${w(t.manualEvaluation)})`)}catch(i){n.warn(`Could not post partial-ack comment on ${e}: ${String(i)}`,s)}}async resolveBoardRouting(e,r,t,n){let s,i=[],c=!1;for(let l of e.addToBoard??[]){let d=l.matchProjects??["*"];if(r.some(p=>J(p,d)))if(l.sprintBoardId!=null){if(!c){c=!0;let p=l.sprintBoardId;if(!this.activeSprintCache.has(p)){let v=await this.client.getActiveSprintId(p).catch(S=>(t.warn(`Could not resolve active sprint for boardId ${p}: ${String(S)}`,n),null));this.activeSprintCache.set(p,v)}s=this.activeSprintCache.get(p)??void 0,l.issueLabels&&i.push(...l.issueLabels)}}else l.issueLabels&&i.push(...l.issueLabels)}let a=[...e.issueLabels??[],...i];return{activeSprintId:s,allLabels:a}}collectProjectComponentTrees(e,r,t){let n=new Map;if(!e.projectsToComponents)return n;for(let s of r){let i=e.projectsToComponents[s]??{},c=[];for(let a of t){let l=i[a];l&&c.push(l)}c.length>0&&n.set(s,c)}return n}};var $=De(require("path")),q=require("fs/promises");var Y=class o{constructor(e){this.workingDir=e}workingDir;static DEFAULT_MAVEN_REPO="https://repository.conterra.de/repository/maven-mirror-ct";static DEFAULT_VEX_SUBDIR="input/vex";static DEFAULT_OUT_SUBDIR="output";static DEFAULT_CACHE_SUBDIR="cache";static DEFAULT_SCANNERS=["grype","trivy","ossindex"];normalize(e,r){let t=e.findNoLongerDetectedVulnerabilitiesOnlyForSnapshots??!1;return{projectConfigFileLocation:r,onNewVulnerabilities:e.onNewVulnerabilities??(e.failOnNewVulnerabilities?"fail":"warn"),onNoLongerDetectedVulnerabilities:e.onNoLongerDetectedVulnerabilities??"ignore",reportNoLongerDetectedVulnerabilities:e.reportNoLongerDetectedVulnerabilities??!0,consoleReport:e.consoleReport??"BY_PROJECT_DETAILED",createSubDirsForProject:e.createSubDirsForProject??!0,mavenRepo:e.mavenRepo??o.DEFAULT_MAVEN_REPO,vexUrls:e.vexUrls??[],vexDir:this.resolvePath(e.vexDir)??(0,$.resolve)(this.workingDir,o.DEFAULT_VEX_SUBDIR),outDir:this.resolvePath(e.outDir)??(0,$.resolve)(this.workingDir,o.DEFAULT_OUT_SUBDIR),cacheDir:this.resolvePath(e.cacheDir)??(0,$.resolve)(this.workingDir,o.DEFAULT_CACHE_SUBDIR),scanners:this.normalizeScanners(e.scanners,r),projects:this.normalizeProjects(e.projects??[],t)}}normalizeScanners(e,r){return(e??o.DEFAULT_SCANNERS).map(n=>{if(typeof n!="string")throw new Error(`Invalid scanner name '${String(n)}' in configuration file '${r}'`);let s=n.split("@");if(s.length>2)throw new Error(`Invalid scanner name '${n}' in configuration file '${r}'`);return{name:s[0],version:s[1]??""}})}normalizeProjects(e,r){return e.map(t=>{let n=t;if(!n.name)throw new Error("Project name is missing on entry: "+JSON.stringify(n));if(!n.version)throw new Error("Project version is missing on entry: "+JSON.stringify(n));if(!n.purl)throw new Error("Project purl is missing on entry: "+JSON.stringify(n));let s={...n,purlAliases:n.purlAliases??[],enabled:n.enabled??!0,silent:n.silent??!1,minimumSeverity:n.minimumSeverity??"UNKNOWN"};return s.sbomFile?{...s,sbomFile:this.resolvePath(s.sbomFile)??s.sbomFile}:{...s,detectNoLongerUsedVulnerabilities:r?s.purl.endsWith("-SNAPSHOT"):!0}})}resolvePath(e){if(e)return $.default.isAbsolute(e)?e:(0,$.resolve)(this.workingDir,e)}},O=class{constructor(e){this.workingDir=e;this.normalizer=new Y(e)}workingDir;normalizer;projectConfigCache;async loadProjectConfig(){return this.projectConfigCache??=this.doLoadProjectConfig(),this.projectConfigCache}async doLoadProjectConfig(){let e=(0,$.resolve)(this.workingDir,"vuln-scan-conf.json"),r=await se(e);if(!r)throw new Error(`Missing project configuration file '${e}'`);return this.normalizer.normalize(r,e)}async loadJiraConfig(e){let r=await(0,q.readFile)(e,"utf8"),t=JSON.parse(r);if(!t.issues&&t.issue&&(t.issues=t.issue),!t.jiraUrl||typeof t.jiraUrl!="string")throw new Error("jira-conf.json: missing or invalid 'jiraUrl' field");if(!Array.isArray(t.issues))throw new Error("jira-conf.json: missing or invalid 'issues' array");this.validateAutoCloseSeverity(t.autoCloseBelowSeverity,"jira-conf.json: invalid 'autoCloseBelowSeverity'");for(let[n,s]of t.issues.entries())if(s&&typeof s=="object"){let i=s;this.validateAutoCloseSeverity(i.autoCloseBelowSeverity,`jira-conf.json: invalid 'issues[${n}].autoCloseBelowSeverity'`),this.validateAutoCloseProjectOverrides(i.projectOverrides,`jira-conf.json: invalid 'issues[${n}].projectOverrides'`)}return t}validateAutoCloseSeverity(e,r){if(e!==void 0&&!y.includes(e))throw new Error(`${r} value '${String(e)}'. Must be one of: ${y.join(", ")}`)}validateAutoCloseProjectOverrides(e,r){if(e!==void 0){if(!Array.isArray(e))throw new Error(`${r}: must be an array`);for(let t=0;t<e.length;t++){let n=e[t],s=`${r}[${t}]`;if(n==null||typeof n!="object")throw new Error(`${s}: must be an object`);let i=n,c=i.projects;if(!Array.isArray(c)||c.length===0)throw new Error(`${s}.projects: must be a non-empty array of strings`);for(let a=0;a<c.length;a++){let l=c[a];if(typeof l!="string"||l.length===0)throw new Error(`${s}.projects[${a}]: must be a non-empty string`)}if(i.autoCloseBelowSeverity===void 0)throw new Error(`${s}.autoCloseBelowSeverity: is required`);if(this.validateAutoCloseSeverity(i.autoCloseBelowSeverity,`${s}.autoCloseBelowSeverity`),i.comment!==void 0&&typeof i.comment!="string")throw new Error(`${s}.comment: must be a string`)}}}async loadAutoVexConfig(e){let r=await(0,q.readFile)(e,"utf8"),t=JSON.parse(r);if(!t.impactStatement||typeof t.impactStatement!="string")throw new Error("auto-vex-conf.json: missing or invalid 'impactStatement' field (must be a non-empty string)");if(t.maxSeverity!==void 0&&!y.includes(t.maxSeverity))throw new Error(`auto-vex-conf.json: invalid 'maxSeverity' value '${String(t.maxSeverity)}'. Must be one of: ${y.join(", ")}`);if(t.projectOverrides!==void 0){if(!Array.isArray(t.projectOverrides))throw new Error("auto-vex-conf.json: 'projectOverrides' must be an array");for(let[n,s]of t.projectOverrides.entries()){if(!s||typeof s!="object")throw new Error(`auto-vex-conf.json: 'projectOverrides[${n}]' must be an object`);let i=s;if(!Array.isArray(i.projects)||i.projects.length===0||!i.projects.every(c=>typeof c=="string"&&c.length>0))throw new Error(`auto-vex-conf.json: 'projectOverrides[${n}].projects' must be a non-empty array of non-empty strings`);if(!y.includes(i.maxSeverity))throw new Error(`auto-vex-conf.json: invalid 'projectOverrides[${n}].maxSeverity' value '${String(i.maxSeverity)}'. Must be one of: ${y.join(", ")}`)}}return t}};async function Pe(o){let{scanSummaryPath:e,jiraConfigPath:r,jiraUser:t,jiraApiToken:n,dryRun:s=!1}=o,i=new O(process.cwd()),[c,a]=await Promise.all([Ge(e),i.loadJiraConfig(r)]);return new B(a,t,n).report(c,s)}function Ae(o){return o.created.length===0&&o.updated.length===0&&o.skipped.length===0&&o.noMatchingRule.length===0&&o.autoClosed.length===0&&o.reopened.length===0&&o.keptClosed.length===0&&o.warnings.length===0&&o.errors.length===0}async function Ge(o){let e=await(0,be.readFile)(o,"utf8");return JSON.parse(e)}var Z={flag:"--dry-run",description:"Print what would happen without making changes"},D=class{specs;booleanSpecs;commandName;helpLines;constructor(e,r,t=[],n=[]){this.commandName=e,this.specs=r;let s=n.some(i=>i.flag===Z.flag);this.booleanSpecs=s?n:[...n,Z],this.helpLines=t}parse(e){let r=e.slice(2),t=new Map(this.specs.map(s=>[s.flag,s.defaultValue])),n=new Map(this.booleanSpecs.map(s=>[s.flag,!1]));for(let s=0;s<r.length;s++){let i=r[s];(i==="--help"||i==="-h")&&(this.printHelp(),process.exit(0));let c=this.booleanSpecs.find(l=>l.flag===i||l.alias===i);if(c){n.set(c.flag,!0);continue}let a=this.specs.find(l=>l.flag===i||l.alias===i);a&&r[s+1]?t.set(a.flag,r[++s]):(console.error(`Unknown argument: ${i}`),this.printHelp(),process.exit(1))}return{values:t,dryRun:n.get(Z.flag)===!0,booleans:n}}printHelp(){let e=this.specs.map(t=>` ${(t.alias?`${t.alias}, ${t.flag} <path>`:` ${t.flag} <path>`).padEnd(38)}${t.description}
13
+ ${"".padEnd(42)}(default: ${t.defaultValue})`),r=this.booleanSpecs.map(t=>` ${(t.alias?`${t.alias}, ${t.flag}`:` ${t.flag}`).padEnd(38)}${t.description}`);console.log([`Usage: ${this.commandName} [options]`,"","Options:",...e,...r," -h, --help"+" ".repeat(32)+"Show this help message",...this.helpLines].join(`
14
+ `))}};Te.dotenv.config();var xe=process.env,Ke=new D("ct-vuln-jira-report",[{flag:"--jira-config",alias:"-c",description:"Path to jira-conf.json configuration file",defaultValue:(0,Q.join)(process.cwd(),"jira-conf.json")},{flag:"--summary",alias:"-s",description:"Path to scan-summary.json produced by ct-vuln-scan",defaultValue:(0,Q.join)(process.cwd(),"output","scan-summary.json")}],["","Required environment variables:"," JIRA_USER Jira account e-mail address"," JIRA_API_TOKEN Jira API token (see https://id.atlassian.com/manage-profile/security/api-tokens)"]);(async()=>{let{values:o,dryRun:e}=Ke.parse(process.argv),r=o.get("--jira-config"),t=o.get("--summary"),n=xe.JIRA_USER,s=xe.JIRA_API_TOKEN;(!n||!s)&&(console.error("Error: JIRA_USER and JIRA_API_TOKEN environment variables must be set."),process.exit(1)),console.log(`Jira reporter${e?" [dry-run]":""}`);try{let c=await Pe({scanSummaryPath:t,jiraConfigPath:r,jiraUser:n,jiraApiToken:s,dryRun:e});Ae(c)&&console.log("[info] nothing to do"),e&&(console.log(""),console.log("No issues were created or modified (dry-run). Re-run without --dry-run to apply.")),c.errors.length>0&&(process.exitCode=1)}catch(c){console.error(`Fatal error: ${String(c)}`),process.exit(1)}})();