← Back to index

DOM-based test cases — JavaScript injection (taint)

High: 0 Medium: 0 Low: 0 Safe: 0 Total: 0

This fixture exercises every sink from the javascript-injection-taint rule: string-based timers / eval / new Function, window.execScript, jQuery globalEval/getScript, document.execCommand, Range.createContextualFragment, crypto.generateCRMFRequest, and assignments to script.textContent. Each card wires attacker-controlled DOM data (hash/search/inputs/storage) into the relevant sink without validation.

Inline scenarios

JSI-H1 (High): Hash/query → string timer (eval:constructor)
// inline-script[#1]
function runTimerFromHash() {
  var field = document.getElementById('jsi-eval-input');
  var fallback = new URLSearchParams(location.search).get('payload') || window.name || '';
  var raw = (field && field.value) || (location.hash ? location.hash.slice(1) : '') || fallback;
  if (!raw) return;
  try { raw = decodeURIComponent(raw); } catch (err) {}
  setTimeout(raw, 15);
}
runTimerFromHash();
JSI-H2 (High): Input/sessionStorage → window.execScript
// inline-script[#2]
function runExecScriptSink() {
  var field = document.getElementById('jsi-execscript-input');
  var stored = sessionStorage.getItem('jsiExecScriptPayload');
  var payload = (field && field.value) || stored || '';
  if (!payload) return;
  if (window.execScript) {
    window.execScript(payload);
  } else if (typeof execScript === 'function') {
    execScript(payload);
  }
}
runExecScriptSink();
JSI-H3 (High): localStorage → $.globalEval / user URL → $.getScript
// inline-script[#3]
function runJqueryExecution() {
  var inline = document.getElementById('jsi-jquery-payload').value;
  var stored = localStorage.getItem('jsiGlobalEvalPayload') || document.cookie;
  var payload = inline || stored;
  if (payload) {
    $.globalEval(payload);
  }
  var url = document.getElementById('jsi-jquery-url').value || new URLSearchParams(location.search).get('script');
  if (url) {
    $.getScript(url);
  }
}
runJqueryExecution();
JSI-H4 (High): Input/hash → document.execCommand('insertHTML')
// inline-script[#4]
function execCommandFromHash() {
  var target = document.getElementById('jsi-execcommand-target');
  var field = document.getElementById('jsi-execcommand-input');
  var hashPayload = location.hash ? location.hash.slice(1) : '';
  var payload = field.value || hashPayload || window.name;
  if (!payload) return;
  try { payload = decodeURIComponent(payload); } catch (err) {}
  target.focus();
  document.execCommand('insertHTML', false, payload);
}
execCommandFromHash();
Rich text target (focus here first)
JSI-H5 (High): sessionStorage → Range.createContextualFragment
// inline-script[#5]
function renderFragmentFromStorage() {
  var field = document.getElementById('jsi-fragment-input');
  var stored = sessionStorage.getItem('jsiFragmentPayload');
  var payload = (field && field.value) || stored || '';
  if (!payload) return;
  var target = document.getElementById('jsi-fragment-target');
  if (!target) return;
  var range = document.createRange();
  range.selectNode(target);
  var fragment = range.createContextualFragment(payload);
  target.innerHTML = '';
  target.appendChild(fragment);
}
renderFragmentFromStorage();
createContextualFragment target
JSI-H6 (High): Query/hash → crypto.generateCRMFRequest
// inline-script[#6]
function submitCrmfRequest() {
  var params = new URLSearchParams(location.search);
  var hashPayload = location.hash ? location.hash.slice(1) : '';
  var payload = params.get('challenge') || hashPayload || document.cookie;
  if (!payload || !window.crypto || !crypto.generateCRMFRequest) {
    document.getElementById('jsi-crmf-log').textContent = 'generateCRMFRequest not available in this browser.';
    return;
  }
  crypto.generateCRMFRequest(payload, '', '', null);
  document.getElementById('jsi-crmf-log').textContent = 'Called crypto.generateCRMFRequest("' + payload + '")';
}
submitCrmfRequest();
Most browsers no longer implement crypto.generateCRMFRequest; this card still demonstrates the API usage for the taint sink.
Waiting for invocation…
JSI-H7 (High): Input/localStorage → script.textContent
// inline-script[#7]
function updateInlineScript() {
  var scriptTag = document.getElementById('jsi-inline-script');
  var field = document.getElementById('jsi-script-text-input');
  var payload = field.value || localStorage.getItem('jsiScriptTextPayload') || window.name;
  if (!payload) return;
  scriptTag.textContent = payload;
}
updateInlineScript();