1. 악성코드 문제
첫 번째로 악성 코드 문제가 있습니다. 그러니까 내 패키지가 의존하는 수많은 하위 패키지 중에 악성코드가 있을 수도 있다는 뜻이죠. 실제로 2017년에는 cross-env라는 유명 패키지와 이름이 비슷한 crossenv라는 패키지에 악성 코드가 들어 있는 경우가 발견된 적도 있습니다.[1] 사용자들이 패키지를 설치할 때 오타를 별로 신경 쓰지 않고 패키지를 설치해버리는 취약점을 공격한 일명 'typo-squatting' 기법을 사용한 경우였는데요.
이 뿐만 아니라 2018년에는 Event-Stream이라는 유명 패키지가 의존하던 Flatmap-Stream이라는 패키지에 비트코인 관련 악성 코드가 포함된 사건도 있었고,[2] 2020년에는 유닉스 시스템의 중요 정보를 빼가는 악성 패키지가 발견되는 사건도 있었습니다.[3]
내가 사용하는 패키지 중에 이런 악성 코드들이 있다고 상상해보면 정말 무섭죠? 물론 패키지들의 보안 검사를 위해 npm 커뮤니티에서 많은 노력을 하고는 있지만, 특정 패키지, 그리고 그것이 의존하는 패키지들이 사용해도 괜찮은 것인지 확인하는 것은 본질적으로 그것을 사용해서 서비스를 만드는 개발자의 책임입니다. 모든 패키지를 본인이 직접 검사하는 것은 현실적으로 어렵겠지만 악성 코드가 있는 패키지를 설치하지 않으려면, 되도록 누구나 알 정도로 공신력있는 패키지들만을 골라서 사용하는 것이 좋습니다.
2. 패키지 내 코드의 취약점 문제
두 번째는 취약점 문제입니다. 어떤 패키지들의 코드에는 보안 측면에서 취약한 부분이 있을 수 있습니다. npm 측과 각종 보안 회사들은 어떤 패키지의 어떤 점이 취약하다고 주기적으로 발표를 하는데요. 이 문제에 관해 우리가 할 수 있는 것은 다음과 같습니다.
(1) npm outdated, npm update 정기적으로 실행하기
먼저, 현재 작업 중인 패키지 안에서 npm outdated, npm update 라는 명령어를 자주 실행해주는 겁니다. npm outdated는 현재 패키지에 설치된 하위 패키지들 중에 버전이 최신이 아닌 것들이 무엇이 있는지 보여주는 명령어입니다. 그리고 npm update는 현재 자신의 패키지에 설치된 모든 패키지들을 최신 패키지로 업데이트해주는 명령어이고요.
본인의 패키지 안에서 npm outdated로 오래된 패키지들이 많지는 않은지 확인해주고, npm update로 이것들을 최신 패키지로 업데이트해주는 작업을 정기적으로 수행해주면 좋습니다. 참고로 npm update는 package.json 파일의 dependencies 필드에 표시된 해당 패키지의 Version Range Syntax가 허용하는 범위 내에서만 업데이트를 해줍니다. 현재 설치된 버전이 1.5.2고, 최신 버전은 3.0.0인 패키지가 있다고 해도 이 패키지에 의존 중인 패키지의 package.json 파일에서 dependencies 필드에 ~1.8.3 이라고 써있다면 1.9.0 미만의 최신 버전까지로만 업데이트해주는 겁니다.
어쨌든 최신 버전의 패키지들을 사용할수록 일반적으로 보안상 더 안전하기 때문에 위 작업을 주기적으로 실행해주는 게 좋습니다. 이때 일부 패키지의 경우, 최신 버전으로 업데이트하기 전에 별도의 검토가 필요해서 모든 패키지를 최신의 것으로 바꾸면 안 되는 경우에는
npm update [패키지명]
을 실행해서 원하는 패키지만 업데이트해줘도 됩니다. 만약 최신보다 약간 이전의 버전을 원하면
npm update [패키지명]@[버전]
이런 식으로 특정 버전을 지정해주고 실행하면 됩니다.
(2) npm audit, npm audit fix으로 취약점 점검하기
패키지 내의 보안을 유지하는 또 다른 방법은 npm audit이라는 커맨드를 사용하는 건데요. 현재 자신의 패키지 안에서 npm audit이라는 커맨드를 실행하면, npm이 현재 설치된 패키지들의 이름과 버전을 보고, 발표된 취약점이 있는 것들은 그 정보를 출력해줍니다. 저도 제 패키지에서 npm audit을 실행해봤더니
이렇게 취약점 하나가 발견되었습니다. 이때 npm install fix라는 명령어를 실행하면 npm이 Version Range Syntax를 준수하면서도, 취약점이 해결된 더 최신 버전의 패키지를 자동으로 설치해줍니다. 하지만 이 npm install fix 만으로는 문제를 해결하지 못하는 경우도 있는데요. 이럴 때는 More info에 있는 URL로 들어가서 필요한 해결 조치를 보고 직접 수행해주면 됩니다.
방금 말한 방법들을 사용하면 보안상 취약한 패키지들을 사용하게 될 가능성은 작아지겠죠?
3. 패키지의 가용성(Availability) 문제
세 번째로 문제점은 사용 중이던 패키지가 갑자기 사라져버리거나 관리되지 않고 방치될 수도 있다는 점입니다. 실제로 2016년에는 left-pad라고 하는 패키지의 주인이 npm 저장소에서 그 패키지를 삭제해버린 사건이 있었습니다.[4] 이 때문에 당시 left-pad에 의존하고 있던, React나 Babel 같은 대형 프로젝트들에도 큰 문제가 발생했었는데요. 다행히 이 문제는 잘 해결되었지만, 이 사건은 당시 수많은 패키지들의 의존 생태계가 단 한 순간에 무너져버릴 수도 있다는 공포감을 개발자들에게 심어주었습니다. 그리고 단순한 기능 정도는 패키지를 굳이 쓰지 말자는 의식의 전환을 가져다주기도 했죠. 왜냐하면 당시 left-pad의 코드는 아래와 같이 단순한 코드였기 때문입니다.
module.exports = leftpad;
function leftpad (str, len, ch) {
str = String(str);
var i = -1;
if (!ch && ch !== 0) ch = ' ';
len = len - str.length;
while (++i < len) {
str = ch + str;
}
return str;
}
이런 작은 코드 조각이 수많은 회사들을 당황하게 만든 겁니다. 놀라운 사실이죠?
현재, npm 저장소에 한 번 올린 패키지는, 올리고 나서 72시간이 지나면 함부로 삭제할 수 없도록 되어 있습니다. 그래서 이제 그런 문제는 발생할 수 없겠지만 내가 사용하는 패키지가 앞으로도 잘 관리될 패키지인지를 확인하는 것은 여전히 중요합니다. 이 부분은 패키지의 인기도, 패키지를 관리하는 주체 등을 보고 스스로 잘 판단해야겠죠?
자, 이때까지 다른 패키지들에 의존함으로써 발생할 수 있는 문제들을 살펴봤습니다. 어떤 플랫폼도 마찬가지지만, 특히 Node.js의 패키지 생태계는 다양하고 유용한 패키지들이 아주 많이 존재한다는 점이 매력적입니다. 하지만 이렇게 다양한 패키지들을 자유롭게 사용하는 편리함을 누리는 만큼, 그 대가로 우리는 사용하는 패키지에 대해
- 이상한 코드는 없는지,
- 외부의 공격에 취약한 부분은 없는지,
- 앞으로도 꾸준한 업데이트가 이루어질지를
잘 고민하고 사용해야 합니다. 특정 분야에서 사실상 표준(de facto standard)처럼 존재하는 패키지가 있는 경우라면 상관없지만, 그렇지 않은 경우에 어떤 패키지를 사용하려고 한다면, 방금 위에서 설명한 기준들을 충족하는지 잘 판단하고 사용 여부를 결정하세요.
'develop > Node' 카테고리의 다른 글
패키지를 npm 공개 저장소에 올리기 (0) | 2023.11.28 |
---|---|
package.json 필드정리 (0) | 2023.11.28 |
패키지가 로드되는 두가지 방법 (1) | 2023.11.28 |
20231122_TIL (0) | 2023.11.23 |
node 프로젝트에 mysql 연동 & 테이블 생성 (1) | 2023.11.22 |