forked from phcode-dev/staging.phcode.dev
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathVulnerabilityInspection.js
More file actions
1 lines (1 loc) · 4.64 KB
/
Copy pathVulnerabilityInspection.js
File metadata and controls
1 lines (1 loc) · 4.64 KB
1
define(function(require,exports,module){const CodeInspection=require("language/CodeInspection"),StringUtils=require("utils/StringUtils"),Strings=require("strings"),semver=require("thirdparty/semver.browser"),NpmRegistry=require("./NpmRegistry"),NpmHints=require("./NpmHints"),PACKAGE_JSON_RE=/(^|\/)package\.json$/,MAX_ADVISORIES_PER_DEP=3,MAX_DEPS_PER_SCAN=150,_resultsByPath=new Map,_refreshing=new Map;function _matchBrace(text,openBrace){let depth=0,i=openBrace;for(;i<text.length;){const ch=text[i];if('"'===ch)for(i++;i<text.length&&'"'!==text[i];)i+="\\"===text[i]?2:1;else if("{"===ch)depth++;else if("}"===ch&&0===--depth)return i+1;i++}return-1}function _findDependencyRanges(text){const lineStarts=[0];for(let i=0;i<text.length;i++)"\n"===text[i]&&lineStarts.push(i+1);function toPos(offset){let low=0,high=lineStarts.length-1;for(;low<high;){const mid=Math.floor((low+high+1)/2);lineStarts[mid]<=offset?low=mid:high=mid-1}return{line:low,ch:offset-lineStarts[low]}}const results=[];return NpmHints.DEP_SECTIONS.forEach(function(section){const keyIdx=text.indexOf('"'+section+'"');if(-1===keyIdx)return;const openBrace=text.indexOf("{",keyIdx);if(-1===openBrace)return;const endIdx=_matchBrace(text,openBrace);if(-1===endIdx)return;const slice=text.slice(openBrace,endIdx),entryRe=/"((?:[^"\\]|\\.)+)"\s*:\s*"((?:[^"\\]|\\.)*)"/g;let match;for(;null!==(match=entryRe.exec(slice));)results.push({name:match[1],range:match[2],section:section,pos:toPos(openBrace+match.index),endPos:toPos(openBrace+match.index+match[0].length)})}),results}function _severityToType(severity){switch(severity){case"critical":case"high":return CodeInspection.Type.ERROR;case"moderate":return CodeInspection.Type.WARNING;default:return CodeInspection.Type.META}}function _severityLabel(severity){switch(severity){case"critical":return Strings.NPM_SEVERITY_CRITICAL;case"high":return Strings.NPM_SEVERITY_HIGH;case"moderate":return Strings.NPM_SEVERITY_MODERATE;default:return Strings.NPM_SEVERITY_LOW}}const SEVERITY_ORDER={critical:0,high:1,moderate:2,low:3};function _errorsForEntry(entry,resolvedVersion,advisories){const seen=new Set;return advisories.filter(function(advisory){return!seen.has(advisory.id)&&(seen.add(advisory.id),!0)}).sort(function(a,b){const rankA=a.severity in SEVERITY_ORDER?SEVERITY_ORDER[a.severity]:9,rankB=b.severity in SEVERITY_ORDER?SEVERITY_ORDER[b.severity]:9;return rankA-rankB}).slice(0,MAX_ADVISORIES_PER_DEP).map(function(advisory){return{pos:entry.pos,endPos:entry.endPos,message:StringUtils.format(Strings.NPM_VULN_MESSAGE,entry.name,resolvedVersion,advisory.title,_severityLabel(advisory.severity)),type:_severityToType(advisory.severity)}})}function _depHash(entries){return entries.map(function(e){return e.name+"@"+e.range}).join("|")}async function _computeErrors(entries){const resolved=[];for(const entry of entries)if(semver.validRange(entry.range))try{const info=await NpmRegistry.getVersions(entry.name),version=semver.maxSatisfying(info.versions,entry.range);version&&resolved.push({entry:entry,version:version})}catch(e){}if(!resolved.length)return[];const advisoryMap=await NpmRegistry.getAdvisoriesBulk(resolved.map(function(r){return{name:r.entry.name,version:r.version}})),errors=[];return resolved.forEach(function(r){const advisories=advisoryMap[r.entry.name];advisories&&advisories.length&&errors.push.apply(errors,_errorsForEntry(r.entry,r.version,advisories))}),errors}function _refreshInBackground(text,fullPath){let entries=_findDependencyRanges(text);entries.length>MAX_DEPS_PER_SCAN&&(entries=entries.slice(0,MAX_DEPS_PER_SCAN));const depHash=_depHash(entries),cached=_resultsByPath.get(fullPath);cached&&cached.depHash===depHash||_refreshing.get(fullPath)||(_refreshing.set(fullPath,!0),_computeErrors(entries).then(function(errors){const previous=_resultsByPath.get(fullPath);_resultsByPath.set(fullPath,{depHash:depHash,errors:errors});const changed=!previous||JSON.stringify(previous.errors)!==JSON.stringify(errors);changed&&CodeInspection.requestRun()}).catch(function(){}).finally(function(){_refreshing.delete(fullPath)}))}function _scanFileAsync(text,fullPath){const deferred=new $.Deferred;if(!PACKAGE_JSON_RE.test(fullPath))return deferred.resolve(),deferred.promise();try{JSON.parse(text)}catch(e){return deferred.resolve(),deferred.promise()}_refreshInBackground(text,fullPath);const cached=_resultsByPath.get(fullPath);return deferred.resolve(cached&&cached.errors.length?{errors:cached.errors}:void 0),deferred.promise()}function init(){CodeInspection.register("json",{name:Strings.NPM_VULN_PROVIDER_NAME,scanFileAsync:_scanFileAsync})}exports.init=init,exports._findDependencyRanges=_findDependencyRanges,exports._errorsForEntry=_errorsForEntry,exports._severityToType=_severityToType});