클론 코딩을 진행하던 중, GitHub에 (1) 알람이 떴다. 확인해보니 "Secret scanning (1)"이라는 보안 경고가 발생했다는 알람이었다. 이는 MongoDB Atlas의 Database URI가 코드에 노출되었음을 감지한 것으로, 민감 정보 유출 위험이 있다는 내용이었다.
MongoDB Atlas 데이터베이스 URI 노출 시 GitHub에서 제안하는 대응 절차를 따라가며 실제로 문제를 해결한 과정을 알아보자.
# Remediation steps
Follow the steps below before you close this alert.
1. Rotate the secret if it's in use to prevent breaking workflows.
2. Revoke this MongoDB Atlas Database URI with credentials through MongoDB to prevent unauthorized access. [Learn more about MongoDB tokens.](https://gh.io/mongodb_atlas_db_uri_with_credentials)
3. Check security logs for potential breaches.
4. Close the alert as revoked.
1. Rotate the secret if it's in use to prevent breaking workflows.
- 의미: 기존 URI가 코드나 배포 환경에 쓰이고 있다면, 단순히 삭제하지 말고 새로운 URI로 먼저 교체해야 한다.
- 조치 방법
1) MongoDB Atlas에 로그인
2) 새 사용자 생성 또는 기존 사용자 비밀번호 재설정 (비밀번호 기반 인증일 경우)
3) 기존 프로젝트 또는 애플리케이션 설정에서 새 URI로 환경변수 혹은 시크릿 값 업데이트 (🧩 dotenv 적용)
2. Revoke this MongoDB Atlas Database URI with credentials through MongoDB to prevent unauthorized access.
- 의미: 외부에 노출된 기존 자격증명은 더 이상 유효하지 않도록 완전히 무력화해야 한다.
- 조치 방법
1) MongoDB Atlas → Project → Database Access
2) 노출된 URI에서 사용된 사용자 계정 확인
3) 해당 사용자 계정 삭제 또는 비밀번호 변경
- 완전히 사용하지 않을 거면 삭제
- 다른 데서 여전히 사용중이라면 비밀번호만 재설정
3. Check security logs for potential breaches.
- 의미: 노출된 URI로 접속 시도나 이상한 동작이 있었는지 확인해야 한다.
- 조치 방법
1) MongoDB Atlas → Project → Activity Feed 또는 Cluster → Metrics → Connection Logs
2) 최근 IP 주소, 위치, 접속 시간 확인
3) 의심스러운 접속(평소와 다른 국가, 갑작스러운 대량 쿼리 등) 식별
4) 필요한 경우 침해 가능성에 따라 데이터 백업, 감사 진행
4. Close the alert as revoked.
- 의미: GitHub Security Alert이나 기타 시스템에서 이번 사고에 대한 대응이 완료되었음을 명시한다.
- 조치 방법
1) GitHub Repository → Security → Secret scanning alerts
2) 해당 MongoDB URI 경고 클릭
3) "Mark as revoked" 또는 "Close as revoked" 선택
이후 index.js에서 URI를 .env 파일로 분리하여 환경변수로 관리하도록 수정하고, 노출된 값을 코드에서 제거한 후 커밋했다.
하지만 이미 이전 커밋에 포함되어 노출되었던 URI는 여전히 GitHub의 Secret scanning 페이지에 기록되어 있었다.
Git의 히스토리 자체를 수정하지 않는 이상 이전 커밋의 흔적은 그대로 남기 때문에, 원격 저장소를 삭제하고 새로 생성한 후 클론하여 재설정했다.
이번에는 .env 파일을 만들어보자.
🧩 dotenv로 환경변수 관리하기
URI가 코드에 하드코딩되어 있으면 보안상 위험할 뿐만 아니라, 협업 중에도 민감 정보가 노출될 수 있다. 이를 해결하기 위해 Node.js에서는 보통 .env 파일에 환경변수를 정의하고 dotenv 패키지를 사용해 이를 불러온다.
npmjs.com 의 Install과 Usage를 적용하여 환경 변수 만드는 방법을 적용했다.
npm install 명령어로 dotenv를 설치했다.
# npm
npm install dotenv --save
# yarn
yarn add dotenv
프로젝트 루트 경로에 .env 파일을 생성한다.
(🛠️ 루트 경로가 아닌 곳에 .env 파일을 생성해서 DB 연결이 안 됐음)
.env 파일에서 환경변수를 정의하는 방법은 다음과 같다.
# .env
# 변수명=값
PORT=5000
MONGODB_URI=mongodb+srv://<id>:<password>@....
.env 파일을 GitHub에 올리는 실수를 하지 않도록, .gitignore 파일에 .env 을 추가해준다.
프로젝트 루트에 있는 index.js 첫 줄에 다음 코드를 입력해서 환경변수를 불러온다.
require('dotenv').config();
.env로부터 불러온 환경변수를 사용하기 위해서는 `process.env.변수명` 키워드를 사용한다.
process.env.PORT
process.env.MONGO_URI
🛠️ .env 파일에 정의한 변수명과 process.env에서 불러온 이름이 달라서 undefined 상태가 되었다. .env 파일의 MONGODB_URI를 MONGO_URI로 수정해서 해결했다.
# .env
MONGODB_URI=mongodb+srv://~
# index.js
const { PORT, MONGO_URI } = process.env;
mongoose.connect(process.env.MONGO_URI)
.then(() => console.log('MongoDB Connected'))
.catch(err => console.error(err));
🧠 What I Learned
민감 정보는 절대 코드에 노출하거나 하드코딩하지 않고, 환경 변수로 관리해야 한다. 이번에는 혼자하는 프로젝트라 큰 문제가 되지 않았지만, 여러명이 함께하거나 회사에서 이런 일이 생기기 않도록 주의 또 주의!!