Haru Utils

보안 취약점 조치 · 런타임 업그레이드

Node.js 보안 취약점 패치 및 LTS 무중단 판올림

Node.js 보안 권고(CVE)에 대응하여 Ubuntu·Rocky Linux 환경에서 NodeSource 또는 nvm 기반 취약 버전을 최신 보안 LTS로 무중단(Zero-downtime) 업그레이드하고, PM2 프로세스 리로드와 npm 의존성 감사를 수행하는 표준 조치 절차입니다.
Node.js 보안 취약점Node.js CVE 패치Node.js LTS 업그레이드PM2 무중단 리로드npm audit fixNodeSource 업그레이드HTTP Request Smuggling
지원 환경Ubuntu Server 22.04 / 24.04 LTS (NodeSource 저장소 또는 nvm)
예상 시간약 45분
난이도중급
검토일2026-09-04

BEFORE YOU START

시작 전에 준비하세요

01

sudo 권한을 가진 운영 계정 및 서비스 전용 Unix 계정(<APP_USER>)

02

현재 구동 중인 Node.js 서비스의 PM2 ecosystem 설정 및 .env 환경 파일의 검증된 백업 경로

03

Node.js 공식 보안 공지(CVE) 및 승인된 목표 보안 LTS 버전(v20.x 또는 v22.x LTS)

04

서비스 포트 및 헬스체크 엔드포인트(예: /healthz 또는 HTTP 200 응답 경로)

권장 대상 보안 감사 및 긴급 CVE 보안 권고에 따라 운영 중인 Node.js 런타임을 무중단으로 최신 보안 패치 LTS 버전으로 안전하게 판올림하려는 서버 관리자·DevOps 엔지니어

FOLLOW THE RECIPE

8단계 구성·점검 레시피

1
확인시스템을 변경하지 않는 점검 단계

현재 Node.js 취약 버전 및 PM2 프로세스 진단

현재 서버에 설치된 Node.js 및 npm 버전이 최근 공지된 CVE 취약점 대상인지 확인하고, 운영 중인 PM2 프로세스 목록과 실행 바이너리 경로를 읽기 전용으로 진단합니다.

Node 및 npm 버전 확인
node -v
npm -v
Node 바이너리 경로 및 OS 확인
which node
cat /etc/os-release
실행 중인 PM2 프로세스 목록
sudo -iu <APP_USER> pm2 list
sudo -iu <APP_USER> pm2 describe <APP_NAME>
  • 현재 구동 중인 Node.js 버전과 공지된 취약 CVE 버전 대조 완료
  • 서비스 실행 Unix 계정(<APP_USER>)과 PM2 홈 디렉터리 확인
  • Node.js 설치 방식(NodeSource 패키지 vs nvm) 파악 완료
결과 읽기

Node.js 버전이 취약점 영향 범위에 속하거나 nvm과 시스템 패키지 경로가 혼재되어 있다면 공식 패키지 저장소(NodeSource) 또는 nvm 관리 경로를 하나로 확정합니다.

다음 판단

운영 포트 점유 상태와 package.json 의존성 보안 감사를 수행합니다.

2
확인시스템을 변경하지 않는 점검 단계

서비스 리스닝 포트 및 npm 의존성 취약점 점검

애플리케이션이 수신 중인 내부 포트, NGINX 프록시 연동 상태를 확인하고 package.json 내 서드파티 패키지의 취약점(npm audit)을 사전에 점검합니다.

내부 리스닝 포트 확인
sudo ss -tulpn | grep -E ':(3000|8080|<APP_PORT>)\b'
패키지 의존성 보안 감사
sudo -iu <APP_USER> bash -lc 'cd /srv/myapp && npm audit --omit=dev || true'
디스크 여유 공간 확인
df -h / /var /srv
  • 서비스 포트 충돌이 없으며 NGINX upstream이 정상 프록시 중임을 확인
  • npm audit에서 Critical/High 등급 취약점 존재 여부 파악
  • 새 패키지 설치 및 빌드를 위한 충분한 디스크 여유 공간 확보
결과 읽기

