thuban 0.4.1 → 0.4.3

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.
Files changed (35) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/package.json +63 -0
  3. package/dist/packages/crucible/banner.js +1 -1
  4. package/dist/packages/crucible/rule-loader.js +1 -1
  5. package/dist/packages/crucible/rules/code-scanner-core.json +147 -0
  6. package/dist/packages/crucible/rules/command-injection.json +411 -0
  7. package/dist/packages/crucible/rules/crypto-misuse.json +35 -0
  8. package/dist/packages/crucible/rules/deserialization.json +152 -0
  9. package/dist/packages/crucible/rules/env-injection.json +46 -0
  10. package/dist/packages/crucible/rules/eval-abuse.json +104 -0
  11. package/dist/packages/crucible/rules/file-upload.json +46 -0
  12. package/dist/packages/crucible/rules/hallucination.json +22 -0
  13. package/dist/packages/crucible/rules/hardcoded-secret.json +397 -0
  14. package/dist/packages/crucible/rules/hardcoded-url.json +13 -0
  15. package/dist/packages/crucible/rules/insecure-crypto.json +302 -0
  16. package/dist/packages/crucible/rules/integer-overflow.json +35 -0
  17. package/dist/packages/crucible/rules/log-injection.json +33 -0
  18. package/dist/packages/crucible/rules/mass-assignment.json +112 -0
  19. package/dist/packages/crucible/rules/open-redirect.json +196 -0
  20. package/dist/packages/crucible/rules/path-traversal.json +422 -0
  21. package/dist/packages/crucible/rules/prototype-pollution.json +22 -0
  22. package/dist/packages/crucible/rules/sql-injection.json +619 -0
  23. package/dist/packages/crucible/rules/ssrf.json +557 -0
  24. package/dist/packages/crucible/rules/timing-attack.json +55 -0
  25. package/dist/packages/crucible/rules/unsafe-block.json +24 -0
  26. package/dist/packages/crucible/rules/xss.json +663 -0
  27. package/dist/packages/crucible/rules/xxe.json +66 -0
  28. package/dist/packages/crucible/rules/yaml-deserialization.json +22 -0
  29. package/dist/packages/crucible/rules/yaml-injection.json +22 -0
  30. package/dist/packages/scanner/drift-detector.js +1 -1
  31. package/dist/packages/scanner/export-verifier.js +1 -1
  32. package/dist/packages/scanner/license-manager.js +1 -1
  33. package/dist/packages/scanner/monitor-service.js +1 -1
  34. package/dist/packages/scanner/taint-tracker.js +1 -1
  35. package/package.json +4 -2
