[2021.06.11] Production Environment에서 SourceMap 보안 이슈 해결
내가 직접 작업하는 프로젝트에 Build 후 Production 환경에 업로드 시 Source map File이 함께 올라가는 이슈가 있었다.
원래 Production 환경에 소스코드를 배포할 때, Webpack Build를 통해 기존 코드를 Uglify하게 만들어 업로드를 한다.
그러나 Source Map 파일이 Production 환경에 같이 올라가면, Source Map 파일을 통해 Uglify JS 파일들이 기존에 어떻게 작성되어있는지 트래킹이 가능하게 되어버리는 보안 이슈가 발생한다.
이러한 기존 코드를 파악하지 못하도록 일반적으로는 Source Map을 따로 업로드를 하지 않는 것이 권장된다.
Next.js 환경에서는 Production Build 시에는 Source Map File을 생성하지 않도록 되어 있으나, Optional로 Source Map을 함께 생성하여 배포할 수 있다. (https://nextjs.org/docs/advanced-features/source-maps)
그러나 Next.js 환경에서 Production Build 시 Source Map을 생성해야 했던 이유
유저 환경에서 Error가 발생 시, Sentry를 통해 어떤 부분에서 에러가 발생했는지 확인이 가능해야 했다. Sentry 환경에 Source Map을 업로드 하기 위해 SentryWebpackPlugin을 사용하여 Source Map을 임의로 생성하도록 해야만 했다.
문제
하지만 이 때 만들어진 Source Map이 Sentry 환경에만 올라가는 것이 아니라 Production환경까지 올라가서 보안 이슈가 발생하게 된다.
해결
Build된 파일의 디렉토리 내에 확장자 '.map' 파일을 모두 찾아서 지우도록 하는 Script 명령어를 추가했다.
// package.json
"scripts": {
...
"maps:remove": "find .next dist -type f -name '*.map' -exec rm {} \\;",
},
그리고 dockerFile에서 Build가 끝나면 해당 명령어를 실행하도록 했다.
// DockerFile
...
...
RUN yarn build
RUN yarn maps:remove
EXPOSE 3000
CMD ["yarn", "start"]
특이사항
Develop 환경까지는 예상대로 Source Map이 나타나지 않는 것을 확인할 수 있었다. 그러나 Production 환경에서만 여전히 Source Map이 확인이 되는 이슈가 있었다.
처음에는 Cloud Front의 캐싱 때문인줄 알았으나, 해당 Source map은 따로 캐싱 대상이 아니였다.
Develop과 Production 환경의 차이점은 CloudFront의 차이였다. Production 환경에서는 다운로드 해야할 리소스들을 Next 서버까지 거치지 않고 정적 파일로 빠르게 다운로드 할 수 있도록 Build 파일들을 AWS S3에 업로드를 한다.
기존의 S3 버킷에 이미 이전의 Source Map이 여전히 남아있기 때문에 발생하는 현상이었다.
하지만 의문점이 하나 있었다. 현재 S3에 올라가 있는 Source Map은 이전 Build에서 나온 파일들이여서, 이번에 새롭게 Source Map을 제거하도록 파이프라인을 추가한 상태의 Build File과는 전혀 다른 Build 파일이랑 서로 매핑이 이루어지면 안되는 것이었다.
그럼에도 새롭게 올라간 Build 파일과 과거의 Source Map File이 매핑이 이루어져 여전히 Production에서 SourceMap이 보여지는 현상이 발생한 것이었다.
Build File들을 확인해보니, 새롭게 Build한 Chunk File의 일부들이 과거에 Build한 Chunk File의 일부와 Hash Name이 같았다.
Next.js 환경에서는 기본적으로 Page 단위로 Chunk 분리를 하고있다보니, 해당 페이지와 관련된 코드들에서 소스코드 변경 점이 없으면, Hash Name이 여전히 그대로인 것이다.
docker File의 파이프라인만 수정하고, 자바스크립트 코드 자체는 건드리지 않았다보니, 이전 Chunk파일의 Hash Name은 물론 이전 SourceMap과도 매핑이 가능했던 것이었다.
해결
이전 S3에 올라가 있던 .map 파일을 모두 제거하고, cache invalidation 처리도 한번 했다.
이후 Production 환경에서도 정상적으로 Source Map File이 올라가지 않는 것을 확인할 수 있었다.