npm audit에서 취약점이 다수 발견되더라도 런타임 자체 CVE 패치와 애플리케이션 라이브러리 패치를 단계별로 분리하여 진행합니다.

다음 판단

공식 저장소에서 최신 보안 패치 Node.js LTS 패키지를 설치합니다.

3
변경패키지·설정·서비스 상태가 달라지는 단계

NodeSource 공식 저장소 갱신 및 최신 보안 LTS 설치

배포판 공식 패키지 관리자(APT/DNF)를 통해 검증된 NodeSource 최신 보안 패치 LTS(v20.x 또는 v22.x) 바이너리를 설치하고 버전을 확인합니다.

변경 단계입니다. 대상 서버, 백업 파일, 서비스 중단 영향과 바로 이전 상태로 돌아가는 방법을 다시 확인하세요.
Ubuntu 패키지 갱신 및 LTS 설치
sudo apt-get update
sudo apt-get install --only-upgrade -y nodejs || sudo apt-get install -y nodejs
Rocky Linux 패키지 갱신 및 LTS 설치
sudo dnf makecache
sudo dnf upgrade -y nodejs || sudo dnf install -y nodejs
설치된 보안 패치 버전 확인
node -v
npm -v
  • 공식 보안 패치가 적용된 LTS 버전으로 node 바이너리가 갱신되었음을 확인
  • npm 버전이 함께 최신 보안 버전으로 갱신되었음을 확인
결과 읽기

바이너리 교체 후에도 기존 실행 중인 PM2 프로세스는 메모리상에서 구버전으로 계속 동작 중이므로 설정 백업 후 리로드가 필요합니다.

다음 판단

설정 파일 백업 및 네이티브 C++ 애드온 재빌드를 진행합니다.

4
주의권한·연결·중단 영향을 확인할 단계

설정 파일 백업 및 글로벌 모듈·네이티브 애드온 정합성 검증

런타임 변경 전 애플리케이션의 package.json, package-lock.json 및 .env 환경설정 파일을 백업하고, Node.js ABI 변경에 따른 네이티브 애드온(node-gyp)을 재빌드합니다.

설정 파일 및 패키지 락 백업
sudo -u <APP_USER> cp -p /srv/myapp/package.json /srv/myapp/package.json.bak
sudo -u <APP_USER> cp -p /srv/myapp/.env /srv/myapp/.env.bak
글로벌 PM2 모듈 정합성 동기화
sudo npm install -g pm2@latest
네이티브 C++ 애드온 재빌드
sudo -iu <APP_USER> bash -lc 'cd /srv/myapp && npm rebuild'
설정 확인 및 필요시 편집
sudoedit /srv/myapp/ecosystem.config.cjs
설정 예시 · /srv/myapp/ecosystem.config.cjs
PM2 클러스터 무중단 재로드 설정 예시
module.exports = {
  apps: [
    {
      name: "myapp",
      script: "server.js",
      instances: "max",
      exec_mode: "cluster",
      wait_ready: true,
      listen_timeout: 10000,
      kill_timeout: 5000,
      env: {
        NODE_ENV: "production",
        PORT: 3000,
      },
    },
  ],
};
  • package.json 및 .env 백업 파일(.bak) 생성 확인
  • Node.js 버전 판올림에 맞춘 PM2 전역 패키지 동기화 완료
  • npm rebuild 실행 시 C++ 애드온 컴파일 에러 없음 확인
결과 읽기

ABI 호환성 문제가 생기면 npm rebuild 또는 클린 설치(npm ci)를 통해 의존 모듈을 다시 빌드합니다.

다음 판단

PM2 Zero-Downtime 무중단 리로드를 수행합니다.

5
변경패키지·설정·서비스 상태가 달라지는 단계

PM2 무중단 리로드(Zero-Downtime) 및 프로세스 저장

클러스터 모드로 구동 중인 PM2 워커 프로세스들을 하나씩 순차적으로 재시작(reload)하여 무중단으로 새 Node.js 런타임을 적용하고 startup 설정을 저장합니다.

