inblog logo
|
spencer-tech
    Problem Solving

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

    koa-helmet, helmet, CORS
    Sang Un Lee's avatar
    Sang Un Lee
    Jul 04, 2024
    Koa-Helmet의 Helmet 버전 불일치로 인한 CORS 에러 발생
    Contents
    1. 문제 상황2. 문제 원인2.1 helmet dependency2.2 helmet 4.6.0 vs 6.0.12.3 관련 개념 : COEP, CORP3. 문제 해결4. 참고4.1 helmet 7.x.x 버전4.2 helmet 5.0.0 버전에서 COEP, CORP의 기본값을 enabled로 바꾼 이유
     
    1. 문제 상황2. 문제 원인2.1 helmet dependency2.2 helmet 4.6.0 vs 6.0.12.3 관련 개념 : COEP, CORPCOEPCORP3. 문제 해결4. 참고4.1 helmet 7.x.x 버전4.2 helmet 5.0.0 버전에서 COEP, CORP의 기본값을 enabled로 바꾼 이유
     

    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

     
    • 5.0.0 버전이 되면서 crossOriginEmbedderPolicy, crossOriginResourcePolicy, crossOriginOpenerPolicy의 기본값이 enabled로 설정됨
      • ChangeLog 화면 캡쳐
        notion image
        https://github.com/helmetjs/helmet/blob/main/CHANGELOG.md#changed-8
     
    • ∴ 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: 모든 출처의 요청 허용
     
    • 즉, COEP가 require-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 버전

     
    • helmet 7.x.x 버전이 되면서 다시 COEP 헤더의 기본값이 disabled 되었음
      • ∵ COEP 헤더의 기본값이 enabled 되면서 CORS 에러 때문에 많은 사람이 이슈를 겪었음
      • notion image
        CORS 에러로 인한 이슈들
        https://stackoverflow.com/questions/70752770/helmet-express-err-blocked-by-response-notsameorigin-200
        https://stackoverflow.com/questions/70752770/helmet-express-err-blocked-by-response-notsameorigin-200
     
    • 따라서 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
    Contents
    1. 문제 상황2. 문제 원인2.1 helmet dependency2.2 helmet 4.6.0 vs 6.0.12.3 관련 개념 : COEP, CORP3. 문제 해결4. 참고4.1 helmet 7.x.x 버전4.2 helmet 5.0.0 버전에서 COEP, CORP의 기본값을 enabled로 바꾼 이유

    spencer-tech

    RSS·Powered by Inblog