@conterra/vuln-scan 0.0.31 → 0.0.32
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.
- package/dist/vuln-scan.js +2 -4
- package/package.json +1 -1
package/dist/vuln-scan.js
CHANGED
|
@@ -29,14 +29,12 @@ ${t.refs.map(o=>`* <${o}>`).join(`
|
|
|
29
29
|
- ${t.components?.join(`
|
|
30
30
|
- `)}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
Usage tree:
|
|
33
|
+
|
|
34
34
|
\`\`\`plain
|
|
35
35
|
${t.componentTree?.map(o=>Pe(o)).join(`
|
|
36
36
|
`)}
|
|
37
37
|
\`\`\`
|
|
38
|
-
</p>
|
|
39
|
-
</details>
|
|
40
38
|
`}var Je=require("fs/promises");async function Wn(t,e,r){if("sbomFile"in t)return await(0,Je.copyFile)(t.sbomFile,e),t.sbomFile=e,t;let n=await r.downloadArtifact(t.sbomMavenCoordinates);return await(0,Je.writeFile)(e,n),{...t,sbomFile:e}}var Ge=class{constructor(e,r){this.repo=e;this.authn=r}async downloadArtifact(e){let r=this.toArtifactInfo(e);if(this.isSnapshotVersion(r.version)&&!r.timestamp){let o=await this.fetchLatestSnapshotTimestamp(r);r={...r,timestamp:o}}let n=this.toArtifactUrl(r),i=await ye(n,this.authn);return Buffer.from(await i.arrayBuffer())}async fetchLatestSnapshotTimestamp(e){let r=`${this.toArtifactBaseUrl(e)}/maven-metadata.xml`,i=await(await ye(r,this.authn)).text();return Ms(i,e)}toArtifactUrl(e){let r=this.toArtifactBaseUrl(e),n=this.isSnapshotVersion(e.version)&&e.timestamp?e.version.replace(/SNAPSHOT$/,e.timestamp):e.version;return`${r}/${e.artifactId}-${n}-${e.classifier}.${e.extension}`}toArtifactBaseUrl(e){return`${this.repo}/${e.groupId.replace(/\./g,"/")}/${e.artifactId}/${e.version}`}isSnapshotVersion(e){return e.endsWith("-SNAPSHOT")}toArtifactInfo(e){let r=e.split(":");return{groupId:r[0],artifactId:r[1],version:r[2],classifier:r[3],extension:"json"}}};function Ms(t,e){if(e.classifier&&e.extension){let i=t.match(new RegExp(`<snapshotVersion>\\s*<classifier>${e.classifier}</classifier>\\s*<extension>${e.extension}</extension>\\s*<value>([^<]+)</value>\\s*<updated>[^<]+</updated>\\s*</snapshotVersion>`)),o=e.version.replace(/SNAPSHOT$/,"");if(i?.[1])return i[1].replace(o,"")}let r=t.match(/<timestamp>([^<]+)<\/timestamp>/),n=t.match(/<buildNumber>([^<]+)<\/buildNumber>/);if(!r||!n)throw new Error(`Failed to get timestamp and build number from ${t} for artifact '${e.artifactId}'`);return`${r[1]}-${n[1]}`}var We=require("fs/promises"),Tt=require("path");var Ct=class{constructor(e){this.location=e}async read(){let e=await G(this.location);if(!e)throw new Error("Invalid VEX file");return e}async write(e){await st(this.location,e)}async delete(){await(0,We.unlink)(this.location)}};async function He(t,e){for(let r of await(0,We.readdir)(t,{withFileTypes:!0}))r.name.endsWith(".json")?await e(new Ct((0,Tt.resolve)(r.parentPath,r.name))):r.isDirectory()&&await He((0,Tt.resolve)(r.parentPath,r.name),e)}function It(t){let e=t.vulnerability.name;return new Set([e,...t.vulnerability.aliases??[]])}var de=class t{statements=[];filteredToProducts=[];static async fromUrl(e,r,n=new t){let o=await(await ye(e,r)).json();return n.add(o),n}static async fromFiles(e,r=new t){return await He(e,async n=>{let i=await n.read();r.add(i)}),r}add(e){Rs(e);let r=e.timestamp;for(let n of e.statements){n.timestamp=n.timestamp??r;let i=Date.parse(n.timestamp),o=n.vulnerability.name,s=It(n),c=new Set(n.products?.map(l=>l["@id"]).filter(l=>!!l)??[]),u=new jt(i,o,s,c,n);this.statements.push(u)}this.sortStatementsByTimestampNewestFirst()}filterByProduct(e){if(this.assertCorrectProductId(e),this.filteredToProducts.length)return this;let r=new t;return r.filteredToProducts=e.slice(0),r.statements=this.statements.filter(n=>n.matchesAtLeastOneProduct(e)),r}findNotMatchingVulnerabilities(e,r){let n=this.filterByProduct(r??this.filteredToProducts),i=new Set;for(let o of n.statements)i.add(o.vulnName);for(let o of e)i.delete(o);return Array.from(i)}newestVulnerabilityStatement(e,r){let n=this.filterByProduct(r??this.filteredToProducts);for(let i of n.statements)if(i.matchesVulnerability(e))return this.reduceToProductInformation(i,n.filteredToProducts[0])}toVexFileForProduct(e){let r=this.filterByProduct(e??this.filteredToProducts),n=r.statements.map(i=>this.reduceToProductInformation(i,r.filteredToProducts[0]));return this.toVexFile(n)}toVexFile(e){let r=e.filter(i=>i.status!=="under_investigation");if(r.length===0)return;this.sortVexStatementsByTimestampNewestFirst(r);let n=r[0].timestamp;return{"@context":"https://openvex.dev/ns/v0.2.0","@id":"https://openvex.dev/docs/public/vex-fc763e6eb63bfbcda20b7cbbddd4e9f8feaaa317fe8d8a6f51a5663a1180343e",author:"conterra",timestamp:n,last_updated:n,version:1,statements:r}}assertCorrectProductId(e){if(!e||e.length===0)throw new Error("Product ID must be provided");if(this.filteredToProducts.length&&!Ns(this.filteredToProducts,e))throw new Error("Cannot filter to a different product")}reduceToProductInformation(e,r){let n={timestamp:new Date(e.timestamp).toISOString(),...e.statement};if(!r)return n;let i=n.products?.filter(o=>o["@id"]===r);return i?.length||(i=[{"@id":r}]),{...n,products:i}}sortStatementsByTimestampNewestFirst(){this.statements.sort((e,r)=>r.timestamp-e.timestamp)}sortVexStatementsByTimestampNewestFirst(e){e.sort((r,n)=>Date.parse(n.timestamp)-Date.parse(r.timestamp))}};function Ns(t,e){return t.length===e.length&&t.every((r,n)=>r===e[n])}var jt=class{constructor(e,r,n,i,o){this.timestamp=e;this.vulnName=r;this.vulnAliases=n;this.products=i;this.statement=o}matchesProduct(e){return this.products.has(e)}matchesAtLeastOneProduct(e){return e.some(this.matchesProduct.bind(this))}matchesVulnerability(e){return this.vulnAliases.has(e)}};function Rs(t){if(t?.["@context"]!=="https://openvex.dev/ns/v0.2.0")throw new Error("Invalid VEX file format")}var Qe=require("path"),Hn=require("fs/promises");var Ye=class{constructor(e,r,n){this.project=e;this.outputDir=r;this.useSubDirForProject=n}async lookupOutputFileForWriting(e){let r=this.useSubDirForProject?`${this.project.name}-${this.project.version}`:"",n=`${this.project.name}-${this.project.version}-`,i=this.getFileSuffix(e),o=(0,Qe.resolve)(this.outputDir,r,`${n}${i}`),s=(0,Qe.dirname)(o);return await oe(s)||await(0,Hn.mkdir)(s,{recursive:!0}),o}getFileSuffix(e){switch(e){case"grype-results":return"scan-grype-results.json";case"trivy-results":return"scan-trivy-results.json";case"ossindex-results":return"scan-ossindex-results.json";case"aggregate-results":return"scan-aggregate-results.json";case"aggregated-sarif-results":return"scan-aggregated-results.sarif.json";case"project-cyclonedx-sbom-file":return"sbom.cdx.json";case"project-openvex-file":return"openvex.vex.json";default:throw new Error(`Unknown output file key: ${e}`)}}};var Ft=require("zx");var Ke=require("path"),Yn="anchore/grype";async function Qn(t,e,r){r&&console.log(`Initializing Grype DB in cache directory: ${e}`);let n=`${Yn}:${t||"latest"}`,i=await Ft.$`docker run --rm -v '${e}:/tmp/.cache' -e GRYPE_DB_CACHE_DIR=/tmp/.cache -e TMPDIR=/tmp ${n} db update`.nothrow();if(i.stdout&&console.log(` Grype DB Update: ${i.stdout}`),i.stderr&&console.log(` Grype DB Update error: ${i.stderr}`),i.exitCode!==0)throw new Error(`Grype DB update failed with exit code ${i.exitCode}: ${i.stderr}`)}async function Kn(t,e,r,n,i,o,s){let c=(0,Ke.dirname)(r),u=(0,Ke.basename)(r),l=[];o||l.push("--quiet");let a=`${Yn}:${t||"latest"}`,f=`${e}:/tmp/.cache`,p=`${c}:/tmp/output`,m=`${n.sbomFile}:/tmp/input.json`,d=`/tmp/output/${u}`,y=await Ft.$`docker run --rm -v ${f} -v ${p} -v ${m} -e GRYPE_DB_CACHE_DIR=/tmp/.cache -e TMPDIR=/tmp -e GRYPE_DB_AUTO_UPDATE=false ${a} sbom:/tmp/input.json -o json --file ${d} --by-cve ${l}`.nothrow();if(y.stdout&&s(` Scan log: ${y.stdout}`),y.stderr&&s(` Scan error: ${y.stderr}`),y.exitCode!==0)throw new Error(`Grype scan failed with exit code ${y.exitCode}: ${y.stderr}`);s(` Grype output file: ${r}`);try{let h=await G(r);Vs(i,h)}catch(h){throw new Error(`Grype scan results could not be read from '${r}': ${h}`,{cause:h})}}function Vs(t,e){if(e)for(let r of e.matches){let n=As(r);t.addVulnerability(n,"grype")}}function As(t){let e=t.vulnerability,r=e.id,n=J(t.artifact.purl),i=J(e.dataSource),o=$s(e.severity);return{id:r,severity:o,scannerSeverity:{grype:o},title:"",description:e.description,components:[n],detectedBy:["grype"],refs:[i]}}function $s(t){switch(t){case"Negligible":return"LOW";case"Low":return"LOW";case"Medium":return"MEDIUM";case"High":return"HIGH";case"Critical":return"CRITICAL";default:return"UNKNOWN"}}var zn=require("fs/promises");async function Zn(t,e,r,n,i,o){try{let s={},c="";r.user&&r.token&&(s.Authorization=`Basic ${Buffer.from(`${r.user}:${r.token}`).toString("base64")}`,c="/authorized");let u=`https://ossindex.sonatype.org/api/v3${c}/component-report`,l=await _s(e.sbomFile),a=new Set(l.map(m=>m.purl.replace(/\?.*$/,"")));Js(a);let f=Array.from(a),p=[];for(let m=0;m<f.length;m+=128){let d=JSON.stringify({coordinates:f.slice(m,m+128)});i&&o(` Sonatype OssIndex request ${u} with body: ${d}`);let h=await(await fetch(u,{method:"POST",headers:{...s,"Content-Type":"application/vnd.ossindex.component-report-request.v1+json"},body:d})).json();Array.isArray(h)?p.push(...h.filter(w=>w.vulnerabilities.length>0)):o(` Sonatype OssIndex Error: ${h.code} - ${h.message}`)}await(0,zn.writeFile)(t,JSON.stringify(p,null,2)),o(` Sonatype OssIndex output file: ${t}`),Us(n,p)}catch(s){throw new Error(`Sonatype OSS Index scan failed: ${s}`,{cause:s})}}async function _s(t){return(await G(t)).components.filter(r=>qs(r)&&!Bs(r))}function qs(t){return!!t.purl}function Bs(t){return t.group?t.group.startsWith("de.conterra")||t.group.startsWith("org.n52.security"):!1}function Us(t,e){if(e)for(let r of e)for(let n of r.vulnerabilities){let i=Xs(n,r.coordinates);t.addVulnerability(i,"ossindex")}}function Xs(t,e){let r=t.cve||t.id,n=J(e),i=J(t.reference),o=Gs(t.cvssScore);return{id:r,severity:o,scannerSeverity:{ossindex:o},title:t.title,description:t.description,components:[n],detectedBy:["ossindex"],refs:i?[i]:[]}}function Gs(t){return t===0?"UNKNOWN":t<4?"LOW":t<7?"MEDIUM":t<9?"HIGH":"CRITICAL"}function Js(t){let e=Array.from(t);for(let r of e){let n=r.replace(/(@[^-]+)-.*$/g,"$1");t.add(n)}}var Mt=require("zx");var ze=require("path"),ei="aquasec/trivy";async function ti(t,e,r,n){let i=[];r&&(i.push("-e"),i.push(`GITHUB_TOKEN=${r}`));let o=[];o.push("--db-repository"),o.push("public.ecr.aws/aquasecurity/trivy-db,aquasec/trivy-db,ghcr.io/aquasecurity/trivy-db"),n||o.push("--quiet");let s=`${ei}:${t||"latest"}`,c=await Mt.$`docker run --rm -v '${e}:/.cache' ${i} ${s} ${o} --cache-dir '/.cache' sbom --download-db-only`.nothrow();if(!c.stdout&&!c.stderr&&console.log(" Trivy DB Update: finished"),c.stdout&&console.log(` Trivy DB Update: ${c.stdout}`),c.stderr&&console.log(` Trivy DB Update error: ${c.stderr}`),c.exitCode!==0)throw new Error(`Trivy DB update failed with exit code ${c.exitCode}: ${c.stderr}`)}async function ri(t,e,r,n,i,o,s){let c=(0,ze.dirname)(r),u=(0,ze.basename)(r),l=[];o||l.push("--quiet");let a=`${ei}:${t||"latest"}`,f=`${e}:/.cache`,p=`${c}:/tmp/output`,m=`${n.sbomFile}:/tmp/input.json`,d=`/tmp/output/${u}`,y=await Mt.$`docker run --rm -v ${f} -v ${p} -v ${m} ${a} sbom --cache-dir '/.cache' --format json --output ${d} ${l} --skip-db-update /tmp/input.json`.nothrow();if(y.stdout&&s(` Scan log: ${y.stdout}`),y.stderr&&s(` Scan error: ${y.stderr}`),y.exitCode!==0)throw new Error(`Trivy scan failed with exit code ${y.exitCode}: ${y.stderr}`);s(` Trivy output file: ${r}`);try{let h=await G(r);Ws(i,h)}catch(h){throw new Error(`Trivy scan results could not be read from '${r}': ${h}`,{cause:h})}}function Ws(t,e){if(e){for(let r of e.Results??[])if(r.Vulnerabilities)for(let n of r.Vulnerabilities){let i=Hs(n);t.addVulnerability(i,"trivy")}}}function Hs(t){let e=t.VulnerabilityID,r=J(t.PkgIdentifier.PURL),n=J(t.PrimaryURL),i=Ys(t.Severity);return{id:e,severity:i,scannerSeverity:{trivy:i},title:t.Title,description:t.Description,components:[r],detectedBy:["trivy"],refs:[n]}}function Ys(t){switch(t){case"UNKNOWN":case"LOW":case"MEDIUM":case"HIGH":case"CRITICAL":return t;default:return"UNKNOWN"}}var Ze=class{constructor(e,r,n){this.scanners=e;this.cacheDir=r;this.options=n}async init(e){let r=[];for(let n of this.scanners)switch(n.name){case"grype":r.push(Qn(n.version,this.cacheDir,e));break;case"trivy":r.push(ti(n.version,this.cacheDir,this.options.trivyGithubToken,e));break;case"ossindex":continue}await Promise.all(r)}async scanProject(e,r,n,i,o){let s=[];for(let c of this.scanners)s.push(this.scanProjectBy(c,e,r,this.cacheDir,n,this.options.ossIndexApiUser,this.options.ossIndexApiToken,i,o));await Promise.all(s)}async scanProjectBy(e,r,n,i,o,s,c,u,l){switch(e.name){case"grype":return Kn(e.version,i,await n.lookupOutputFileForWriting("grype-results"),r,o,u,l);case"trivy":return ri(e.version,i,await n.lookupOutputFileForWriting("trivy-results"),r,o,u,l);case"ossindex":return Zn(await n.lookupOutputFileForWriting("ossindex-results"),r,{user:s,token:c},o,u,l)}}};async function ni(t,e,r){await He(t,async n=>{let i=await n.read(),o=!1,s=i.statements,c=[];for(let u of s){if(r&&!It(u).has(r)||!u.products)continue;let l=u.products.findIndex(a=>a["@id"]===e);l!==-1&&(u.products.splice(l,1),o=!0,u.products.length===0&&c.push(u))}if(o){for(let u of c){let l=s.indexOf(u);s.splice(l,1)}if(s.length===0){console.info(`Remove ${e} from ${n.location} and delete file.`),await n.delete();return}console.info(`Remove ${e} from ${n.location}`),await n.write(i)}})}var ke=require("fs/promises"),Nt=require("path");async function oi(t,e){let{orderBy:r,reportNoLongerDetectedVulnerabilities:n,reportCveDetails:i,outputDirectory:o}={orderBy:"CVE",reportNoLongerDetectedVulnerabilities:!0,reportCveDetails:!1,...e},s=!1,c=!1,u=!1,l=new Map,a=new Map,f=new Map,p=new Map,m=new Map,d=[];for(let x of t.values()){let D=x.project,A=`${D.name}@${D.version}`;if(x.error&&(s=!0,d.push({project:A,error:x.error})),D.silent)continue;let Ee=X[D.minimumSeverity],rt=x.newVulns.filter(T=>Ee<=X[T.severity]);for(let T of rt){if(c=!0,!l.has(T.id))l.set(T.id,T);else{let S=l.get(T.id);ea(S,T)}a.has(T.id)||a.set(T.id,[]),p.has(A)||p.set(A,[]),p.get(A).push(T.id),a.get(T.id).push(A)}for(let T of x.noLongerDetectedVulns)u=!0,f.has(T)||f.set(T,[]),m.has(A)||m.set(A,[]),m.get(A).push(T),f.get(T).push(A)}let y;o&&(y=(0,Nt.join)(o,"scan-summary.txt"),await(0,ke.writeFile)(y,"","utf8"));let h=async x=>{console.log(x),y&&await(0,ke.appendFile)(y,x+`
|
|
41
39
|
`,"utf8")};switch(await h("=== Scan summary ==="),d.length&&await Qs(h,d),i&&await Zs(h,l),r){case"CVE":{await zs(h,a,l,n?f:new Map);break}case"PROJECT":{await Ks(h,p,n?m:new Map,l);break}}!s&&!c&&(!u||!n)&&await h(" No issues found");let w={errors:d,vulnerabilities:Object.fromEntries(l),vulnerabilityToProject:Object.fromEntries(a.entries()),projectToVulnerability:Object.fromEntries(p.entries()),noLongerDetectedVulnerabilities:Object.fromEntries(f)};if(o){let x=(0,Nt.join)(o,"scan-summary.json");await(0,ke.writeFile)(x,JSON.stringify(w,null,2),"utf8")}return{hasError:s,hasNewVuln:c,hasNoLongerDetectedVuln:u}}async function Qs(t,e){await t(""),await t("- Errors during scan:");for(let{project:r,error:n}of e)await t(` - ${r}:`),await t(` Error: ${n}`)}async function Ks(t,e,r,n){let i=new Set([...Array.from(e.keys()),...Array.from(r.keys())]),o=Array.from(i.keys()).sort();if(o.length){await t(""),await t("- Vulnerabilities by project:");for(let s of o){await t(` - ${s}:`);let c=e.get(s)??[];for(let l of c.slice().sort(Rt(a=>n.get(a).severity))){let{severity:a}=n.get(l);await t(` - [${a}] ${l}`)}let u=(r.get(s)??[]).slice().sort();for(let l of u)await t(` - ${l} (no longer detected)`)}}}async function zs(t,e,r,n){let i=Array.from(e.keys()).sort(Rt(s=>r.get(s).severity));if(i.length){await t(""),await t("- New vulnerabilities:");for(let s of i){let c=e.get(s),{severity:u}=r.get(s);await t(` - [${u}] ${s}`);for(let l of c.slice().sort())await t(` - ${l}`)}}let o=Array.from(n.keys()).sort();if(o.length){await t(""),await t("- Declared but no longer detected vulnerabilities:");for(let s of o){let c=n.get(s);await t(` - ${s}`);for(let u of c.slice().sort())await t(` - ${u}`)}}}async function Zs(t,e){if(e.size===0)return;await t(""),await t("- Vulnerability details:");let r=Array.from(e.keys()).sort(Rt(n=>e.get(n).severity));for(let n of r){let i=e.get(n);if(await t(` - [${i.severity}] ${i.id} - ${i.title||""}:`),i.description){await t(" Description:");let o=i.description.split(/\r?\n/);for(let s of o)await t(` ${s}`)}if(i.components.length){await t(" Components:");for(let o of i.components)await t(" - "+o);if(i.componentTree){await t(" Usage Tree:");for(let o of i.componentTree)await t(Pe(o," "))}}if(i.refs.length){await t(" Links:");for(let o of i.refs)await t(` - ${o}`)}}}function ea(t,e){t.title=t.title||e.title,t.severity=X[t.severity]>X[e.severity]?t.severity:e.severity,t.description=t.description||e.description,t.components=ii(t.components,e.components),t.refs=ii(t.refs,e.refs)}function ii(t,e){let r=new Set([...t,...e]);return Array.from(r)}function Rt(t){return(e,r)=>{let n=t(e),i=t(r),o=X[n],s=X[i];return o!==s?o>s?-1:1:e.localeCompare(r)}}et.os.type().startsWith("Windows")&&(0,et.usePowerShell)();async function si(t){let e=await lt(t),r=e.cacheDir;await oe(r)||await(0,ce.mkdir)(r);let n=e.outDir;await oe(n)&&await at(n),await(0,ce.mkdir)(n);let i=await ia(e,{user:t.vexUrlsUser,pw:t.vexUrlsPw}),o=new Ge(e.mavenRepo,{user:t.mavenRepoUser,pw:t.mavenRepoPw}),s=oa(e,t,r),c=Date.now();console.log("Initializing scanner engines ..."),await s.init(t.verbose),console.log(`Scanner engines initialization took ${Date.now()-c}ms
|
|
42
40
|
`);let u=sa(t),l=e.projects,a=new Map,f=Date.now();console.log("Scanning projects ...");let p=l.filter(u).map(d=>{let y=new Ye(d,n,e.createSubDirsForProject),h=[],w=D=>{h.push(D)};return{scan(){return ta(d,y,o,s,i,w,a,t,h)}}});await ca(p),console.log(`Scanning took ${Date.now()-f}ms`),t.autoRemoveUnusedStatements&&await aa(a,e.vexDir);let m=await oi(a,{orderBy:e.consoleReport.startsWith("BY_CVE")?"CVE":"PROJECT",reportCveDetails:e.consoleReport.endsWith("_DETAILED"),reportNoLongerDetectedVulnerabilities:e.reportNoLongerDetectedVulnerabilities,outputDirectory:n});if(m.hasError)return 1;if(m.hasNewVuln){if(e.onNewVulnerabilities==="fail")return 1;e.onNewVulnerabilities==="warn"&&(console.log("##vso[task.logissue type=warning;]NEW_VULNERABILITIES_DETECTED"),console.log("##vso[task.complete result=SucceededWithIssues;]"))}if(m.hasNoLongerDetectedVuln){if(e.onNoLongerDetectedVulnerabilities==="fail")return 1;e.onNoLongerDetectedVulnerabilities==="warn"&&(console.log("##vso[task.logissue type=warning;]NO_LONGER_DETECTED_VULNERABILITIES"),console.log("##vso[task.complete result=SucceededWithIssues;]"))}return 0}async function ta(t,e,r,n,i,o,s,c,u){try{let{unmatchedVulnerabilities:l,noLongerDetectedVulnerabilities:a}=await ra(t,e,r,n,i,c.verbose,o);s.set(t.purl,{project:t,newVulns:l,noLongerDetectedVulns:a})}catch(l){let a=l;s.set(t.purl,{project:t,error:`${a}`,newVulns:[],noLongerDetectedVulns:[]})}if(c.verbose)for(let l of u)console.log(l)}async function ra(t,e,r,n,i,o,s){let c=await Wn(t,await e.lookupOutputFileForWriting("project-cyclonedx-sbom-file"),r);s(`Analyzing project: ${c.name} - ${c.version} - ${c.sbomFile}`);let u=await G(c.sbomFile),l=new De(Xe.createForSbom(u));await n.scanProject(c,e,l,o,s);let a=i.filterByProduct([c.purl,...c.purlAliases]),{unmatchedVulnerabilities:f}=l.enhanceWithVexData(a),p=c.detectNoLongerUsedVulnerabilities?a.findNotMatchingVulnerabilities(l.getAllVulnIds()):[];return await na(e,c,l,a,s),{unmatchedVulnerabilities:f,noLongerDetectedVulnerabilities:p}}async function na(t,e,r,n,i){let o=r.getAllVulnerabilitiesSortedBySeverity(),s=await t.lookupOutputFileForWriting("aggregate-results");await(0,ce.writeFile)(s,JSON.stringify(o,null,2)),i(` Vulnerabilities output file: ${s}`);let c=await t.lookupOutputFileForWriting("aggregated-sarif-results"),u=Jn(o,e);await(0,ce.writeFile)(c,JSON.stringify(u,null,2)),i(` Vuln Sarif output file: ${c}`);let l=n.toVexFile(o.filter(f=>f.vexStatement).map(f=>{let p=f.vexStatement;for(let m of f.components??[])p.products.push({"@id":m});return p}));if(!l)return;let a=await t.lookupOutputFileForWriting("project-openvex-file");await(0,ce.writeFile)(a,JSON.stringify(l,null,2)),i(` OpenVex file: ${a}`)}async function ia(t,e){let r=t.vexDir,n;await oe(r)?n=await de.fromFiles(r):n=new de;for(let i of t.vexUrls)await de.fromUrl(i,e,n);return n}function oa(t,e,r){if(e.scannerEngine)return e.scannerEngine;if(t.scanners.length===0)throw new Error("No scanners configured");return new Ze(t.scanners,r,e)}function sa(t){let{reduceToProjectName:e,reduceToProjectVersion:r}=t;return n=>!(!n.enabled||e&&(n.name!==e||r&&n.version!==r))}async function aa(t,e){for(let r of t.values())if(!r.project.silent)for(let n of r.noLongerDetectedVulns)await ni(e,r.project.purl,n)}async function ca(t,e=5){let r=0,n=0,i=0,o=t.length,s,c=new Promise(l=>{s=l});function u(){for(;r<e&&i<o;){let l=t[i++];r++,l.scan().finally(()=>{r--,n++,n>=o?s():u()})}}u(),await c}var ai=require("zx");ai.dotenv.config();var z=process.env;(async()=>{let t=await si({workingDir:process.cwd(),reduceToProjectName:process.argv[2],reduceToProjectVersion:process.argv[3],ossIndexApiUser:z.OSS_INDEX_API_USER,ossIndexApiToken:z.OSS_INDEX_API_TOKEN,mavenRepoUser:z.MAVEN_REPO_USER,mavenRepoPw:z.MAVEN_REPO_PW,trivyGithubToken:z.TRIVY_GITHUB_TOKEN,vexUrlsUser:z.VEX_URLS_USER,vexUrlsPw:z.VEX_URLS_PW,verbose:z.VERBOSE==="true",autoRemoveUnusedStatements:z.AUTO_REMOVE_UNUSED_STATEMENTS==="true"});process.exitCode=t})();
|