변경 단계입니다. 대상 서버, 백업 파일, 서비스 중단 영향과 바로 이전 상태로 돌아가는 방법을 다시 확인하세요.
PM2 무중단 리로드
sudo -iu <APP_USER> pm2 reload all --update-env
PM2 데몬 바이너리 동기화
sudo -iu <APP_USER> pm2 update
PM2 저장 상태 갱신
sudo -iu <APP_USER> pm2 save
  • 다운타임 없이 각 워커 프로세스가 순차적으로 online 상태로 전환되었음을 확인
  • pm2 update로 백그라운드 PM2 데몬도 최신 Node 바이너리를 참조하도록 갱신
  • pm2 save로 부팅 시 자동 시작 구성 저장 완료
결과 읽기

프로세스가 errored 상태로 빠지거나 재시작 루프가 발생하면 즉시 logs 명령으로 예외 원인을 추적합니다.

다음 판단

서비스 헬스체크 및 런타임 정상 동작을 검증합니다.

6
확인시스템을 변경하지 않는 점검 단계

무중단 전환 검증 및 런타임 취약점 패치 확인

로컬 헬스체크 엔드포인트를 호출하여 HTTP 200 응답을 확인하고, PM2 프로세스가 실제로 신규 Node.js 런타임 버전에서 실행 중인지 프로세스 정보를 대조합니다.

HTTP 헬스체크 응답 확인
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:<APP_PORT>/healthz || curl -s -I http://127.0.0.1:<APP_PORT>/
PM2 프로세스 런타임 및 상태 확인
sudo -iu <APP_USER> pm2 status
sudo -iu <APP_USER> pm2 describe <APP_NAME> | grep -E 'node version|status|uptime'
실시간 에러 로그 모니터링
sudo -iu <APP_USER> pm2 logs <APP_NAME> --lines 40 --nostream
  • HTTP 200 정상 응답 및 기대 지연 시간 이내 처리 확인
  • pm2 describe 출력에서 신규 보안 LTS Node 버전 번호 확인
  • 에러 로그에 UncaughtException 또는 경고 발생 없음 확인
결과 읽기

정상 응답이 확인되면 런타임 수준의 CVE 패치가 완료된 상태입니다. 이후 보안 강화를 진행합니다.

다음 판단

npm audit 기반 프로덕션 의존성 취약점 자동 교정 및 권한 강화를 수행합니다.

7
주의권한·연결·중단 영향을 확인할 단계

프로덕션 의존성 취약점 교정 및 런타임 보안 강화

프로덕션 의존성 패키지 취약점을 자동 교정(npm audit fix)하고, 서비스 계정의 파일 권한과 Node.js 런타임 플래그(--disable-proto 등)를 검토합니다.

프로덕션 의존성 취약점 자동 패치
sudo -iu <APP_USER> bash -lc 'cd /srv/myapp && npm audit fix --omit=dev'
서비스 디렉터리 소유권 및 권한 제한
sudo chown -R <APP_USER>:<APP_USER> /srv/myapp
sudo chmod 750 /srv/myapp
외부 직접 노출 방지 로컬 바인딩 확인
sudo ss -tulpn | grep -E ':(3000|8080|<APP_PORT>)\b'
  • npm audit 결과 Critical/High 취약점이 해소되었음을 확인
  • Node.js 프로세스가 root가 아닌 <APP_USER> 권한으로만 실행됨을 확인
  • 애플리케이션 포트가 외부가 아닌 127.0.0.1(루프백)에 바인딩되어 NGINX를 통해서만 접근됨을 확인
결과 읽기

Breaking change가 있는 메이저 라이브러리 취약점은 별도 스테이징 환경에서 테스트 후 패키지 업그레이드를 계획합니다.

다음 판단

장애 발생 시 안전하게 이전 버전으로 복구하는 롤백 절차를 숙지합니다.

8
주의권한·연결·중단 영향을 확인할 단계

취약점 패치 실패 시 이전 Node.js 런타임 및 의존성 복원

신규 Node.js 런타임과의 비호환성이나 앱 충돌로 장애가 발생할 경우 백업된 package.json과 설정 파일(.bak)을 복구하고 이전 런타임 버전으로 롤백합니다.

