- 공급망 공격은 오픈소스 코드에 악성 업데이트가 숨어들어오는 방식이며, Obsidian은 이를 최소화하기 위해 외부 의존성 자체를 줄이는 전략을 사용
- 앱 기능 대부분을 직접 구현하거나, 필요할 경우 포크된 코드를 자체 코드베이스에 포함하여 관리
- 필수적인 대형 라이브러리(pdf.js, Mermaid, MathJax 등)는 버전 고정을 통해 안전성을 확보하고, 업데이트는 보안 패치가 있을 때만 신중하게 진행
- 모든 의존성은 lockfile로 고정하며, postinstall 스크립트를 실행하지 않아 설치 시 임의 코드 실행을 차단
- 이러한 신중한 업데이트 절차와 시간 지연 전략을 통해 Obsidian은 잠재적 위협이 커뮤니티에서 탐지되기 전에 대응 가능
공급망 공격이란 무엇인가
- 공급망 공격은 오픈소스 생태계에서 악성 업데이트가 배포 코드에 숨어드는 방식
- 많은 앱들이 오픈 소스 코드를 사용하기 때문에, 하나의 악성 업데이트가 파급적으로 여러 앱에 영향을 주게 됨
- Obsidian은 의존성을 최소화하는 전략을 통해 이러한 공격 표면을 줄이고, 앱을 안전하게 설계함
의존성 최소화 전략 : Less is Safer
- Obsidian은 카테고리 내 다른 앱과 비교해 매우 적은 수의 외부 라이브러리에 의존함
- 주요 기능(예: Bases, Canvas)은 외부 라이브러리 도입 대신 자체 구현 진행
- 이를 통해 실행되는 코드에 대한 완전한 제어력 확보 가능함
- 소규모 유틸리티 함수는 거의 항상 개발팀이 직접 구현함
- 중간 규모 모듈은 라이선스 허용 시 포크하여 코드베이스에 포함함
- 대형 라이브러리(pdf.js, Mermaid, MathJax 등) 는 검증된 버전을 고정해서 포함하고, 중요 보안 이슈가 발견될 때에만 최소한으로 업그레이드
- 모든 외부 변경 사항을 상세히 검토하고, 철저한 테스트 절차 수행함
- 이러한 방식으로 서브 의존성 개수도 최소화하여, 악성 코드가 유입될 일차적인 위험 자체를 줄이는 구조
실제 앱에 포함되는 요소
- 실제로 사용자가 실행하는 앱에는 Electron, CodeMirror, moment.js 등 아주 소수의 패키지만 포함됨
- 그 외의 개발 도구들은 앱 빌드 과정에만 사용되고, 최종 사용자에게는 전달되지 않음
버전 고정과 lockfile 관리
- 모든 외부 의존성은 엄격한 버전 고정(pin) 및 lockfile 커밋을 통해 관리함
- 이를 통해 설치가 항상 재현 가능하며, 변경 내역 추적이 용이함
- postinstall 스크립트 미실행 정책을 통해, 설치 중 임의의 코드 실행 가능성을 원천적으로 차단
느리고 신중한 업데이트 절차
- 의존성 업그레이드가 필요할 때에는 아래와 같은 체계적 검토 절차를 진행함
- 변경 기록(changelog) 한 줄씩 세밀 검토
- 새 버전에서 추가된 하위 의존성 확인
- 변화 폭이 크거나 위험 요소가 있는 경우 upstream 소스와 diff 직접 확인
- 주요 경로 및 플랫폼에 대해 자동/수동 테스트 실시
- 위 모든 단계 통과 이후에만 lockfile 커밋 진행
- 대부분의 의존성은 자주 변경이 필요하지 않기 때문에, 업데이트 빈도 자체가 낮음
- 새로운 외부 코드 도입은 기존 의존성 신규 채택 수준으로 검토하고 관리함
안정성을 위한 "시간적 여유" : Time is a buffer
- 각종 업그레이드는 즉시 배포하지 않고 일정 기간 지연시킴
- 이 기간 동안 오픈 소스 커뮤니티 및 보안 연구자들이 악성 버전을 탐지할 수 있는 사전 대응 창구로 작용
- 실제 배포 시점에는 이미 문제가 확인될 확률이 높아, 위험 최소화에 효과적임
결론
- 단일 보안 대책만으로는 공급망 공격 위험을 완전히 제거할 수 없음
- 그러나 Obsidian은 의존성 최소화, 얕은 그래프, 버전 고정, postinstall 금지, 검토 중심의 느린 업데이트를 병행해 위험을 대폭 감소시키고 있음
- 이런 절차를 통해 코드가 사용자에게 도달하기 전 위험 탐지 시간도 크게 확보할 수 있음
- Obsidian의 전체 보안 접근법 및 과거 보안 감사 내역은 공식 security page에서 확인 가능함