์—…๋ฐ์ดํŠธ๋กœ ๋Œ์•„๊ฐ€๊ธฐ
New releaseSep 19, 2026

js-x-ray @nodesecure/[email protected]

JavaScript ๋ฐ Node.js ์˜คํ”ˆ์†Œ์Šค SAST ์Šค์บ๋„ˆ. ๊ฐ€์žฅ ํ”ํ•œ ์•…์„ฑ ํŒจํ„ด์„ ํƒ์ง€ํ•˜๋Š” ์ •์  ๋ถ„์„๊ธฐ ๐Ÿ”ฌ.

๊ณต์œ 

@nodesecure/js-x-ray

npm version license ossf scorecard slsa level3 github ci workflow

JS-X-Ray๋Š” ์•…์„ฑ ํŒจํ„ด, ๋ณด์•ˆ ์ทจ์•ฝ์ , ์ฝ”๋“œ ์ด์ƒ ์ง•ํ›„๋ฅผ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•œ JavaScript ๋ฐ TypeScript SAST์ž…๋‹ˆ๋‹ค. ESLint์™€ ๋น„์Šทํ•˜์ง€๋งŒ ๋ณด์•ˆ ๋ถ„์„์— ํŠนํ™”๋˜์–ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์›๋ž˜ NodeSecure CLI๋ฅผ ์œ„ํ•ด ๋งŒ๋“ค์–ด์กŒ์ง€๋งŒ, JS-X-Ray๋Š” ์ด์ œ ๊ณต๊ธ‰๋ง ๋ณดํ˜ธ๋ฅผ ์œ„ํ•œ ๋…๋ฆฝ์ ์ด๊ณ  ์ง„์ง€ํ•œ ์„ ํƒ์ง€๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ”Ž ์ž‘๋™ ๋ฐฉ์‹

JS-X-Ray๋Š” JS ๋˜๋Š” TS ์ฝ”๋“œ๋ฅผ Abstract Syntax Tree (AST) ๋กœ ํŒŒ์‹ฑํ•˜๋ฉฐ, RegEx๋‚˜ Semgrep ๊ทœ์น™์„ ๊ด‘๋ฒ”์œ„ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ณ€์ˆ˜ ์ถ”์ , ๋™์  import ํ•ด์„, ๊ทธ๋ฆฌ๊ณ  ํŒจํ„ด ๋งค์นญ ๋„๊ตฌ๊ฐ€ ๋†“์น˜๋Š” ์ •๊ตํ•œ ๋‚œ๋…ํ™” ํƒ์ง€๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋Œ€์‹  JS-X-Ray๋Š” JavaScript/TypeScript ์ƒํƒœ๊ณ„์—๋งŒ ์ „์ ์œผ๋กœ ํŠนํ™”๋˜์–ด ์žˆ๋‹ค๋Š” ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก ๊ธฐ๋Šฅ

  • ์™„์ „ํ•œ ๋ณ€์ˆ˜ ์ถ”์ ์„ ํ†ตํ•ด require(), import, ๋™์  import ์ถ”์ 
  • ๋‚œ๋…ํ™”๋œ ์ฝ”๋“œ๋ฅผ ํƒ์ง€ํ•˜๊ณ  ์‚ฌ์šฉ๋œ ๋„๊ตฌ ์‹๋ณ„ (jsfuck, jjencode, obfuscator.io ๋“ฑ)
  • ์•…์„ฑ ํŒจํ„ด ํ‘œ์‹œ: ๋ฐ์ดํ„ฐ ์œ ์ถœ, process.env ์ง๋ ฌํ™”, ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์…ธ ๋ช…๋ น
  • ์ทจ์•ฝํ•œ ์ฝ”๋“œ ํƒ์ง€: eval(), Function() ์ƒ์„ฑ์ž, ReDoS์— ์ทจ์•ฝํ•œ ์ •๊ทœ์‹, SQL ์ธ์ ์…˜
  • ์ทจ์•ฝํ•œ ์•”ํ˜ธํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜ ํ‘œ์‹œ (MD5, SHA1 ๋“ฑ)
  • ์ธํ”„๋ผ ์ง€ํ‘œ ์ถ”์ถœ: URL, IP, ํ˜ธ์ŠคํŠธ ์ด๋ฆ„, ์ด๋ฉ”์ผ
  • ๊ตฌ์„ฑ ๊ฐ€๋Šฅํ•œ ๋ฏผ๊ฐ๋„ ๋ชจ๋“œ (conservative/aggressive) ๋ฐ ํ™•์žฅ ๊ฐ€๋Šฅํ•œ probe ์‹œ์Šคํ…œ
  • JavaScript์™€ TypeScript ๋ชจ๋‘ ์ง€์›

