Content-Security-Policy가 이제 'strict-dynamic'을 사용합니다

v3.3.0.beta1부터 Discourse는 ‘strict-dynamic’ 콘텐츠 보안 정책(CSP)을 구현합니다. 이를 통해 수동 CSP 설정의 필요성이 사라지며, 태그 매니저 및 광고와 같은 외부 도구와의 호환성이 크게 향상됩니다.

사이트 관리자로서 당신이 해야 할 일은 아무것도 없습니다. 이 변경 사항은 자동으로 적용되며, 현재 사용 중인 외부 스크립트는 계속 작동합니다.

테마에는 변경 사항이 필요하지 않습니다. 소수의 플러그인[1]은 이 변경 사항과 호환되도록 약간의 조정이 필요할 수 있습니다(예: 1, 2).

이전에는 외부 스크립트와의 호환성을 위해 CSP를 비활성화했던 포럼은 이제 문제나 설정 작업 없이 CSP를 다시 활성화할 수 있어야 합니다.

기술적 세부 사항은 다음 토픽을 확인하세요:

현재로서는 ‘content security policy strict dynamic’ 사이트 설정을 비활성화하여 이전 시스템으로 전환할 수 있습니다. 이렇게 해야 할 이유가 있다면 알려주세요!


v3.3.0.beta3부터 ‘strict-dynamic’ 키워드는 CSP의 필수 구성 요소가 되었습니다. ‘content security policy strict dynamic’ 사이트 설정은 제거되었으며, ‘content security policy script src’ 사이트 설정은 유효한 값만 저장하도록 업데이트되었습니다.

