{"id":35765337,"url":"https://github.com/evex-dev/expose-kit","last_synced_at":"2026-01-18T02:25:42.780Z","repository":{"id":332412723,"uuid":"1127803205","full_name":"evex-dev/expose-kit","owner":"evex-dev","description":"A universal toolkit for deobfuscating JavaScript","archived":false,"fork":false,"pushed_at":"2026-01-07T19:29:50.000Z","size":198,"stargazers_count":12,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-13T19:57:41.506Z","etag":null,"topics":["deobfuscation","deobfuscator","javascript","obfuscator"],"latest_commit_sha":null,"homepage":"https://evex.land","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/evex-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-01-04T16:17:00.000Z","updated_at":"2026-01-12T10:27:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/evex-dev/expose-kit","commit_stats":null,"previous_names":["evex-dev/expose-kit"],"tags_count":33,"template":false,"template_full_name":null,"purl":"pkg:github/evex-dev/expose-kit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evex-dev%2Fexpose-kit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evex-dev%2Fexpose-kit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evex-dev%2Fexpose-kit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evex-dev%2Fexpose-kit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/evex-dev","download_url":"https://codeload.github.com/evex-dev/expose-kit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evex-dev%2Fexpose-kit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28526569,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T00:39:45.795Z","status":"online","status_checked_at":"2026-01-18T02:00:07.578Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deobfuscation","deobfuscator","javascript","obfuscator"],"created_at":"2026-01-07T01:16:40.961Z","updated_at":"2026-01-18T02:25:42.770Z","avatar_url":"https://github.com/evex-dev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Expose Kit\n![release workflow](https://github.com/evex-dev/linejs/actions/workflows/release.yml/badge.svg)\n[![](https://dcbadge.limes.pink/api/server/evex)](https://discord.gg/evex)\n\n\u003e A universal toolkit for JavaScript deobfuscation\n\n---\n\n## What is this?\n\nJavaScript deobfuscation tools are everywhere.  \nBut many of them are **too aggressive**, rewriting code until it breaks.\n\nExpose Kit takes a **different approach**.\n\n- No brute force\n- Step-by-step, verifiable transforms\n- Designed to *not* break your code silently\n\nEach transformation is meant to be **checked and validated**, so you always know *when* something goes wrong.\n\nAlongside deobfuscation, Expose Kit also provides a set of **practical utilities** for working with obfuscated JavaScript.\n\n---\n\n## Installation\n\nJust one step:\n\n```bash\nnpm i -g expose-kit\n# or\nbun i -g expose-kit\n```\n\n```bash\nexpose --help\nexpose parsable sample.js\n```\n\n---\n\n## Usage Notes\n\n### Default arguments\n\n- The first argument is the input file  \n  (`--file` / `--input` can also be used)\n- If required options are missing, Expose Kit will **prompt you**\n- A timeout is enabled by default to avoid hangs  \n  Use `--unlimited` for long-running execution\n\n---\n\n## Recommended Workflow\n\nFirst, an important premise:\n\n\u003e It is **impossible** to create a static deobfuscation tool that *never* breaks.\n\nReasons include:\n- Unpredictable execution (`eval`, dynamic code)\n- Bugs or edge cases in AST manipulation\n\nBecause of this, you should **verify the code at every step**.\n\n### 1. Always verify with `parsable`\n\nAfter each transformation, run:\n\n```bash\nexpose parsable file.js\n```\n\nThis ensures the syntax is still valid.\n\n---\n\n### 2. Make scopes safe first\n\nOne of the most common causes of breakage is **variable name confusion**.\n\nIf you try to write your own deobfuscation logic (e.g. in Python), you’ll quickly realize how painful it is to track scopes correctly.\n\nThat’s why you should **always start with**:\n\n```bash\nexpose safe-scope input.js\n```\n\nThis renames bindings per scope, producing code like:\n\n```js\nBefore: var x = 810;((x) =\u003e console.log(x))(114514);\nAfter:  var x = 810;((_x) =\u003e console.log(_x))(114514);\n```\n\nWith this alone:\n- The code becomes far more resistant to breakage\n- Writing custom deobfuscation logic becomes much easier\n- You no longer need to worry about scope collisions\n\n---\n\n### 3. Apply transforms step by step\n\nAfter `safe-scope`, combine common techniques like:\n- `expand-array`, `expand-object` and more\n\nAfter **each step**, run `parsable` and `remove-unused` again.   \n    (even if it's not frequent, we might overlook something broken)\n\nThe more you do it, the clearer it becomes.\n\nExpose Kit will also clearly indicate whether a **diff** exists, making inspection easy.\n\nRepeat this process, and the original code will gradually reveal itself.\n\n---\n\n## Commands\n\n### `expose parsable`\n\nCheck whether a file is syntactically valid.\n\n```js\nparsable:     const x = 810;\nnot parsable: const ;x; == 810;\n```\n\n```bash\nexpose parsable path/to/file.js\n```\n\nArgs:\n- Default args only\n\n---\n\n### `expose safe-scope`\n\nRename bindings per scope for safer transformations.\n\n```bash\nexpose safe-scope path/to/file.js --output path/to/file.safe-scope.js\n```\nExample is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/safe-scope/mocks).\n\nArgs:\n- `--o, --output \u003cfile\u003e`  \n  Output file path  \n  - No extension → `file.safe-scope.js`\n  - With extension → `file.safe-scope.\u003cext\u003e`\n\n---\n\n### `expose pre-evaluate`\n\nPre-evaluate const numeric/string expressions. (Safe evaluate)\n\n```js\nconst a = 1 + 2 * 3; // =\u003e 7\nconst c = \"aaaa\";\nconst b = \"a\" + c; // =\u003e \"aaaaa\"\n```\n\n```bash\nexpose pre-evaluate path/to/file.js --output path/to/file.pre-evaluate.js\n```\n\nArgs:\n- `--o, --output \u003cfile\u003e`  \n  Output file path  \n  - No extension → `file.pre-evaluate.js`\n  - With extension → `file.pre-evaluate.\u003cext\u003e`\n\nNotes:\n- Inlines zero-arg functions that return safe array literals by hoisting them to a var.\n\n---\n\n### `expose expand-array`\n\nExpand array index access for primitive values.\n```js\nvar a = [1, 1, 4, 5, 1, 4];\n// before\nconsole.log(a[0], a[2], a[3]);\n// after\nconsole.log(1, 4, 5);\n```\nExample is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/expand-array/mocks).\n\n```bash\nexpose expand-array path/to/file.js --target arrayName --output path/to/file.expand-array.js\n```\n\nArgs:\n- `--target \u003cname\u003e`  \n  Target array variable name\n- `--o, --output \u003cfile\u003e`  \n  Output file path  \n\nNotes:\n- Each replacement is validated by reparsing; unsafe replacements are skipped. \n    (This array is intended to be immutable, so caution is required)\n\n---\n\n### `expose expand-object`\n\nExpand object property access for primitive values.\n```js\nconst obj = { a: 1, b: 2 };\n// before\nconsole.log(obj.a, obj[\"b\"]);\n// after\nconsole.log(1, 2);\n```\nExample is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/expand-object/mocks).\n\n```bash\nexpose expand-object path/to/file.js --target objectName --output path/to/file.expand-object.js\n```\n\nArgs:\n- `--target \u003cname\u003e`  \n  Target object variable name\n- `--o, --output \u003cfile\u003e`  \n  Output file path  \n\nNotes:\n- Each replacement is validated by reparsing; unsafe replacements are skipped.\n    (This object is intended to be immutable, so caution is required)\n\n---\n\n### `expose object-packer`\n\nPack consecutive object property assignments into literals.\n```js\nconst obj = {};\n// before\nobj.a = 0;\nobj[\"b\"] = 1;\n// after\nconst obj = { a: 0, b: 1 };\n```\nExample is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/object-packer/mocks).\n\n```bash\nexpose object-packer path/to/file.js --output path/to/file.object-packer.js\n```\n\nArgs:\n- `--o, --output \u003cfile\u003e`  \n  Output file path  \n\nNotes:\n- Packs only consecutive assignments following an empty object literal.\n- Stops when a property value references the object itself.\n\n---\n\n### `expose key-simplify`\n\nReplace safe string literal property accesses (`obj[\"foo\"]`) with dot-style access (`obj.foo`).\n```js\nconst obj = { foo: 1, bar_baz: 2 };\nobj[\"foo\"] = obj['bar'];\nconsole.log(obj[\"foo\"], obj[\"bar_baz\"]);\n```\nExample is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/key-simplify/mocks).\n\n```bash\nexpose key-simplify path/to/file.js --output path/to/file.key-simplify.js\n```\n\nArgs:\n- `--o, --output \u003cfile\u003e`  \n  Output file path  \n\nNotes:\n- Only rewrites computed keys that are plain identifiers.\n- Leaves invalid identifier keys untouched so the output stays parseable.\n\n---\n\n### `expose remove-updater`\n\nReplace safe update expressions with += or -=.\n```js\n// before\na++;\n--b;\n// after\na += 1;\nb -= 1;\n```\nExample is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/remove-updater/mocks).\n\n```bash\nexpose remove-updater path/to/file.js --output path/to/file.remove-updater.js\n```\n\nArgs:\n- `--o, --output \u003cfile\u003e`  \n  Output file path  \n\nNotes:\n- Only replaces update expressions whose value is not used.\n- Safe for expression statements and for-loop update clauses.\n\n---\n\n### `expose remove-reassign`\n\nInline safe alias assignments and wrapper calls.\n```js\nconst a = 0;\nconst b = a;\nconst c = b;\nconsole.log(c); // =\u003e console.log(a);\n```\n```js\nfunction a(arg) {\n  return b(arg);\n}\nfunction c(arg) {\n  return d[arg];\n}\na(0); // =\u003e b(0)\nc(0); // =\u003e d[0]\n```\nExample is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/remove-reassign/mocks).\n\n```bash\nexpose remove-reassign path/to/file.js --output path/to/file.remove-reassign.js\n```\n\nArgs:\n- `--o, --output \u003cfile\u003e`  \n  Output file path  \n\nNotes:\n- Only inlines const/immutable alias chains.\n- Skips object shorthand replacements and shadowed bindings.\n- Wrapper inlining is limited to single-return passthroughs.\n\n---\n\n### `expose remove-deadcode`\n\nRemove unreachable branches and simplify conditional expressions.\n```js\nif (true) {\n  a();\n} else {\n  b();\n}\n// after\na();\n\nconst x = cond ? true : false;\n// after\nconst x = !!cond;\n```\nExample is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/remove-deadcode/mocks).\n\n```bash\nexpose remove-deadcode path/to/file.js --output path/to/file.remove-deadcode.js\n```\n\nArgs:\n- `--o, --output \u003cfile\u003e`  \n  Output file path  \n\nNotes:\n- Only removes branches with literal/array/object tests.\n- Simplifies ternaries when both branches are booleans.\n\n---\n\n### `expose remove-anti-tamper`\n\nDrop the self-defending wrapper, debug guards, and console hijacks generated by anti-tamper scripts.\n```js\nvar wrapper = (function () {\n  var guard = true;\n  return function (ctx, fn) {\n    var thunk = guard ? function () {\n      if (fn) {\n        fn.apply(ctx, arguments);\n        fn = null;\n      }\n    } : function () {};\n    guard = false;\n    return thunk;\n  };\n})();\n\nwrapper(this, function () {\n  console.log(\"tamper\");\n});\n\nconsole.log(\"safe\");\n```\nExample is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/remove-anti-tamper/mocks).\n\n```bash\nexpose remove-anti-tamper path/to/file.js --output path/to/file.remove-anti-tamper.js\n```\n\nArgs:\n- `--o, --output \u003cfile\u003e`  \n  Output file path  \n\nNotes:\n- Targets wrappers that return guarded helper functions and removes their invocations.\n- Cleans up debug/console helper functions before removing the wrapper.\n\n---\n\n### `expose control-flow-packer`\n\nInline control-flow flattening loops generated by string-based state machines.\n```js\nconst _0x1 = \"a|b|c\".split(\"|\");\nlet _0x2 = 0;\n\nwhile (true) {\n  switch (_0x1[_0x2++]) {\n    case \"a\":\n      console.log(\"a\");\n      continue;\n    case \"b\":\n      console.log(\"b\");\n      continue;\n    case \"c\":\n      console.log(\"c\");\n      return;\n  }\n  break;\n}\n```\nExample is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/control-flow-packer/mocks).\n\n```bash\nexpose control-flow-packer path/to/file.js --output path/to/file.control-flow-packer.js\n```\n\nArgs:\n- `--o, --output \u003cfile\u003e`  \n  Output file path  \n\nNotes:\n- Only flattens loops whose state array comes from a literal `split`.\n- Stops when a branch returns or a state token is missing.\n\n---\n\n### `expose fn-inliner`\n\nInline proxy function calls into expressions.\n```js\nconst add = (a, b) =\u003e a + b;\nconst sum = add(1, 2);\n// after\nconst sum = 1 + 2;\n```\nExample is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/fn-inliner/mocks).\n\n```bash\nexpose fn-inliner path/to/file.js --output path/to/file.fn-inliner.js\n```\n\nArgs:\n- `--o, --output \u003cfile\u003e`  \n  Output file path  \n\nNotes:\n- Only inlines functions that return a single expression.\n- Skips return expressions with assignments, functions, blocks, or sequences.\n\n---\n\n### `expose sequence-split`\n\nSplit sequence expressions into statements.\n```js\n// before\na, b, c;\n// after\na;\nb;\nc;\n```\nExample is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/sequence-split/mocks).\n\n```bash\nexpose sequence-split path/to/file.js --output path/to/file.sequence-split.js\n```\n\nArgs:\n- `--o, --output \u003cfile\u003e`  \n  Output file path  \n\nNotes:\n- Splits safe sequence expressions into standalone statements.\n- Also normalizes single-statement control flow blocks.\n\n---\n\n### `expose remove-unused`\n\nRemove unused variabless.\n```js\n// before\nvar a = 0, b = 1;\nconsole.log(a);\n// after\nvar a = 0;\nconsole.log(a);\n```\nExample is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/remove-unused/mocks).\n\n```bash\nexpose remove-unused path/to/file.js --output path/to/file.remove-unused.js\n```\n\nArgs:\n- `--o, --output \u003cfile\u003e`  \n  Output file path  \n\n\n## Community \u0026 Support\n\n- Missing a feature? → [Create an issue](https://github.com/EdamAme-x/expose-kit/issues)\n- Not sure which command to use? → Join our [Discord](https://evex.land)\n\n---\n\n## Author\n\n- [EdamAme-x](https://github.com/EdamAme-x)\n\nBuilt for research, not abuse.  \nWant stronger obfuscation? Then build something this tool can’t reverse.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevex-dev%2Fexpose-kit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fevex-dev%2Fexpose-kit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevex-dev%2Fexpose-kit/lists"}