DEV Community

Niti Agrawal
Niti Agrawal

Posted on

My Journey to Removing unsafe-eval from CSP: A Step-by-Step Guide

Hello everyone! đź‘‹

This is my first post here. After facing significant challenges while trying to eliminate unsafe-eval from an existing application's Content Security Policy (CSP), I finally developed a robust and generic solution that other developers can easily adopt and extend. To support the dev community, I’m excited to share the steps I followed to accomplish this.

Step 1: Replacing unsafe-eval Using mathjs
I found that mathjs is a powerful tool that can replace the need for eval in evaluating mathematical expressions.
Steps:
Install mathjs:

npm install mathjs

Enter fullscreen mode Exit fullscreen mode

Import and configure mathjs:

const { create, all } = require('mathjs');
const math = create(all);

Enter fullscreen mode Exit fullscreen mode

Set up custom functions:

math.import(
  {
    YOURFUNC: YOURFUNC,
    ADD: (a, b) => a + b,
    parseInt
  },
  { override: true }
);

// Create a scope object
const scope = {
  x: 3,
  y: 4
};

try {
  evaluateValue = math.evaluate(exp, scope);
} catch (error) {
  // If `mathjs` cannot evaluate, proceed with the next approach
}

Enter fullscreen mode Exit fullscreen mode

Success! 🎉 The code above should work for the following expressions, producing the same results as eval:

let exp;

exp = '1 + 2'; // Output: 3
exp = 'ADD(1, 2)'; // Output: 3
exp = '2 + 3 + parseInt(4.5)'; // Output: 9
exp = 'x * y' // Output: 12

Enter fullscreen mode Exit fullscreen mode

Step 2: Handling Complex Expressions if mathjs Fails
If mathjs cannot handle complex expressions that involve object properties, try this approach:

Solution:
Replace expressions dynamically:

const replacedExp = exp => exp.replace(/myObject\["([^"]+)"\]/g, (_, key) => JSON.stringify(data[key] || ''));

const myObject = {
  a: "test1",
  "a.b": "test2",
  "a.b.c": "test3",
  2: "test4"
};

// Examples
console.log(myObject["a"]);       // Output: "test1"
console.log(myObject["a.b"]);     // Output: "test2"
console.log(myObject["a.b.c"]);   // Output: "test3"
console.log(myObject[2]);         // Output: "test4"

Enter fullscreen mode Exit fullscreen mode

This approach should help you safely handle complex object expressions without resorting to eval.

Top comments (0)