관리자분께서는 사이트의 직원 작업 로그(https://<site_url>/admin/logs/staff_action_logs?filters=%7B%22action_name%22%3A%22change_site_setting%22%2C%22action_id%22%3A3%2C%22subject%22%3A%22content_security_policy_script_src%22%7D - <site_url>을 사이트의 기본 URL로 대체)에서 ‘content security policy script src’ 사이트 설정의 이전 값을 찾을 수 있어야 합니다.


  1. 기술적으로: register_html_builder 또는 erb 템플릿을 통해 <script> 요소를 도입하는 플러그인 ↩︎

26개의 좋아요

이 변경 사항 이후에도 이전과 같이 'unsafe-eval'을 어떻게 구성할 수 있나요?

1개의 좋아요

여기서는 변경 사항이 없습니다 - 여전히 content security script src 사이트 설정에 'unsafe eval’을 (따옴표 포함) 추가할 수 있습니다.

3개의 좋아요

content security script src 설정의 설명에 content_security_policy_strict_dynamic를 활성화하면 이 설정이 무시된다고 되어 있어서, 확인을 위해 이곳에 질문드립니다.

3개의 좋아요

설명의 내용은 다음과 같습니다.

content_security_policy_strict_dynamic이 활성화되면 호스트 소스(Host sources)는 무시됩니다.

여기서 중요한 부분은 "호스트 소스"입니다. 'unsafe-inline'은 호스트 소스가 아니므로 여전히 지원됩니다.

그럼에도 불구하고, 이 부분이 혼란스럽다는 점에는 전적으로 동의합니다. strict-dynamic의 성공적인 도입을 고려하여, 기존 시스템을 제거할 계획입니다. 그렇게 되면 목록에서 모든 호스트 소스를 자동으로 제거할 수 있으며, 관리자의 작업이 훨씬 간단해질 것입니다. :rocket:

5개의 좋아요

네, 설명해 주셔서 감사합니다.

4개의 좋아요

David,

간단히 확인하고 싶은 부분이 있습니다.

이 새로운 시스템은 다음과 같은 경우에서 잘 작동할 것으로 예상됩니다:

  • 인라인 스크립트
  • 로컬에 호스팅된 전체 스크립트 소스

그렇다면 "loadScript"를 사용하여 원격 스크립트를 호출하고 전체 원격 URL을 전달하는 경우는 어떻게 될까요?

틀렸다면 알려주세요. 하지만 제 생각에는 그 경우를 깔끔하게 처리하는 좋은 방법이 없는 것 같습니다.

그러면 해당 경우를 처리하려면 다음 중 하나로 의존해야 한다는 뜻인가요?

  • 해당 호출을 인라인 스크립트로 이동하거나
  • 전체 소스를 테마 자산(Theme asset)으로 다운로드하는 것?

전자의 인라인 스크립트 경우라면, 스크립트의 요소를 사용하기 전에 스크립트가 로드되었음을 보장하는 방법이 없을 것 같습니다. (예: loadScript 이후의 .then 내에서 수행할 수 있었던 것과 같은 방식)

2개의 좋아요

strict-dynamic는 loadScript를 통해 로드되는 원격 스크립트와 함께 작동해야 합니다. 사실, 이것이 전환의 주요 이유였습니다. 이제 모든 외부 스크립트 URL을 사전에 나열할 필요가 없습니다. 이는 특히 광고를 운영하는 사람들에게 유리하며, 광고는 종종 대량의 원격 스크립트를 가져오기 때문입니다.

loadScript에서 오류가 발생하고 있나요?

3개의 좋아요

일부 오류를 확인했지만, 그 때문은 아닐 수도 있습니다. 예를 들어 찾아보겠습니다.

저는 주로 loadScript와 원격 스크립트를 포함하는 것으로 알려진 안정적인 업그레이드를 준비하고 있었습니다.

loadScript를 통해 코드 내에서 무작위로 호출되는 원격 스크립트가 Dynamic 모드 CSP에 의해 어떻게 "인가"되는지 설명해 주시겠습니까? 어떤 마법이 작용하는 건가요?

3개의 좋아요

네, 맞습니다!

MDN에는 훌륭한 설명과 예제가 있습니다.

'strict-dynamic' 소스 표현식은 마크업 내에 존재하는 스크립트에 nonce나 해시를 동반하여 명시적으로 부여된 신뢰가 해당 루트 스크립트에 의해 로드되는 모든 스크립트로 전파되어야 함을 지정합니다.

따라서 원래 스크립트가 신뢰받으면(예: nonce를 통해), 브라우저는 제한 없이 다른 모든 스크립트를 로드할 수 있도록 허용합니다. 그리고 그런 스크립트들이 신뢰받기 때문에, 그것들은 더 많은 스크립트를 로드할 수 있습니다!


단, 스크립트는 '파서 삽입(parser inserted)'되어서는 안 된다는 주의 사항이 있습니다. 이는 strict-dynamic이 XSS 공격에 악용되는 것을 방지합니다.

예를 들어, 다음 코드는 '파서 삽입’에 해당하며 차단됩니다:

document.head.appendChild("<script src='https://example.com/xss-attempt.js' />");

하지만 스크립트 요소를 프로그래매틱하게 생성하는 것은 HTML 파싱을 수반하지 않으며, XSS 벡터가 될 가능성이 훨씬 낮기 때문에 허용됩니다:

const script = document.createElement("script");
script.src = "https://example.com/script.js"
document.head.appendChild(script);

^^ 이는 기본적으로 loadScript()가 작동하는 방식입니다.

3개의 좋아요

좋은 링크네요.

거의 해결했습니다. 감사합니다!

그럼 loadScript로 렌더링되는 스크립트 태그에도 nonce가 포함되나요?

2개의 좋아요

아니요, nonce는 Rails가 렌더링하는 원래의 script 태그(예: 코어, 플러그인, 테마 스크립트)에만 포함됩니다.

즉, 코어/플러그인/테마 코드는 신뢰할 수 있는 것으로 간주되며, 다른 스크립트를 삽입할 수 있습니다. 여기서는 nonce가 필요하지 않습니다. 브라우저는 어떤 스크립트가 삽입을 수행했는지를 알고, 그것이 신뢰할 수 있음을 자동으로 인식하기 때문입니다.

4개의 좋아요

데이비드, 또다시 시간 내어 주셔서 감사합니다!

4개의 좋아요

6개의 게시글이 새 주제로 분리되었습니다: 테마 구성 요소를 통해 스크립트를 추가할 때 발생하는 CSP 오류