@@ -1 +1 @@
1
- "use strict";const NO_COLOR=void 0!==process.env.NO_COLOR,IS_TTY=!!process.stdout.isTTY,COLORTERM=(process.env.COLORTERM||"").toLowerCase(),TERM=(process.env.TERM||"").toLowerCase(),HAS_TRUECOLOR=!NO_COLOR&&IS_TTY&&("truecolor"===COLORTERM||"24bit"===COLORTERM),HAS_256=!NO_COLOR&&IS_TTY&&(HAS_TRUECOLOR||TERM.includes("256color")||"256color"===COLORTERM),HAS_COLOR=!NO_COLOR&&IS_TTY&&(HAS_TRUECOLOR||HAS_256||""!==TERM||""!==COLORTERM);function _c(E,e,r){return HAS_COLOR?HAS_TRUECOLOR&&E?E:HAS_256&&e?e:r||"":""}const RESET=HAS_COLOR?"":"",BOLD=HAS_COLOR?"":"",DIM=HAS_COLOR?"":"",UNDER=HAS_COLOR?"":"",BLUE=_c("","",""),PURPLE=_c("","",""),RED=_c("","",""),GREEN=_c("","",""),AMBER=_c("","",""),WHITE=HAS_COLOR?"":"",DBLUE=HAS_COLOR?HAS_256?DIM+BLUE:DIM+"":"",GRAY=HAS_COLOR?"":"",YELLOW=AMBER,ORANGE=AMBER,CYAN=BLUE,SEP_WIDTH=58,SEP_CHAR="─";function _sep(){return DBLUE+" "+"─".repeat(58)+RESET}function statusTag(E,e){return GRAY+"[ "+RESET+(e||WHITE)+BOLD+E+RESET+GRAY+" ]"+RESET}const TAG_DONE=statusTag("DONE",GREEN),TAG_ACTIVE=statusTag("ACTIVE",AMBER),TAG_RUNNING=statusTag("RUNNING",PURPLE),TAG_WAITING=statusTag("WAITING",GRAY+DIM),TAG_DEFLECTED=statusTag("DEFLECTED",GREEN),TAG_MUTATED=statusTag("MUTATED",RED),TAG_PASS=statusTag("PASS",GREEN),TAG_FAIL=statusTag("FAIL",RED),TAG_BREACH=statusTag("BREACH",RED),TAG_SURVIVED=statusTag("SURVIVED",GREEN),TAG_SKIP=statusTag("SKIP",GRAY+DIM);function renderInit(E={}){const e=E.version||"0.4.0",r=E.target||".",T=E.mode||"standard",n=null!=E.seed?"0x"+Number(E.seed).toString(16).toUpperCase().padStart(9,"0"):"0x000000000",R=[];return R.push(""),R.push(" "+WHITE+BOLD+"🛡️ THUBAN CRUCIBLE"+RESET+DBLUE+" // "+RESET+WHITE+"v"+e+RESET),R.push(_sep()),R.push(" "+BLUE+BOLD+"[INIT]"+RESET+WHITE+" Target: "+RESET+WHITE+r+RESET),R.push(" "+BLUE+BOLD+"[INIT]"+RESET+WHITE+" Mode: "+RESET+WHITE+T+RESET),R.push(" "+BLUE+BOLD+"[INIT]"+RESET+WHITE+" Seed: "+RESET+WHITE+n+RESET+GRAY+" (Deterministic)"+RESET),R.push(""),R.join("\n")}function renderPhaseHeader(E){return"\n 🔨 "+WHITE+BOLD+(E||"THE CRUCIBLE IS BURNING...")+RESET+"\n"}function renderProgress(E,e,r={}){const T=_resolveTag(e),n=r.sub,R=r.last,t=(n||_padPhase(E),r.detail||"");if(n){const E=void 0!==r.emoji?r.emoji:"🧪";return DBLUE+" │ └─ "+RESET+GRAY+E+" "+RESET+WHITE+(r.subLabel||t)+RESET+(T?" "+_rightAlign(T,t?"":t):"")}const s=t?GRAY+t+RESET:"",A=T?" "+T:"";return(R?DBLUE+" └─ "+RESET:DBLUE+" ├─ "+RESET)+_padPhase(BLUE+BOLD+"["+E+"]"+RESET,E.length)+" "+s+A}function renderVerdict(E={}){const e=!1!==E.survived,r=_fmt(E.mutationsAttempted),T=_fmt(E.deflections),n=null!=E.breaches?E.breaches:0,R=E.reportPath||"",t=E.selfHeal||"",s=E.seedHex||"",A=null!=E.score?E.score:null,a=e?GREEN+BOLD+"CODEBASE SURVIVED THE CRUCIBLE."+RESET:RED+BOLD+"CODEBASE BREACHED — CRITICAL FAILURES DETECTED."+RESET,u=[];u.push(""),u.push(" 🏁 "+WHITE+BOLD+"[VERDICT]"+RESET+" "+a),u.push(_sep()),null!==r&&u.push(" 📦 "+WHITE+"Mutations Attempted: "+RESET+WHITE+BOLD+r+RESET),null!==T&&u.push(" 🛡️ "+WHITE+"Deflections: "+RESET+GREEN+BOLD+T+RESET);const o=n>0?RED+BOLD+String(n)+RESET+(t?GRAY+" ("+t+")"+RESET:""):GREEN+BOLD+"0"+RESET;if(u.push(" 💥 "+WHITE+"Critical Breaches: "+RESET+o),null!==A){const E=A>=90?GREEN:A>=70?AMBER:RED;u.push(" 🌟 "+WHITE+"Crucible Score: "+RESET+E+BOLD+A+"/100"+RESET)}return R&&u.push(" 📄 "+WHITE+"Report Generated: "+RESET+BLUE+UNDER+R+RESET),s&&u.push(" "+GRAY+"Seed: "+s+RESET),u.push(""),u.join("\n")}function fullBanner(E={}){return renderInit({version:E.version,target:E.targetPath||".",mode:E.level?"--level "+E.level:"standard",seed:E.seed})}function compactBanner(E){return"\n 🔥 "+WHITE+BOLD+"CRUCIBLE"+RESET+(E?" "+GRAY+"["+RESET+AMBER+E+RESET+GRAY+"]"+RESET:"")+"\n"}function scoreBanner(E,e){const r=scoreColor(E),T=e||scoreLabel(E),n=buildProgressBar(E,40);return[""," "+WHITE+BOLD+"Crucible Score"+RESET," "+r+n+RESET+" "+r+BOLD+E+"/100"+RESET+" "+GRAY+T+RESET,""].join("\n")}function sectionHeader(E,e){return"\n"+AMBER+" "+(e?e+" ":"")+BOLD+E+RESET+"\n"+GRAY+" "+"─".repeat(Math.min(60,E.length+4))+RESET+"\n"}function statusLine(E,e,r){return` ${E?GREEN+"✓"+RESET:RED+"✗"+RESET} ${DIM+e+RESET}${r?GRAY+" "+r+RESET:""}`}function summaryLine(E,e,r){const T=scoreColor(r),n=e-E;return["",` ${BOLD}Results:${RESET} ${GREEN}${E} passed${RESET} `+(n>0?RED+n+" failed"+RESET:DIM+"0 failed"+RESET)+" "+`${GRAY}(${e} total)${RESET}`,` ${BOLD}Score:${RESET} ${T}${BOLD}${r}/100${RESET}`,""].join("\n")}function plainBanner(){return[""," THUBAN CRUCIBLE"," "+"─".repeat(58)," The Fire Test for Security Scanners",""].join("\n")}const PHASE_WIDTH=12;function _padPhase(E,e){const r=null!=e?e:_stripAnsi(E).length,T=Math.max(0,PHASE_WIDTH-r);return E+" ".repeat(T)}function _stripAnsi(E){return E.replace(/\x1b\[[0-9;]*m/g,"")}function _resolveTag(E){switch((E||"").toUpperCase()){case"DONE":return TAG_DONE;case"ACTIVE":return TAG_ACTIVE;case"RUNNING":return TAG_RUNNING;case"WAITING":return TAG_WAITING;case"DEFLECTED":return TAG_DEFLECTED;case"MUTATED":return TAG_MUTATED;case"PASS":return TAG_PASS;case"FAIL":return TAG_FAIL;case"BREACH":return TAG_BREACH;case"SURVIVED":return TAG_SURVIVED;case"SKIP":return TAG_SKIP;default:return statusTag(E||"?",GRAY)}}function _rightAlign(E,e){return E}function _fmt(E){return null==E?null:Number(E).toLocaleString("en-US")}function buildProgressBar(E,e){const r=Math.round(E/100*e),T=e-r;return"["+"█".repeat(r)+"░".repeat(T)+"]"}function scoreColor(E){return HAS_COLOR?E>=90?GREEN:E>=70||E>=50?AMBER:RED:""}function scoreLabel(E){return E>=90?"Excellent":E>=70?"Good":E>=50?"Fair":E>=30?"Poor":"Critical"}function levelColor(E){if(!HAS_COLOR)return"";switch((E||"").toLowerCase()){case"gentle":return GREEN;case"medium":return AMBER;case"hell":return RED;default:return GRAY}}module.exports={renderInit:renderInit,renderPhaseHeader:renderPhaseHeader,renderProgress:renderProgress,renderVerdict:renderVerdict,statusTag:statusTag,fullBanner:fullBanner,compactBanner:compactBanner,scoreBanner:scoreBanner,sectionHeader:sectionHeader,statusLine:statusLine,summaryLine:summaryLine,plainBanner:plainBanner,scoreColor:scoreColor,scoreLabel:scoreLabel,TAG_DONE:TAG_DONE,TAG_ACTIVE:TAG_ACTIVE,TAG_RUNNING:TAG_RUNNING,TAG_WAITING:TAG_WAITING,TAG_DEFLECTED:TAG_DEFLECTED,TAG_MUTATED:TAG_MUTATED,TAG_PASS:TAG_PASS,TAG_FAIL:TAG_FAIL,TAG_BREACH:TAG_BREACH,TAG_SURVIVED:TAG_SURVIVED,TAG_SKIP:TAG_SKIP,colors:{RESET:RESET,BOLD:BOLD,DIM:DIM,UNDER:UNDER,BLUE:BLUE,PURPLE:PURPLE,RED:RED,GREEN:GREEN,AMBER:AMBER,WHITE:WHITE,GRAY:GRAY,DBLUE:DBLUE,YELLOW:AMBER,ORANGE:AMBER,CYAN:BLUE}};
1
+ "use strict";const _fs=require("fs"),_path=require("path");let _PKG_VERSION;try{_PKG_VERSION=JSON.parse(_fs.readFileSync(_path.join(__dirname,"..","..","package.json"),"utf-8")).version}catch(E){_PKG_VERSION="0.4.3"}const NO_COLOR=void 0!==process.env.NO_COLOR,IS_TTY=!!process.stdout.isTTY,COLORTERM=(process.env.COLORTERM||"").toLowerCase(),TERM=(process.env.TERM||"").toLowerCase(),HAS_TRUECOLOR=!NO_COLOR&&IS_TTY&&("truecolor"===COLORTERM||"24bit"===COLORTERM),HAS_256=!NO_COLOR&&IS_TTY&&(HAS_TRUECOLOR||TERM.includes("256color")||"256color"===COLORTERM),HAS_COLOR=!NO_COLOR&&IS_TTY&&(HAS_TRUECOLOR||HAS_256||""!==TERM||""!==COLORTERM);function _c(E,e,r){return HAS_COLOR?HAS_TRUECOLOR&&E?E:HAS_256&&e?e:r||"":""}const RESET=HAS_COLOR?"":"",BOLD=HAS_COLOR?"":"",DIM=HAS_COLOR?"":"",UNDER=HAS_COLOR?"":"",BLUE=_c("","",""),PURPLE=_c("","",""),RED=_c("","",""),GREEN=_c("","",""),AMBER=_c("","",""),WHITE=HAS_COLOR?"":"",DBLUE=HAS_COLOR?HAS_256?DIM+BLUE:DIM+"":"",GRAY=HAS_COLOR?"":"",YELLOW=AMBER,ORANGE=AMBER,CYAN=BLUE,SEP_WIDTH=58,SEP_CHAR="─";function _sep(){return DBLUE+" "+"─".repeat(58)+RESET}function statusTag(E,e){return GRAY+"[ "+RESET+(e||WHITE)+BOLD+E+RESET+GRAY+" ]"+RESET}const TAG_DONE=statusTag("DONE",GREEN),TAG_ACTIVE=statusTag("ACTIVE",AMBER),TAG_RUNNING=statusTag("RUNNING",PURPLE),TAG_WAITING=statusTag("WAITING",GRAY+DIM),TAG_DEFLECTED=statusTag("DEFLECTED",GREEN),TAG_MUTATED=statusTag("MUTATED",RED),TAG_PASS=statusTag("PASS",GREEN),TAG_FAIL=statusTag("FAIL",RED),TAG_BREACH=statusTag("BREACH",RED),TAG_SURVIVED=statusTag("SURVIVED",GREEN),TAG_SKIP=statusTag("SKIP",GRAY+DIM);function renderInit(E={}){const e=E.version||_PKG_VERSION,r=E.target||".",T=E.mode||"standard",n=null!=E.seed?"0x"+Number(E.seed).toString(16).toUpperCase().padStart(9,"0"):"0x000000000",t=[];return t.push(""),t.push(" "+WHITE+BOLD+"🛡️ THUBAN CRUCIBLE"+RESET+DBLUE+" // "+RESET+WHITE+"v"+e+RESET),t.push(_sep()),t.push(" "+BLUE+BOLD+"[INIT]"+RESET+WHITE+" Target: "+RESET+WHITE+r+RESET),t.push(" "+BLUE+BOLD+"[INIT]"+RESET+WHITE+" Mode: "+RESET+WHITE+T+RESET),t.push(" "+BLUE+BOLD+"[INIT]"+RESET+WHITE+" Seed: "+RESET+WHITE+n+RESET+GRAY+" (Deterministic)"+RESET),t.push(""),t.join("\n")}function renderPhaseHeader(E){return"\n 🔨 "+WHITE+BOLD+(E||"THE CRUCIBLE IS BURNING...")+RESET+"\n"}function renderProgress(E,e,r={}){const T=_resolveTag(e),n=r.sub,t=r.last,R=(n||_padPhase(E),r.detail||"");if(n){const E=void 0!==r.emoji?r.emoji:"🧪";return DBLUE+" │ └─ "+RESET+GRAY+E+" "+RESET+WHITE+(r.subLabel||R)+RESET+(T?" "+_rightAlign(T,R?"":R):"")}const s=R?GRAY+R+RESET:"",A=T?" "+T:"";return(t?DBLUE+" └─ "+RESET:DBLUE+" ├─ "+RESET)+_padPhase(BLUE+BOLD+"["+E+"]"+RESET,E.length)+" "+s+A}function renderVerdict(E={}){const e=!1!==E.survived,r=_fmt(E.mutationsAttempted),T=_fmt(E.deflections),n=null!=E.breaches?E.breaches:0,t=E.reportPath||"",R=E.selfHeal||"",s=E.seedHex||"",A=null!=E.score?E.score:null,a=e?GREEN+BOLD+"CODEBASE SURVIVED THE CRUCIBLE."+RESET:RED+BOLD+"CODEBASE BREACHED — CRITICAL FAILURES DETECTED."+RESET,S=[];S.push(""),S.push(" 🏁 "+WHITE+BOLD+"[VERDICT]"+RESET+" "+a),S.push(_sep()),null!==r&&S.push(" 📦 "+WHITE+"Mutations Attempted: "+RESET+WHITE+BOLD+r+RESET),null!==T&&S.push(" 🛡️ "+WHITE+"Deflections: "+RESET+GREEN+BOLD+T+RESET);const o=n>0?RED+BOLD+String(n)+RESET+(R?GRAY+" ("+R+")"+RESET:""):GREEN+BOLD+"0"+RESET;if(S.push(" 💥 "+WHITE+"Critical Breaches: "+RESET+o),null!==A){const E=A>=90?GREEN:A>=70?AMBER:RED;S.push(" 🌟 "+WHITE+"Crucible Score: "+RESET+E+BOLD+A+"/100"+RESET)}return t&&S.push(" 📄 "+WHITE+"Report Generated: "+RESET+BLUE+UNDER+t+RESET),s&&S.push(" "+GRAY+"Seed: "+s+RESET),S.push(""),S.join("\n")}function fullBanner(E={}){return renderInit({version:E.version,target:E.targetPath||".",mode:E.level?"--level "+E.level:"standard",seed:E.seed})}function compactBanner(E){return"\n 🔥 "+WHITE+BOLD+"CRUCIBLE"+RESET+(E?" "+GRAY+"["+RESET+AMBER+E+RESET+GRAY+"]"+RESET:"")+"\n"}function scoreBanner(E,e){const r=scoreColor(E),T=e||scoreLabel(E),n=buildProgressBar(E,40);return[""," "+WHITE+BOLD+"Crucible Score"+RESET," "+r+n+RESET+" "+r+BOLD+E+"/100"+RESET+" "+GRAY+T+RESET,""].join("\n")}function sectionHeader(E,e){return"\n"+AMBER+" "+(e?e+" ":"")+BOLD+E+RESET+"\n"+GRAY+" "+"─".repeat(Math.min(60,E.length+4))+RESET+"\n"}function statusLine(E,e,r){return` ${E?GREEN+"✓"+RESET:RED+"✗"+RESET} ${DIM+e+RESET}${r?GRAY+" "+r+RESET:""}`}function summaryLine(E,e,r){const T=scoreColor(r),n=e-E;return["",` ${BOLD}Results:${RESET} ${GREEN}${E} passed${RESET} `+(n>0?RED+n+" failed"+RESET:DIM+"0 failed"+RESET)+" "+`${GRAY}(${e} total)${RESET}`,` ${BOLD}Score:${RESET} ${T}${BOLD}${r}/100${RESET}`,""].join("\n")}function plainBanner(){return[""," THUBAN CRUCIBLE"," "+"─".repeat(58)," The Fire Test for Security Scanners",""].join("\n")}const PHASE_WIDTH=12;function _padPhase(E,e){const r=null!=e?e:_stripAnsi(E).length,T=Math.max(0,PHASE_WIDTH-r);return E+" ".repeat(T)}function _stripAnsi(E){return E.replace(/\x1b\[[0-9;]*m/g,"")}function _resolveTag(E){switch((E||"").toUpperCase()){case"DONE":return TAG_DONE;case"ACTIVE":return TAG_ACTIVE;case"RUNNING":return TAG_RUNNING;case"WAITING":return TAG_WAITING;case"DEFLECTED":return TAG_DEFLECTED;case"MUTATED":return TAG_MUTATED;case"PASS":return TAG_PASS;case"FAIL":return TAG_FAIL;case"BREACH":return TAG_BREACH;case"SURVIVED":return TAG_SURVIVED;case"SKIP":return TAG_SKIP;default:return statusTag(E||"?",GRAY)}}function _rightAlign(E,e){return E}function _fmt(E){return null==E?null:Number(E).toLocaleString("en-US")}function buildProgressBar(E,e){const r=Math.round(E/100*e),T=e-r;return"["+"█".repeat(r)+"░".repeat(T)+"]"}function scoreColor(E){return HAS_COLOR?E>=90?GREEN:E>=70||E>=50?AMBER:RED:""}function scoreLabel(E){return E>=90?"Excellent":E>=70?"Good":E>=50?"Fair":E>=30?"Poor":"Critical"}function levelColor(E){if(!HAS_COLOR)return"";switch((E||"").toLowerCase()){case"gentle":return GREEN;case"medium":return AMBER;case"hell":return RED;default:return GRAY}}module.exports={renderInit:renderInit,renderPhaseHeader:renderPhaseHeader,renderProgress:renderProgress,renderVerdict:renderVerdict,statusTag:statusTag,fullBanner:fullBanner,compactBanner:compactBanner,scoreBanner:scoreBanner,sectionHeader:sectionHeader,statusLine:statusLine,summaryLine:summaryLine,plainBanner:plainBanner,scoreColor:scoreColor,scoreLabel:scoreLabel,TAG_DONE:TAG_DONE,TAG_ACTIVE:TAG_ACTIVE,TAG_RUNNING:TAG_RUNNING,TAG_WAITING:TAG_WAITING,TAG_DEFLECTED:TAG_DEFLECTED,TAG_MUTATED:TAG_MUTATED,TAG_PASS:TAG_PASS,TAG_FAIL:TAG_FAIL,TAG_BREACH:TAG_BREACH,TAG_SURVIVED:TAG_SURVIVED,TAG_SKIP:TAG_SKIP,colors:{RESET:RESET,BOLD:BOLD,DIM:DIM,UNDER:UNDER,BLUE:BLUE,PURPLE:PURPLE,RED:RED,GREEN:GREEN,AMBER:AMBER,WHITE:WHITE,GRAY:GRAY,DBLUE:DBLUE,YELLOW:AMBER,ORANGE:AMBER,CYAN:BLUE}};
@@ -1 +1 @@
1
- "use strict";const fs=require("fs"),path=require("path"),RULES_DIR=path.join(__dirname,"rules"),MAX_PATTERN_LENGTH=500,MAX_QUANTIFIERS=20,MAX_ALTERNATIONS=30;function _checkRegexComplexity(e){if("string"!=typeof e||!e)return{safe:!1,reason:"pattern must be a non-empty string"};if(e.length>500)return{safe:!1,reason:"pattern exceeds max length of 500"};let t=0,n=0;const r=[];for(let a=0;a<e.length;a++){const s=e[a];if("\\"!==s)if("("!==s){if(")"===s){const n=r.pop();if(!n)continue;const s=/^\{\d+(,\d*)?\}/.exec(e.slice(a+1)),i=e[a+1];if("+"===i||"*"===i||"?"===i||s){if(t++,n.hasQuantifier||n.hasAlternation)return{safe:!1,reason:"nested quantifier detected (potential catastrophic backtracking)"};r.length>0&&(r[r.length-1].hasQuantifier=!0)}continue}if("+"!==s&&"*"!==s&&"?"!==s){if("{"===s){/^\{\d+(,\d*)?\}/.exec(e.slice(a))&&(t++,r.length>0&&(r[r.length-1].hasQuantifier=!0));continue}"|"!==s||(n++,r.length>0&&(r[r.length-1].hasAlternation=!0))}else t++,r.length>0&&(r[r.length-1].hasQuantifier=!0)}else r.push({hasQuantifier:!1,hasAlternation:!1});else a++}return t>20?{safe:!1,reason:`pattern has ${t} quantifiers, exceeding max of 20`}:n>30?{safe:!1,reason:`pattern has ${n} alternations, exceeding max of 30`}:{safe:!0,reason:null}}let _compiledPatterns=null;function getPatterns(){if(_compiledPatterns)return _compiledPatterns;const e=fs.readdirSync(RULES_DIR).filter(e=>e.endsWith(".json")).sort(),t=[];for(const n of e){const e=path.join(RULES_DIR,n);let r;try{const t=fs.readFileSync(e,"utf-8");r=JSON.parse(t)}catch(e){throw new Error(`[rule-loader] Failed to read/parse rule file "${n}": ${e.message}`)}if(!Array.isArray(r))throw new Error(`[rule-loader] Rule file "${n}" must export a JSON array, got: ${typeof r}`);for(const e of r){if(e.pattern){const t=_checkRegexComplexity(e.pattern);if(!t.safe){console.warn(`[rule-loader] WARNING: Skipping rule "${e.id}" in "${n}" — ${t.reason}`);continue}}let r,a;try{r=new RegExp(e.pattern,e.flags||"")}catch(t){throw new Error(`[rule-loader] Failed to compile rule "${e&&e.id}" in file "${n}": ${t.message}\n pattern: ${e&&e.pattern}\n flags: ${e&&e.flags}`)}if(e.context)try{a=new RegExp(e.context,e.contextFlags||"")}catch(t){throw new Error(`[rule-loader] Failed to compile context for rule "${e&&e.id}" in file "${n}": ${t.message}`)}t.push({regex:r,category:e.category,id:e.id,description:e.description,language:e.language,severity:e.severity,name:e.name,type:e.type,message:e.message,context:a,skipIfSafe:e.skipIfSafe,skipInTests:e.skipInTests,sourceFile:n})}}return _compiledPatterns=t,_compiledPatterns}function getCodeScannerPatterns(){return getPatterns().filter(e=>"code-scanner-core.json"===e.sourceFile).map(e=>{const t={id:e.id,name:e.name,type:e.type,pattern:e.regex,severity:e.severity,message:e.message};return e.context&&(t.context=e.context),e.skipIfSafe&&(t.skipIfSafe=!0),e.skipInTests&&(t.skipInTests=!0),t})}module.exports={getPatterns:getPatterns,getCodeScannerPatterns:getCodeScannerPatterns};
1
+ "use strict";const fs=require("fs"),path=require("path"),RULES_DIR=path.join(__dirname,"rules"),MAX_PATTERN_LENGTH=500,MAX_QUANTIFIERS=20,MAX_ALTERNATIONS=30;function _checkRegexComplexity(e){if("string"!=typeof e||!e)return{safe:!1,reason:"pattern must be a non-empty string"};if(e.length>500)return{safe:!1,reason:"pattern exceeds max length of 500"};let t=0,n=0;const r=[];for(let s=0;s<e.length;s++){const a=e[s];if("\\"!==a)if("("!==a){if(")"===a){const n=r.pop();if(!n)continue;const a=/^\{\d+(,\d*)?\}/.exec(e.slice(s+1)),i=e[s+1];if("+"===i||"*"===i||"?"===i||a){if(t++,n.hasQuantifier)return{safe:!1,reason:"nested quantifier detected (potential catastrophic backtracking)"};r.length>0&&(r[r.length-1].hasQuantifier=!0)}continue}if("+"!==a&&"*"!==a&&"?"!==a){if("{"===a){/^\{\d+(,\d*)?\}/.exec(e.slice(s))&&(t++,r.length>0&&(r[r.length-1].hasQuantifier=!0));continue}"|"!==a||(n++,r.length>0&&(r[r.length-1].hasAlternation=!0))}else t++,r.length>0&&(r[r.length-1].hasQuantifier=!0)}else{if("?"===e[s+1]){const t=e[s+2];":"===t||"="===t||"!"===t?s+=2:"<"===t&&(s+=3)}r.push({hasQuantifier:!1,hasAlternation:!1})}else s++}return t>20?{safe:!1,reason:`pattern has ${t} quantifiers, exceeding max of 20`}:n>30?{safe:!1,reason:`pattern has ${n} alternations, exceeding max of 30`}:{safe:!0,reason:null}}let _compiledPatterns=null;function getPatterns(){if(_compiledPatterns)return _compiledPatterns;const e=fs.readdirSync(RULES_DIR).filter(e=>e.endsWith(".json")).sort(),t=[];for(const n of e){const e=path.join(RULES_DIR,n);let r;try{const t=fs.readFileSync(e,"utf-8");r=JSON.parse(t)}catch(e){throw new Error(`[rule-loader] Failed to read/parse rule file "${n}": ${e.message}`)}if(!Array.isArray(r))throw new Error(`[rule-loader] Rule file "${n}" must export a JSON array, got: ${typeof r}`);for(const e of r){if(e.pattern){const t=_checkRegexComplexity(e.pattern);if(!t.safe){console.warn(`[rule-loader] WARNING: Skipping rule "${e.id}" in "${n}" — ${t.reason}`);continue}}let r,s;try{r=new RegExp(e.pattern,e.flags||"")}catch(t){throw new Error(`[rule-loader] Failed to compile rule "${e&&e.id}" in file "${n}": ${t.message}\n pattern: ${e&&e.pattern}\n flags: ${e&&e.flags}`)}if(e.context)try{s=new RegExp(e.context,e.contextFlags||"")}catch(t){throw new Error(`[rule-loader] Failed to compile context for rule "${e&&e.id}" in file "${n}": ${t.message}`)}t.push({regex:r,category:e.category,id:e.id,description:e.description,language:e.language,severity:e.severity,name:e.name,type:e.type,message:e.message,context:s,skipIfSafe:e.skipIfSafe,skipInTests:e.skipInTests,sourceFile:n})}}return _compiledPatterns=t,_compiledPatterns}function getCodeScannerPatterns(){return getPatterns().filter(e=>"code-scanner-core.json"===e.sourceFile).map(e=>{const t={id:e.id,name:e.name,type:e.type,pattern:e.regex,severity:e.severity,message:e.message};return e.context&&(t.context=e.context),e.skipIfSafe&&(t.skipIfSafe=!0),e.skipInTests&&(t.skipInTests=!0),t})}module.exports={getPatterns:getPatterns,getCodeScannerPatterns:getCodeScannerPatterns};
@@ -0,0 +1,147 @@
1
+ [
2
+ {
3
+ "id": "SEC001",
4
+ "name": "Hardcoded API Key",
5
+ "type": "hardcoded_secret",
6
+ "pattern": "['\"](?:sk-|pk-|xox[pboa]-|AKIA|ghp_|gho_|github_pat_)[a-zA-Z0-9_-]{10,}['\"]|['\"][a-zA-Z0-9]{32,}['\"]",
7
+ "flags": "",
8
+ "severity": "critical",
9
+ "message": "Possible hardcoded API key or secret detected",
10
+ "context": "(api[_-]?key|apikey|secret[_\\s]*key|token|credential|bearer)",
11
+ "contextFlags": "i",
12
+ "skipIfSafe": true
13
+ },
14
+ {
15
+ "id": "SEC001B",
16
+ "name": "Hardcoded API Key (bare)",
17
+ "type": "hardcoded_secret",
18
+ "pattern": "['\"](?:sk-|pk-|xox[pboa]-|AKIA|ghp_|gho_|github_pat_)[a-zA-Z0-9_-]{10,}['\"]",
19
+ "flags": "",
20
+ "severity": "critical",
21
+ "message": "Possible hardcoded API key or secret detected",
22
+ "skipIfSafe": true
23
+ },
24
+ {
25
+ "id": "SEC002",
26
+ "name": "Hardcoded Password",
27
+ "type": "hardcoded_secret",
28
+ "pattern": "password\\s*[:=]\\s*['\"][^'\"]+['\"]",
29
+ "flags": "i",
30
+ "severity": "critical",
31
+ "message": "Hardcoded password detected",
32
+ "skipIfSafe": true,
33
+ "skipInTests": true
34
+ },
35
+ {
36
+ "id": "SEC002B",
37
+ "name": "Hardcoded Password (JSON key)",
38
+ "type": "hardcoded_secret",
39
+ "pattern": "[\"']password[\"']\\s*:\\s*[\"'][^\"']+[\"']",
40
+ "flags": "i",
41
+ "severity": "critical",
42
+ "message": "Hardcoded password detected",
43
+ "skipIfSafe": true,
44
+ "skipInTests": true
45
+ },
46
+ {
47
+ "id": "SEC003",
48
+ "name": "SQL Injection Risk",
49
+ "type": "sql_injection",
50
+ "pattern": "\\b(?:SELECT|INSERT\\s+INTO|UPDATE|DELETE\\s+FROM|WHERE)\\b.*(\\$\\{|\\+\\s*['\"]|\\+\\s*\\w+|f['\"].*\\{|%s|%d)",
51
+ "flags": "i",
52
+ "severity": "error",
53
+ "message": "Potential SQL injection - use parameterized queries"
54
+ },
55
+ {
56
+ "id": "SEC004",
57
+ "name": "eval() Usage",
58
+ "type": "eval_abuse",
59
+ "pattern": "\\beval\\s*\\(",
60
+ "flags": "",
61
+ "severity": "error",
62
+ "message": "eval() is dangerous and should be avoided"
63
+ },
64
+ {
65
+ "id": "SEC004B",
66
+ "name": "eval() Usage (unicode-escaped)",
67
+ "type": "eval_abuse",
68
+ "pattern": "\\\\u0065\\\\u0076\\\\u0061\\\\u006[cC]",
69
+ "flags": "",
70
+ "severity": "error",
71
+ "message": "Obfuscated eval() usage (unicode escapes) is dangerous and should be avoided"
72
+ },
73
+ {
74
+ "id": "SEC005",
75
+ "name": "innerHTML/document.write Assignment",
76
+ "type": "xss",
77
+ "pattern": "\\.innerHTML\\s*=|\\bdocument\\.write\\s*\\(",
78
+ "flags": "",
79
+ "severity": "warning",
80
+ "message": "innerHTML/document.write can cause XSS - consider using textContent or sanitization"
81
+ },
82
+ {
83
+ "id": "SEC006",
84
+ "name": "Disabled Security",
85
+ "type": "insecure_config",
86
+ "pattern": "rejectUnauthorized\\s*:\\s*false|verify\\s*=\\s*False|InsecureSkipVerify\\s*:\\s*true",
87
+ "flags": "",
88
+ "severity": "error",
89
+ "message": "SSL certificate validation disabled"
90
+ },
91
+ {
92
+ "id": "SEC007",
93
+ "name": "Exposed .env Reference",
94
+ "type": "insecure_config",
95
+ "pattern": "\\.env['\"]",
96
+ "flags": "",
97
+ "severity": "warning",
98
+ "message": "Direct .env file manipulation - ensure not exposed",
99
+ "context": "fs\\.(read|write)|path\\.join|open\\s*\\(|os\\.Open",
100
+ "contextFlags": "i"
101
+ },
102
+ {
103
+ "id": "SEC008",
104
+ "name": "Unsafe Block (Rust)",
105
+ "type": "memory_safety",
106
+ "pattern": "\\bunsafe\\s*\\{",
107
+ "flags": "",
108
+ "severity": "warning",
109
+ "message": "Rust unsafe block - verify memory safety guarantees"
110
+ },
111
+ {
112
+ "id": "SEC009",
113
+ "name": "Shell Execution (PHP/Ruby/Python)",
114
+ "type": "command_injection",
115
+ "pattern": "\\bshell_exec\\s*\\(|\\bpassthru\\s*\\(|`[^`]+`|\\bos\\.system\\s*\\(|\\bos\\.popen\\s*\\(|\\bsubprocess\\.(?:call|run|Popen|check_output)\\s*\\([^)]*shell\\s*=\\s*True",
116
+ "flags": "",
117
+ "severity": "error",
118
+ "message": "Shell/OS execution function — command injection risk if input unsanitized"
119
+ },
120
+ {
121
+ "id": "SEC010",
122
+ "name": "Prototype Pollution",
123
+ "type": "prototype_pollution",
124
+ "pattern": "\\[\\s*['\"]__proto__['\"]\\s*\\]|\\.__proto__\\s*(=|\\[)|constructor\\s*\\[\\s*['\"]prototype['\"]\\s*\\]|constructor\\.prototype\\s*(=|\\[)|['\"]__proto__['\"]\\s*:",
125
+ "flags": "",
126
+ "severity": "error",
127
+ "message": "Possible prototype pollution via __proto__/constructor.prototype"
128
+ },
129
+ {
130
+ "id": "SEC011",
131
+ "name": "PHP SQL Injection (dot concatenation)",
132
+ "type": "sql_injection",
133
+ "pattern": "\"SELECT[^\"]*WHERE[^\"]*\"\\s*\\.\\s*\\$[a-zA-Z_]|\"UPDATE[^\"]*SET[^\"]*\"\\s*\\.\\s*\\$[a-zA-Z_]|\"DELETE[^\"]*WHERE[^\"]*\"\\s*\\.\\s*\\$[a-zA-Z_]|\\$(?:query|sql|qry)\\s*\\.=\\s*\\$(?:_GET|_POST|_REQUEST|_COOKIE)",
134
+ "flags": "i",
135
+ "severity": "critical",
136
+ "message": "PHP SQL injection: user input concatenated into SQL query with dot operator — use PDO prepared statements"
137
+ },
138
+ {
139
+ "id": "SEC012",
140
+ "name": "PHP XSS (echo with user input)",
141
+ "type": "xss",
142
+ "pattern": "echo\\s+(?!htmlspecialchars|htmlentities|strip_tags|esc_html).*\\$(?:_GET|_POST|_REQUEST|_COOKIE)|echo\\s+[\"'][^\"']*[\"']\\s*\\.\\s*\\$(?:_GET|_POST|_REQUEST|_COOKIE)|print\\s+\\$(?:_GET|_POST|_REQUEST|_COOKIE)",
143
+ "flags": "i",
144
+ "severity": "error",
145
+ "message": "PHP XSS: unescaped user input echoed to page — use htmlspecialchars()"
146
+ }
147
+ ]
@@ -0,0 +1,411 @@
1
+ [
2
+ {
3
+ "id": "CMD001",
4
+ "pattern": "exec(?:Sync|FileSync)?\\s*\\([^)]*\\+|os\\.system\\s*\\(|exec\\.Command\\s*\\([^)]*\\+",
5
+ "flags": "",
6
+ "category": "command_injection",
7
+ "description": "Command injection (original)",
8
+ "language": [
9
+ "js",
10
+ "ts",
11
+ "python",
12
+ "java",
13
+ "go",
14
+ "csharp",
15
+ "php",
16
+ "ruby",
17
+ "rust",
18
+ "kotlin"
19
+ ],
20
+ "severity": "critical"
21
+ },
22
+ {
23
+ "id": "CMD002",
24
+ "pattern": "spawn\\s*\\([^)]*shell\\s*:\\s*true",
25
+ "flags": "",
26
+ "category": "command_injection",
27
+ "description": "Command injection — JS/TS: spawn with shell:true, execa",
28
+ "language": [
29
+ "js",
30
+ "ts"
31
+ ],
32
+ "severity": "critical"
33
+ },
34
+ {
35
+ "id": "CMD003",
36
+ "pattern": "execa(?:\\.command)?\\s*\\(",
37
+ "flags": "",
38
+ "category": "command_injection",
39
+ "description": "Command injection — JS/TS: spawn with shell:true, execa",
40
+ "language": [
41
+ "js",
42
+ "ts"
43
+ ],
44
+ "severity": "critical"
45
+ },
46
+ {
47
+ "id": "CMD004",
48
+ "pattern": "subprocess\\s*\\.\\s*(?:call|check_output|Popen|run)\\s*\\([^)]*shell\\s*=\\s*True",
49
+ "flags": "",
50
+ "category": "command_injection",
51
+ "description": "Command injection — Python: subprocess variants with shell=True, os.popen, paramiko",
52
+ "language": [
53
+ "python"
54
+ ],
55
+ "severity": "critical"
56
+ },
57
+ {
58
+ "id": "CMD005",
59
+ "pattern": "os\\s*\\.\\s*popen\\s*\\(",
60
+ "flags": "",
61
+ "category": "command_injection",
62
+ "description": "Command injection — Python: subprocess variants with shell=True, os.popen, paramiko",
63
+ "language": [
64
+ "python"
65
+ ],
66
+ "severity": "critical"
67
+ },
68
+ {
69
+ "id": "CMD006",
70
+ "pattern": "\\.exec_command\\s*\\(",
71
+ "flags": "",
72
+ "category": "command_injection",
73
+ "description": "Command injection — Python: subprocess variants with shell=True, os.popen, paramiko",
74
+ "language": [
75
+ "python"
76
+ ],
77
+ "severity": "critical"
78
+ },
79
+ {
80
+ "id": "CMD007",
81
+ "pattern": "`[^`]*#\\{[^}]+\\}[^`]*`",
82
+ "flags": "",
83
+ "category": "command_injection",
84
+ "description": "Command injection — Ruby: backtick with interpolation, system, exec, Open3, IO.popen",
85
+ "language": [
86
+ "ruby"
87
+ ],
88
+ "severity": "critical"
89
+ },
90
+ {
91
+ "id": "CMD008",
92
+ "pattern": "\\b(?:system|exec)\\s*\\(\\s*[\"'`]?[^\"'`\\n]*#\\{|\\b(?:system|exec)\\s*\\(\\s*[\"'][^\"']*[\"']\\s*\\+",
93
+ "flags": "",
94
+ "category": "command_injection",
95
+ "description": "Command injection — Ruby: backtick with interpolation, system, exec, Open3, IO.popen",
96
+ "language": [
97
+ "ruby"
98
+ ],
99
+ "severity": "critical"
100
+ },
101
+ {
102
+ "id": "CMD009",
103
+ "pattern": "\\bIO\\.popen\\s*\\(|Open3\\.\\w+\\s*\\(",
104
+ "flags": "",
105
+ "category": "command_injection",
106
+ "description": "Command injection — Ruby: backtick with interpolation, system, exec, Open3, IO.popen",
107
+ "language": [
108
+ "ruby"
109
+ ],
110
+ "severity": "critical"
111
+ },
112
+ {
113
+ "id": "CMD010",
114
+ "pattern": "Runtime\\s*\\.\\s*getRuntime\\s*\\(\\s*\\)\\s*\\.\\s*exec\\s*\\(",
115
+ "flags": "",
116
+ "category": "command_injection",
117
+ "description": "Command injection — Java/Kotlin: Runtime.exec, ProcessBuilder",
118
+ "language": [
119
+ "kotlin",
120
+ "java"
121
+ ],
122
+ "severity": "critical"
123
+ },
124
+ {
125
+ "id": "CMD011",
126
+ "pattern": "new\\s+ProcessBuilder\\s*\\(",
127
+ "flags": "",
128
+ "category": "command_injection",
129
+ "description": "Command injection — Java/Kotlin: Runtime.exec, ProcessBuilder",
130
+ "language": [
131
+ "kotlin",
132
+ "java"
133
+ ],
134
+ "severity": "critical"
135
+ },
136
+ {
137
+ "id": "CMD012",
138
+ "pattern": "Process\\s*\\.\\s*Start\\s*\\(|new\\s+ProcessStartInfo\\s*[({]",
139
+ "flags": "",
140
+ "category": "command_injection",
141
+ "description": "Command injection — C#: Process.Start / ProcessStartInfo",
142
+ "language": [
143
+ "csharp"
144
+ ],
145
+ "severity": "critical"
146
+ },
147
+ {
148
+ "id": "CMD013",
149
+ "pattern": "Command\\s*::\\s*new\\s*\\(",
150
+ "flags": "",
151
+ "category": "command_injection",
152
+ "description": "Command injection — Rust: Command::new",
153
+ "language": [
154
+ "rust"
155
+ ],
156
+ "severity": "critical"
157
+ },
158
+ {
159
+ "id": "CMD014",
160
+ "pattern": "\\bshell_exec\\s*\\(|\\bpassthru\\s*\\(|\\bpopen\\s*\\(",
161
+ "flags": "",
162
+ "category": "command_injection",
163
+ "description": "Command injection — PHP: shell_exec, system, passthru, popen, backtick with variable",
164
+ "language": [
165
+ "php"
166
+ ],
167
+ "severity": "critical"
168
+ },
169
+ {
170
+ "id": "CMD015",
171
+ "pattern": "\\bsystem\\s*\\(\\s*[\"'][^\"']*[\"']\\s*\\.\\s*\\$|\\bsystem\\s*\\(\\s*\\$",
172
+ "flags": "",
173
+ "category": "command_injection",
174
+ "description": "Command injection — PHP: shell_exec, system, passthru, popen, backtick with variable",
175
+ "language": [
176
+ "php"
177
+ ],
178
+ "severity": "critical"
179
+ },
180
+ {
181
+ "id": "CMD016",
182
+ "pattern": "`[^`]*\\$(?:_GET|_POST|_REQUEST|_COOKIE|\\w+)[^`]*`",
183
+ "flags": "",
184
+ "category": "command_injection",
185
+ "description": "Command injection — PHP: shell_exec, system, passthru, popen, backtick with variable",
186
+ "language": [
187
+ "php"
188
+ ],
189
+ "severity": "critical"
190
+ },
191
+ {
192
+ "id": "CMD017",
193
+ "pattern": "exec\\s*\\.\\s*Command\\s*\\([^)]*fmt\\.Sprintf|exec\\s*\\.\\s*Command\\s*\\([^)]*parts\\b",
194
+ "flags": "",
195
+ "category": "command_injection",
196
+ "description": "Command injection — Go: exec.Command with fmt.Sprintf, user-split args, or /bin/sh -c pattern",
197
+ "language": [
198
+ "go"
199
+ ],
200
+ "severity": "critical"
201
+ },
202
+ {
203
+ "id": "CMD018",
204
+ "pattern": "exec\\s*\\.\\s*Command\\s*\\(\\s*[\"']\\/bin\\/(?:sh|bash)[\"']\\s*,\\s*[\"']-c[\"']",
205
+ "flags": "",
206
+ "category": "command_injection",
207
+ "description": "Command injection — Go: exec.Command with fmt.Sprintf, user-split args, or /bin/sh -c pattern",
208
+ "language": [
209
+ "go"
210
+ ],
211
+ "severity": "critical"
212
+ },
213
+ {
214
+ "id": "CMD019",
215
+ "pattern": "\\bexec\\s*\\(\\s*[\"'][^\"']*[\"']\\s*\\.\\s*\\$|\\bexec\\s*\\(\\s*\\$",
216
+ "flags": "",
217
+ "category": "command_injection",
218
+ "description": "Command injection — PHP: exec() with user input",
219
+ "language": [
220
+ "php"
221
+ ],
222
+ "severity": "critical"
223
+ },
224
+ {
225
+ "id": "CMD020",
226
+ "pattern": "ProcessStartInfo\\s*\\{[^}]*Arguments\\s*=\\s*\\$[\"']",
227
+ "flags": "i",
228
+ "category": "command_injection",
229
+ "description": "C# command injection: ProcessStartInfo / Process.Start with user input",
230
+ "language": [
231
+ "csharp"
232
+ ],
233
+ "severity": "critical"
234
+ },
235
+ {
236
+ "id": "CMD021",
237
+ "pattern": "Arguments\\s*=\\s*\\$[\"'][^\"']*\\{(?:host|cmd|args|input|filename|email|script)",
238
+ "flags": "i",
239
+ "category": "command_injection",
240
+ "description": "C# command injection: ProcessStartInfo / Process.Start with user input",
241
+ "language": [
242
+ "csharp"
243
+ ],
244
+ "severity": "critical"
245
+ },
246
+ {
247
+ "id": "CMD022",
248
+ "pattern": "new ProcessStartInfo\\s*\\(\\s*[\"'][^\"']*(?:bash|sh|cmd)[\"']",
249
+ "flags": "i",
250
+ "category": "command_injection",
251
+ "description": "C# command injection: ProcessStartInfo / Process.Start with user input",
252
+ "language": [
253
+ "csharp"
254
+ ],
255
+ "severity": "critical"
256
+ },
257
+ {
258
+ "id": "CMD023",
259
+ "pattern": "`[^`]*#\\{[^`]*`",
260
+ "flags": "",
261
+ "category": "command_injection",
262
+ "description": "Ruby command injection: backtick, system(), exec(), Open3, IO.popen",
263
+ "language": [
264
+ "ruby"
265
+ ],
266
+ "severity": "critical"
267
+ },
268
+ {
269
+ "id": "CMD024",
270
+ "pattern": "\\bsystem\\s*\\([^)]*#\\{",
271
+ "flags": "i",
272
+ "category": "command_injection",
273
+ "description": "Ruby command injection: backtick, system(), exec(), Open3, IO.popen",
274
+ "language": [
275
+ "ruby"
276
+ ],
277
+ "severity": "critical"
278
+ },
279
+ {
280
+ "id": "CMD025",
281
+ "pattern": "\\bexec\\s*\\([^)]*#\\{",
282
+ "flags": "i",
283
+ "category": "command_injection",
284
+ "description": "Ruby command injection: backtick, system(), exec(), Open3, IO.popen",
285
+ "language": [
286
+ "ruby"
287
+ ],
288
+ "severity": "critical"
289
+ },
290
+ {
291
+ "id": "CMD026",
292
+ "pattern": "Open3\\.capture2\\s*\\(.*(?:#\\{|cmd)",
293
+ "flags": "i",
294
+ "category": "command_injection",
295
+ "description": "Ruby command injection: backtick, system(), exec(), Open3, IO.popen",
296
+ "language": [
297
+ "ruby"
298
+ ],
299
+ "severity": "critical"
300
+ },
301
+ {
302
+ "id": "CMD027",
303
+ "pattern": "IO\\.popen\\s*\\([^)]*#\\{",
304
+ "flags": "i",
305
+ "category": "command_injection",
306
+ "description": "Ruby command injection: backtick, system(), exec(), Open3, IO.popen",
307
+ "language": [
308
+ "ruby"
309
+ ],
310
+ "severity": "critical"
311
+ },
312
+ {
313
+ "id": "CMD028",
314
+ "pattern": "\\bspawn\\s*\\([^)]*#\\{",
315
+ "flags": "i",
316
+ "category": "command_injection",
317
+ "description": "Ruby command injection: backtick, system(), exec(), Open3, IO.popen",
318
+ "language": [
319
+ "ruby"
320
+ ],
321
+ "severity": "critical"
322
+ },
323
+ {
324
+ "id": "CMD029",
325
+ "pattern": "\\bexec\\s*\\(\\s*[\"'][^\"']*[\"']?\\s*\\.\\s*\\$(?:_GET|_POST|host|cmd|ip)",
326
+ "flags": "i",
327
+ "category": "command_injection",
328
+ "description": "PHP command injection",
329
+ "language": [
330
+ "php"
331
+ ],
332
+ "severity": "critical"
333
+ },
334
+ {
335
+ "id": "CMD030",
336
+ "pattern": "shell_exec\\s*\\([^)]*\\$(?:_GET|_POST|domain|ip|host|cmd|server)",
337
+ "flags": "i",
338
+ "category": "command_injection",
339
+ "description": "PHP command injection",
340
+ "language": [
341
+ "php"
342
+ ],
343
+ "severity": "critical"
344
+ },
345
+ {
346
+ "id": "CMD031",
347
+ "pattern": "\\bsystem\\s*\\([^)]*\\$(?:_GET|_POST|src|dest|format|file)",
348
+ "flags": "i",
349
+ "category": "command_injection",
350
+ "description": "PHP command injection",
351
+ "language": [
352
+ "php"
353
+ ],
354
+ "severity": "critical"
355
+ },
356
+ {
357
+ "id": "CMD032",
358
+ "pattern": "passthru\\s*\\([^)]*\\$(?:_POST|_GET|archive|zip|dest)",
359
+ "flags": "i",
360
+ "category": "command_injection",
361
+ "description": "PHP command injection",
362
+ "language": [
363
+ "php"
364
+ ],
365
+ "severity": "critical"
366
+ },
367
+ {
368
+ "id": "CMD033",
369
+ "pattern": "popen\\s*\\(\\s*[\"'][^\"']*[\"']?\\s*\\.\\s*\\$(?:_GET|pattern|logfile)",
370
+ "flags": "i",
371
+ "category": "command_injection",
372
+ "description": "PHP command injection",
373
+ "language": [
374
+ "php"
375
+ ],
376
+ "severity": "critical"
377
+ },
378
+ {
379
+ "id": "CMD034",
380
+ "pattern": "exec\\.Command\\s*\\(\\s*[\"'][^\"']*(?:bash|sh)[\"'][^)]*\"-c\"",
381
+ "flags": "i",
382
+ "category": "command_injection",
383
+ "description": "Go command injection",
384
+ "language": [
385
+ "go"
386
+ ],
387
+ "severity": "critical"
388
+ },
389
+ {
390
+ "id": "CMD035",
391
+ "pattern": "exec\\.Command\\s*\\(\\s*[\"'][^\"']*(?:sh|bash)[\"'][^)]*cmdStr",
392
+ "flags": "i",
393
+ "category": "command_injection",
394
+ "description": "Go command injection",
395
+ "language": [
396
+ "go"
397
+ ],
398
+ "severity": "critical"
399
+ },
400
+ {
401
+ "id": "CMD036",
402
+ "pattern": "cmd\\s*:=\\s*exec\\.Command\\s*\\([^)]*\\+",
403
+ "flags": "i",
404
+ "category": "command_injection",
405
+ "description": "Go command injection",
406
+ "language": [
407
+ "go"
408
+ ],
409
+ "severity": "critical"
410
+ }
411
+ ]
@@ -0,0 +1,35 @@
1
+ [
2
+ {
3
+ "id": "CMISUSE001",
4
+ "pattern": "use\\s+md5\\b|md5::compute|ecb_encrypt|AesCipher|nonce\\s*=\\s*0\\b",
5
+ "flags": "i",
6
+ "category": "crypto_misuse",
7
+ "description": "crypto_misuse (Rust-specific)",
8
+ "language": [
9
+ "rust"
10
+ ],
11
+ "severity": "medium"
12
+ },
13
+ {
14
+ "id": "CMISUSE002",
15
+ "pattern": "\\bxor_encrypt\\b|\\bxor_decrypt\\b|\\brot13\\b|\\bcaesar_cipher\\b",
16
+ "flags": "i",
17
+ "category": "crypto_misuse",
18
+ "description": "Rust: crypto misuse (homegrown ciphers)",
19
+ "language": [
20
+ "rust"
21
+ ],
22
+ "severity": "medium"
23
+ },
24
+ {
25
+ "id": "CMISUSE003",
26
+ "pattern": "struct\\s+Rc4\\b|\\brc4\\b",
27
+ "flags": "i",
28
+ "category": "crypto_misuse",
29
+ "description": "Rust: crypto misuse (homegrown ciphers)",
30
+ "language": [
31
+ "rust"
32
+ ],
33
+ "severity": "medium"
34
+ }
35
+ ]