Koa-Helmet의 Helmet 버전 불일치로 인한 CORS 에러 발생

koa-helmet, helmet, CORS
Sang Un Lee's avatar
Jul 04, 2024
Koa-Helmet의 Helmet 버전 불일치로 인한 CORS 에러 발생
 
 

1. 문제 상황

 
  • 이미지를 조회하는 API에서 CORS 에러 발생
    • FE의 origin : http://localhost:3000
    • 화면 캡쳐 : 브라우저 콘솔
      notion image
 
  • 서버의 CORS 미들웨어에 FE의 origin을 추가했음
    • 코드 : app.ts
      import cors, { Options } from '@koa/cors'; ... const corsOptions: Options = { maxAge: 86400, credentials: true }; // 개발 환경에서 origin 추가 if (process.env.NODE_ENV === 'development') { corsOptions.credentials = false; corsOptions.origin = 'http://localhost:3000'; } app.use(cors(corsOptions)); app.use(helmet({ frameguard: false })); ...
 
  • 여전히 같은 CORS 에러가 발생함

2. 문제 원인

 
  • app.use(helmet({ frameguard: false }));
    • helmet 미들웨어
    • 보안 관련 HTTP 헤더를 설정하고 자동으로 추가해주는 미들웨어
 

2.1 helmet dependency

 
  • koa-helmet 7.0.2는 helmet 6.0.1 버전에 의존
    • package-lock.json
      // package-lock.json "node_modules/koa-helmet": { "version": "7.0.2", ... "dependencies": { "helmet": "^6.0.1" }, ... },
 
  • 반면 koa-helmet 6.0.1은 helmet 4.6.0 버전에 의존
 

2.2 helmet 4.6.0 vs 6.0.1

 
 
  • ∴ helmet 버전에 따라 설정이 바뀜
    • 아래와 같은 코드를 사용할 때
      • app.use(helmet());
    • helmet 4.6.0 의 기본값 : unsafe-none → 크로스 오리진 리소스 사용 가능
      • app.use(helmet({ crossOriginEmbedderPolicy: false }));
    • helmet 6.0.1 의 기본값 : require-corp → 크로스 오리진 리소스 사용 불가
      • // Sets "Cross-Origin-Embedder-Policy: require-corp" app.use(helmet({ crossOriginEmbedderPolicy: true }));
      • 따라서 helmet 6.0.1에서 크로스 오리진 리소스를 사용하려면 CORP 헤더를 따로 설정해야함
      •  

2.3 관련 개념 : COEP, CORP

COEP

  • Cross-Origin-Embedder-Policy (COEP)
    • 문서에 크로스 오리진 리소스를 포함할 때 설정하는 HTTP 응답 헤더
    • 웹 페이지가 오리진이 다른 리소스를 어떻게 포함하고 사용할 수 있는지를 제어함
 
  • 옵션
    • Cross-Origin-Embedder-Policy: unsafe-none | require-corp | credentialless
    • unsafe-none : CORS 프로토콜이나 CORP 헤어 없이도 오리진이 다른 리소스 사용 가능
    • require-corp : 같은 오리진의 리소스 / 다른 오리진의 리소스를 사용하려면 CORP 헤더를 사용
    • credentialless : 자격증명(ex. 쿠키)이 필요없는 경우 다른 오리진의 리소스 사용 가능
      • 자격증명이 필요한 경우에는 크로스 오리진 리소스 사용 불가

CORP

  • Cross-Origin-Resource-Policy(CORP)
    • 리소스가 어떤 출처에서 로드될 수 있는지 제어
 
  • 옵션
    • Cross-Origin-Resource-Policy: same-origin | same-site | cross-origin
    • same-origin: 동일 출처의 요청만 허용
    • same-site: 동일 사이트의 요청만 허용
    • cross-origin: 모든 출처의 요청 허용
 
  • 즉, COEPrequire-corp인 경우, CORP 헤더의 값에 따라 요청을 허용할 출처를 설정
 

3. 문제 해결

 
  • CORP 헤더 설정 : cross-origin으로 설정
    • // app.ts app.use(helmet({ frameguard: false, crossOriginResourcePolicy: { policy: 'cross-origin' } })); app.use(cors({ maxAge: 86400, credentials: true }));

4. 참고

4.1 helmet 7.x.x 버전

 
 
  • 따라서 koa-helmet의 버전이 업데이트되면서 의존하는 helmet의 버전이 7 이상이 된다면, 프로젝트에서 CORS 설정을 따로 하지 않아도 괜찮음
 

4.2 helmet 5.0.0 버전에서 COEP, CORP의 기본값을 enabled로 바꾼 이유

 
  • helmet v4에서는 CSP의 기본값이 true가 되고, helmet v5에서는 COEP, CORP, COOP의 기본값이 true가 된 것으로 봐서, helmet maintainer는 보안을 더 신경쓰려고 했던 것 같음
 
 
 
 
Share article

spencer-tech