백업된 설정 및 package.json 원복
sudo -u <APP_USER> cp -p /srv/myapp/package.json.bak /srv/myapp/package.json
sudo -u <APP_USER> cp -p /srv/myapp/.env.bak /srv/myapp/.env
이전 Node.js 버전 패키지 다운그레이드 (Ubuntu)
sudo apt-get install --allow-downgrades -y nodejs=<PREVIOUS_SAFE_VERSION>
이전 Node.js 버전 패키지 다운그레이드 (Rocky Linux)
sudo dnf downgrade -y nodejs-<PREVIOUS_SAFE_VERSION>
이전 버전 의존성 복원 및 PM2 롤백 재기동
sudo -iu <APP_USER> bash -lc 'cd /srv/myapp && npm ci --omit=dev && pm2 reload all'
  • 백업된 package.json 및 .env 파일로 원복 완료
  • 이전 안정화 Node.js 버전으로 패키지 다운그레이드 확인
  • PM2 무중단 롤백 후 HTTP 헬스체크 정상 응답 확인
결과 읽기

롤백 후 즉시 모니터링 로그를 확인하고, 호환성 문제의 근본 원인을 분석하여 런타임 재패치 계획을 수립합니다.

다음 판단

서비스 정상 복구 확인 후 인시던트 로그를 정리합니다.

SECURITY CHECK

운영 전 마지막 보안 점검

  • Node.js 런타임이 root 권한이 아닌 전용 서비스 계정(<APP_USER>)으로 구동되는지 확인
  • 프로덕션 환경에 불필요한 devDependencies가 제거되고 npm audit 조치가 완료되었는지 확인
  • HTTP Request Smuggling 방지를 위해 NGINX와 Node.js 간 HTTP keep-alive 및 헤더 처리 정합성 검토
  • reverse proxy(NGINX)를 거치지 않고 직접 외부에 Node.js 포트가 노출되지 않도록 로컬 루프백 바인딩 확인

COMMON ERRORS

자주 막히는 지점

pm2 reload 후에도 이전 Node.js 버전으로 표시됨

증상
node -v는 최신 버전인데 pm2 describe에서는 구버전 node 경로가 표시됨
가능한 원인
PM2 백그라운드 마스터 데몬이 구버전 Node 환경에서 실행된 상태로 캐시되어 있음
확인 순서
sudo -iu <APP_USER> pm2 update 명령으로 PM2 데몬을 갱신하면 기존 프로세스를 유지하며 최신 바이너리로 동기화됩니다.
트러블슈팅으로 이어보기

npm rebuild 시 node-gyp C++ 컴파일 실패

증상
node-gyp rebuild 오류 및 C++ ABI 불일치로 네이티브 모듈 로드 실패
가능한 원인
Node.js 메이저 버전 변경으로 V8 엔진 ABI가 변경되었거나 빌드 도구(gcc/g++, python3) 부재
확인 순서
build-essential 패키지를 확인하고 sudo -iu <APP_USER> npm rebuild를 실행하거나 node_modules를 클린 재설치(npm ci)합니다.
트러블슈팅으로 이어보기

PM2 리로드 중 NGINX에서 502 Bad Gateway 발생

증상
무중단 리로드 중 일부 요청이 502 Bad Gateway로 실패
가능한 원인
워커 프로세스가 listen 준비(ready)되기 전에 이전 프로세스가 kill되었거나 wait_ready 설정 미흡
확인 순서
ecosystem.config.cjs에 wait_ready: true와 listen_timeout을 지정하고 앱 소스에서 process.send('ready')를 명시 호출합니다.
트러블슈팅으로 이어보기

PRIMARY REFERENCES

공식 문서

설치 저장소와 지원 버전은 바뀔 수 있습니다. 검토일 이후에는 링크된 공식 문서와 현재 서버의 패키지 후보 버전을 함께 확인하세요.

도구 빠른 검색

최근 사용한 도구를 다시 열거나, 이름과 기능으로 검색하세요.

검색어와 도구의 입력·결과는 저장하지 않습니다.

↑↓ 이동 · Enter 열기 · Esc 닫기