[GH-ISSUE #3353] [feature]: support importing CryptoJS in pre-request script #1119

Closed
opened 2026-03-16 18:39:58 +03:00 by kerem · 11 comments
Owner

Originally created by @junziqiao on GitHub (Sep 14, 2023).
Original GitHub issue: https://github.com/hoppscotch/hoppscotch/issues/3353

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

var raw = CryptoJS.HmacSHA256(sign_string,secret_key).toString();
var words = CryptoJS.enc.Utf8.parse(raw);

use postman
``

Steps to reproduce

can not import CryptoJS in pre-request script

Environment

Production

Version

Cloud

Originally created by @junziqiao on GitHub (Sep 14, 2023). Original GitHub issue: https://github.com/hoppscotch/hoppscotch/issues/3353 ### Is there an existing issue for this? - [X] I have searched the existing issues ### Current behavior var raw = CryptoJS.HmacSHA256(sign_string,secret_key).toString(); var words = CryptoJS.enc.Utf8.parse(raw); use postman `` ### Steps to reproduce can not import CryptoJS in pre-request script ### Environment Production ### Version Cloud
kerem 2026-03-16 18:39:58 +03:00
Author
Owner

@ifnotnithya commented on GitHub (Nov 15, 2023):

I am running into this as well.
Any plans on supporting CryptoJS

<!-- gh-comment-id:1813158135 --> @ifnotnithya commented on GitHub (Nov 15, 2023): I am running into this as well. Any plans on supporting CryptoJS
Author
Owner

@gzgzapp commented on GitHub (Jul 8, 2024):

you can download CryptoJS file like this url (https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js)
and add the global variables ,key name CryptoJS, value is the CryptoJS flies content.
in pre-request script, you can add eval(pw.env.get("CryptoJS")) in your first script line. now CryptoJS will be imported

<!-- gh-comment-id:2213622132 --> @gzgzapp commented on GitHub (Jul 8, 2024): you can download CryptoJS file like this url (https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js) and add the global variables ,key name CryptoJS, value is the CryptoJS flies content. in pre-request script, you can add eval(pw.env.get("CryptoJS")) in your first script line. now CryptoJS will be imported
Author
Owner

@kholisrag commented on GitHub (Jul 15, 2024):

you can download CryptoJS file like this url (https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js) and add the global variables ,key name CryptoJS, value is the CryptoJS flies content. in pre-request script, you can add eval(pw.env.get("CryptoJS")) in your first script line. now CryptoJS will be imported

worked for me

<!-- gh-comment-id:2227676118 --> @kholisrag commented on GitHub (Jul 15, 2024): > you can download CryptoJS file like this url (https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js) and add the global variables ,key name CryptoJS, value is the CryptoJS flies content. in pre-request script, you can add eval(pw.env.get("CryptoJS")) in your first script line. now CryptoJS will be imported worked for me
Author
Owner

@lovelock commented on GitHub (Sep 18, 2024):

you can download CryptoJS file like this url (https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js) and add the global variables ,key name CryptoJS, value is the CryptoJS flies content. in pre-request script, you can add eval(pw.env.get("CryptoJS")) in your first script line. now CryptoJS will be imported

it works like a charm, thanks

<!-- gh-comment-id:2357923063 --> @lovelock commented on GitHub (Sep 18, 2024): > you can download CryptoJS file like this url (https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js) and add the global variables ,key name CryptoJS, value is the CryptoJS flies content. in pre-request script, you can add eval(pw.env.get("CryptoJS")) in your first script line. now CryptoJS will be imported it works like a charm, thanks
Author
Owner

@nerdbugg commented on GitHub (Jan 16, 2025):

It works, but support CryptoJS builtin will be nice for new user.

<!-- gh-comment-id:2594408837 --> @nerdbugg commented on GitHub (Jan 16, 2025): It works, but support CryptoJS builtin will be nice for new user.
Author
Owner

@afrocubanito commented on GitHub (Feb 24, 2025):

Hi,
Sorry for my dumb question.
After eval(pw.env.get("CryptoJS")) what will be the syntax ?
let = CryptoJS.SHA256(variable).toString() ?

<!-- gh-comment-id:2678032545 --> @afrocubanito commented on GitHub (Feb 24, 2025): Hi, Sorry for my dumb question. After eval(pw.env.get("CryptoJS")) what will be the syntax ? let = CryptoJS.SHA256(variable).toString() ?
Author
Owner

@gzgzapp commented on GitHub (Feb 24, 2025):

Hi, Sorry for my dumb question. After eval(pw.env.get("CryptoJS")) what will be the syntax ? let = CryptoJS.SHA256(variable).toString() ?

eval(pw.env.get("CryptoJS"))
var str = "xxxxxxxxxxxxxxxxxxxxxxx",
pw = "admin";

var strSHA1 = CryptoJS.enc.Hex.stringify(CryptoJS.HmacSHA256(str, pw));
console.log(strSHA1);

You may need to search on Google about how to use the related functions of CryptoJS.

<!-- gh-comment-id:2678166332 --> @gzgzapp commented on GitHub (Feb 24, 2025): > Hi, Sorry for my dumb question. After eval(pw.env.get("CryptoJS")) what will be the syntax ? let = CryptoJS.SHA256(variable).toString() ? eval(pw.env.get("CryptoJS")) var str = "xxxxxxxxxxxxxxxxxxxxxxx", pw = "admin"; var strSHA1 = CryptoJS.enc.Hex.stringify(CryptoJS.HmacSHA256(str, pw)); console.log(strSHA1); You may need to search on Google about how to use the related functions of CryptoJS.
Author
Owner

@akbarraihanm commented on GitHub (Jul 11, 2025):

you can download CryptoJS file like this url (https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js) and add the global variables ,key name CryptoJS, value is the CryptoJS flies content. in pre-request script, you can add eval(pw.env.get("CryptoJS")) in your first script line. now CryptoJS will be imported

Not working on me

<!-- gh-comment-id:3062051625 --> @akbarraihanm commented on GitHub (Jul 11, 2025): > you can download CryptoJS file like this url (https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js) and add the global variables ,key name CryptoJS, value is the CryptoJS flies content. in pre-request script, you can add eval(pw.env.get("CryptoJS")) in your first script line. now CryptoJS will be imported Not working on me
Author
Owner

@chyg-start commented on GitHub (Jul 16, 2025):

Hi, Sorry for my dumb question. After eval(pw.env.get("CryptoJS")) what will be the syntax ? let = CryptoJS.SHA256(variable).toString() ?

eval(pw.env.get("CryptoJS")) var str = "xxxxxxxxxxxxxxxxxxxxxxx", pw = "admin";

var strSHA1 = CryptoJS.enc.Hex.stringify(CryptoJS.HmacSHA256(str, pw)); console.log(strSHA1);

You may need to search on Google about how to use the related functions of CryptoJS.

Hello, prompted me with 'RequestFailure: script_fail'

<!-- gh-comment-id:3077936720 --> @chyg-start commented on GitHub (Jul 16, 2025): > > Hi, Sorry for my dumb question. After eval(pw.env.get("CryptoJS")) what will be the syntax ? let = CryptoJS.SHA256(variable).toString() ? > > eval(pw.env.get("CryptoJS")) var str = "xxxxxxxxxxxxxxxxxxxxxxx", pw = "admin"; > > var strSHA1 = CryptoJS.enc.Hex.stringify(CryptoJS.HmacSHA256(str, pw)); console.log(strSHA1); > > You may need to search on Google about how to use the related functions of CryptoJS. Hello, prompted me with 'RequestFailure: script_fail'
Author
Owner

@waf commented on GitHub (Sep 18, 2025):

I think this will improve with the planned feature here: https://github.com/hoppscotch/hoppscotch/discussions/5221.

Until that's done, I (well, an LLM) have reimplemented HmacSHA256 / Utf8.parse and it works well for me as a pre-request script, and it passes the required crypto checks server-side. See code below. I'm sure it won't handle everything but it worked for my limited use case.

An alternate way to do this would be to use the existing Crypto/SubtleCrypto APIs that are already available in Hoppscotch prerequest scripts,, but I couldn't get them to work with the underlying faraday-cage library that Hoppscotch uses in their new scripting sandbox (ref https://github.com/AndrewBastin/faraday-cage/issues/1).

const myPassword = 'myPassword';
const myToken = 'abcabcabcabcabcabcabc';

// Build header
function buildAuthHeader(myPassword, myToken) {
  const msg = utf8Parse(myPassword);
  const key = utf8Parse(myToken);
  const sig = hmacSha256(key, msg);
  const signatureEncoded = base64Stringify(sig);
  return signatureEncoded;
}

// set variable to use in the request
const signature  = buildAuthHeader(myPassword, myToken);
pw.env.set("signature  ", signature);

function sha256Bytes(msg) {
  function rightRotate(value, amount) {
    return (value >>> amount) | (value << (32 - amount));
  }

  let h = [
    0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
    0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
  ];

  const k = new Uint32Array([
    0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
    0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
    0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
    0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
    0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
    0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
    0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
    0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
  ]);

  // Preprocessing
  let l = msg.length * 8;
  let withOne = new Uint8Array(((msg.length + 9 + 63) >> 6) << 6);
  withOne.set(msg);
  withOne[msg.length] = 0x80;
  new DataView(withOne.buffer).setUint32(withOne.length - 4, l, false);

  let w = new Uint32Array(64);
  for (let i = 0; i < withOne.length; i += 64) {
    for (let j = 0; j < 16; j++) {
      w[j] = new DataView(withOne.buffer, i + j*4, 4).getUint32(0, false);
    }
    for (let j = 16; j < 64; j++) {
      let s0 = rightRotate(w[j-15],7) ^ rightRotate(w[j-15],18) ^ (w[j-15]>>>3);
      let s1 = rightRotate(w[j-2],17) ^ rightRotate(w[j-2],19) ^ (w[j-2]>>>10);
      w[j] = (w[j-16] + s0 + w[j-7] + s1) | 0;
    }

    let [a,b,c,d,e,f,g,hh] = h;
    for (let j = 0; j < 64; j++) {
      let S1 = rightRotate(e,6)^rightRotate(e,11)^rightRotate(e,25);
      let ch = (e & f) ^ (~e & g);
      let temp1 = (hh + S1 + ch + k[j] + w[j]) | 0;
      let S0 = rightRotate(a,2)^rightRotate(a,13)^rightRotate(a,22);
      let maj = (a & b) ^ (a & c) ^ (b & c);
      let temp2 = (S0 + maj) | 0;

      hh=g; g=f; f=e; e=(d+temp1)|0;
      d=c; c=b; b=a; a=(temp1+temp2)|0;
    }
    h[0]=(h[0]+a)|0; h[1]=(h[1]+b)|0; h[2]=(h[2]+c)|0; h[3]=(h[3]+d)|0;
    h[4]=(h[4]+e)|0; h[5]=(h[5]+f)|0; h[6]=(h[6]+g)|0; h[7]=(h[7]+hh)|0;
  }

  let result = new Uint8Array(32);
  let dv = new DataView(result.buffer);
  h.forEach((v,i)=>dv.setUint32(i*4,v,false));
  return result;
}

function hmacSha256(key, message) {
  const blocksize = 64;
  if (key.length > blocksize) key = sha256Bytes(key);
  if (key.length < blocksize) {
    let tmp = new Uint8Array(blocksize);
    tmp.set(key);
    key = tmp;
  }
  let oKeyPad = new Uint8Array(blocksize);
  let iKeyPad = new Uint8Array(blocksize);
  for (let i=0;i<blocksize;i++) {
    oKeyPad[i] = key[i] ^ 0x5c;
    iKeyPad[i] = key[i] ^ 0x36;
  }
  return sha256Bytes(new Uint8Array([...oKeyPad, ...sha256Bytes(new Uint8Array([...iKeyPad, ...message]))]));
}

function utf8Parse(str) {
  const bytes = [];
  for (let i = 0; i < str.length; i++) {
    let codePoint = str.charCodeAt(i);

    // handle surrogate pairs
    if (codePoint >= 0xd800 && codePoint <= 0xdbff && i + 1 < str.length) {
      const next = str.charCodeAt(i + 1);
      if (next >= 0xdc00 && next <= 0xdfff) {
        codePoint = ((codePoint - 0xd800) << 10) + (next - 0xdc00) + 0x10000;
        i++;
      }
    }

    if (codePoint <= 0x7f) {
      bytes.push(codePoint);
    } else if (codePoint <= 0x7ff) {
      bytes.push(0xc0 | (codePoint >> 6));
      bytes.push(0x80 | (codePoint & 0x3f));
    } else if (codePoint <= 0xffff) {
      bytes.push(0xe0 | (codePoint >> 12));
      bytes.push(0x80 | ((codePoint >> 6) & 0x3f));
      bytes.push(0x80 | (codePoint & 0x3f));
    } else {
      bytes.push(0xf0 | (codePoint >> 18));
      bytes.push(0x80 | ((codePoint >> 12) & 0x3f));
      bytes.push(0x80 | ((codePoint >> 6) & 0x3f));
      bytes.push(0x80 | (codePoint & 0x3f));
    }
  }
  return new Uint8Array(bytes);
}

function base64Stringify(bytes) {
  let bin = "";
  for (let b of bytes) bin += String.fromCharCode(b);
  return btoa(bin);
}
<!-- gh-comment-id:3307725322 --> @waf commented on GitHub (Sep 18, 2025): I think this will improve with the planned feature here: https://github.com/hoppscotch/hoppscotch/discussions/5221. Until that's done, I (well, an LLM) have reimplemented HmacSHA256 / Utf8.parse and it works well for me as a pre-request script, and it passes the required crypto checks server-side. See code below. I'm sure it won't handle everything but it worked for my limited use case. An alternate way to do this would be to use the existing Crypto/SubtleCrypto APIs that are already available in Hoppscotch prerequest scripts,, but I couldn't get them to work with the underlying faraday-cage library that Hoppscotch uses in their new scripting sandbox (ref https://github.com/AndrewBastin/faraday-cage/issues/1). ```javascript const myPassword = 'myPassword'; const myToken = 'abcabcabcabcabcabcabc'; // Build header function buildAuthHeader(myPassword, myToken) { const msg = utf8Parse(myPassword); const key = utf8Parse(myToken); const sig = hmacSha256(key, msg); const signatureEncoded = base64Stringify(sig); return signatureEncoded; } // set variable to use in the request const signature = buildAuthHeader(myPassword, myToken); pw.env.set("signature ", signature); function sha256Bytes(msg) { function rightRotate(value, amount) { return (value >>> amount) | (value << (32 - amount)); } let h = [ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 ]; const k = new Uint32Array([ 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 ]); // Preprocessing let l = msg.length * 8; let withOne = new Uint8Array(((msg.length + 9 + 63) >> 6) << 6); withOne.set(msg); withOne[msg.length] = 0x80; new DataView(withOne.buffer).setUint32(withOne.length - 4, l, false); let w = new Uint32Array(64); for (let i = 0; i < withOne.length; i += 64) { for (let j = 0; j < 16; j++) { w[j] = new DataView(withOne.buffer, i + j*4, 4).getUint32(0, false); } for (let j = 16; j < 64; j++) { let s0 = rightRotate(w[j-15],7) ^ rightRotate(w[j-15],18) ^ (w[j-15]>>>3); let s1 = rightRotate(w[j-2],17) ^ rightRotate(w[j-2],19) ^ (w[j-2]>>>10); w[j] = (w[j-16] + s0 + w[j-7] + s1) | 0; } let [a,b,c,d,e,f,g,hh] = h; for (let j = 0; j < 64; j++) { let S1 = rightRotate(e,6)^rightRotate(e,11)^rightRotate(e,25); let ch = (e & f) ^ (~e & g); let temp1 = (hh + S1 + ch + k[j] + w[j]) | 0; let S0 = rightRotate(a,2)^rightRotate(a,13)^rightRotate(a,22); let maj = (a & b) ^ (a & c) ^ (b & c); let temp2 = (S0 + maj) | 0; hh=g; g=f; f=e; e=(d+temp1)|0; d=c; c=b; b=a; a=(temp1+temp2)|0; } h[0]=(h[0]+a)|0; h[1]=(h[1]+b)|0; h[2]=(h[2]+c)|0; h[3]=(h[3]+d)|0; h[4]=(h[4]+e)|0; h[5]=(h[5]+f)|0; h[6]=(h[6]+g)|0; h[7]=(h[7]+hh)|0; } let result = new Uint8Array(32); let dv = new DataView(result.buffer); h.forEach((v,i)=>dv.setUint32(i*4,v,false)); return result; } function hmacSha256(key, message) { const blocksize = 64; if (key.length > blocksize) key = sha256Bytes(key); if (key.length < blocksize) { let tmp = new Uint8Array(blocksize); tmp.set(key); key = tmp; } let oKeyPad = new Uint8Array(blocksize); let iKeyPad = new Uint8Array(blocksize); for (let i=0;i<blocksize;i++) { oKeyPad[i] = key[i] ^ 0x5c; iKeyPad[i] = key[i] ^ 0x36; } return sha256Bytes(new Uint8Array([...oKeyPad, ...sha256Bytes(new Uint8Array([...iKeyPad, ...message]))])); } function utf8Parse(str) { const bytes = []; for (let i = 0; i < str.length; i++) { let codePoint = str.charCodeAt(i); // handle surrogate pairs if (codePoint >= 0xd800 && codePoint <= 0xdbff && i + 1 < str.length) { const next = str.charCodeAt(i + 1); if (next >= 0xdc00 && next <= 0xdfff) { codePoint = ((codePoint - 0xd800) << 10) + (next - 0xdc00) + 0x10000; i++; } } if (codePoint <= 0x7f) { bytes.push(codePoint); } else if (codePoint <= 0x7ff) { bytes.push(0xc0 | (codePoint >> 6)); bytes.push(0x80 | (codePoint & 0x3f)); } else if (codePoint <= 0xffff) { bytes.push(0xe0 | (codePoint >> 12)); bytes.push(0x80 | ((codePoint >> 6) & 0x3f)); bytes.push(0x80 | (codePoint & 0x3f)); } else { bytes.push(0xf0 | (codePoint >> 18)); bytes.push(0x80 | ((codePoint >> 12) & 0x3f)); bytes.push(0x80 | ((codePoint >> 6) & 0x3f)); bytes.push(0x80 | (codePoint & 0x3f)); } } return new Uint8Array(bytes); } function base64Stringify(bytes) { let bin = ""; for (let b of bytes) bin += String.fromCharCode(b); return btoa(bin); } ```
Author
Owner

@jamesgeorge007 commented on GitHub (Nov 6, 2025):

Hi! #5090 added the ability to import ESM packages in the scripting context as part of the Experimental scripting sandbox. You can now import crypto libraries directly:

import CryptoJS from 'https://esm.run/crypto-js@4.2.0';

Please track the further progress in #2015.

<!-- gh-comment-id:3498580483 --> @jamesgeorge007 commented on GitHub (Nov 6, 2025): Hi! #5090 added the ability to import ESM packages in the scripting context as part of the `Experimental scripting sandbox`. You can now import crypto libraries directly: ```ts import CryptoJS from 'https://esm.run/crypto-js@4.2.0'; ``` Please track the further progress in #2015.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/hoppscotch#1119
No description provided.