๐Ÿ’ƒ ์‹œ์ž‘ํ•˜๊ธฐ

์ด ํŒจํ‚ค์ง€๋“ค์€ Node ํŒจํ‚ค์ง€ ์ €์žฅ์†Œ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ npm ๋˜๋Š” yarn์œผ๋กœ ์‰ฝ๊ฒŒ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

$ npm i @nodesecure/js-x-ray
# or
$ yarn add @nodesecure/js-x-ray

๐Ÿ‘€ ์‚ฌ์šฉ๋ฒ•

import { AstAnalyser } from "@nodesecure/js-x-ray";

const scanner = new AstAnalyser();

const { warnings, dependencies } = await scanner.analyseFile("./file.js");

console.log(dependencies);
console.dir(warnings, { depth: null });

์ „์ฒด API ๋ฌธ์„œ, ๊ฒฝ๊ณ  ์นดํƒˆ๋กœ๊ทธ, ๊ณ ๊ธ‰ ์‚ฌ์šฉ๋ฒ•์€ @nodesecure/js-x-ray ํŒจํ‚ค์ง€ README๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

Workspaces

๐Ÿฅ ๊ธฐ์—ฌ์ž ๊ฐ€์ด๋“œ

ํ”„๋กœ์ ํŠธ์— ๊ธฐ์—ฌํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋ผ๋ฉด ๋จผ์ € CONTRIBUTING ๊ฐ€์ด๋“œ๋ฅผ ์ฝ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์„ ๋งˆ์นœ ํ›„์—๋Š” ๋‹ค์Œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ํ…Œ์ŠคํŠธ(๋ฐ ๋ฆฐํ„ฐ)๊ฐ€ ์—ฌ์ „ํžˆ ์ •์ƒ์ธ์ง€ ํ™•์ธํ•˜์„ธ์š”:

$ npm run check

[!CAUTION] ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๋ฒ„๊ทธ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒฝ์šฐ, ๋ฐ˜๋“œ์‹œ ์ด์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ๋„ ํฌํ•จํ•˜์„ธ์š”.

๋‚ด๋ถ€ API

JS-X-Ray ๋‚ด๋ถ€ ๊ตฌ์กฐ๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ธฐ์—ฌ์ž๋ฅผ ์œ„ํ•ด, ๋‹ค์Œ ๋ฆฌ์†Œ์Šค๋Š” ์ €์ˆ˜์ค€ ์œ ํ‹ธ๋ฆฌํ‹ฐ์™€ AST ์กฐ์ž‘ ํŒจํ„ด์„ ๋ฌธ์„œํ™”ํ•ฉ๋‹ˆ๋‹ค:

๋ฒค์น˜๋งˆํฌ

js-x-ray์˜ ์„ฑ๋Šฅ์€ mitata๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ธก์ •๋˜๊ณ  ์ถ”์ ๋ฉ๋‹ˆ๋‹ค.

๋ฒค์น˜๋งˆํฌ๋ฅผ ์‹คํ–‰ํ•˜๋ ค๋ฉด:

  1. workspaces/js-x-ray๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
  2. npm run bench๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋ฒค์น˜๋งˆํฌ ๊ฒฐ๊ณผ๋Š” workspaces/js-x-ray/benchmark/report.json์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ์ด ํŒŒ์ผ์„ ์ˆ˜๋™์œผ๋กœ ํŽธ์ง‘ํ•˜์ง€ ๋งˆ์„ธ์š”. ๋ชจ๋“  pull request์—์„œ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธ๋ฉ๋‹ˆ๋‹ค.

๊ธฐ์—ฌ์ž โœจ

All Contributors

์ด ๋ฉ‹์ง„ ๋ถ„๋“ค๊ป˜ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค (emoji key):

License

MIT

์นดํ…Œ๊ณ ๋ฆฌ