CVE-2019-18841 (JavaScript, published 2019-11-11T01:15Z)
Description: value: Chartkick.js 3.1.0 through 3.1.3, as used in the Chartkick gem before 3.3.0 for Ruby, allows prototype pollution.
Severity: HIGH (CVSS v3 base score: 7.3)
Weakness: NVD-CWE-noinfo \u2014 Insufficient Information
There is insufficient information about the issue to classify it; details are unkown or unspecified.
Repository: https://github.com/ankane/chartkick
Files changed:
CHANGELOG.md
vendor/assets/javascripts/chartkick.js
Commit message: Updated Chartkick.js to 3.2.0


Vulnerable code:
 * v3.1.3
}(this, function () { 'use strict';
    return Object.prototype.toString.call(variable) === "[object Object]";
  function formatValue(pre, value, options) {
    return pre + value + (options.suffix || "");
      decimal: chart.options.decimal
          return formatValue("", value, formatOptions);
      decimal: chart.options.decimal
}));

Fixed code:
- Updated Chartkick.js to 3.2.0
 * v3.2.0
}(this, (function () { 'use strict';
    // protect against prototype pollution, defense 2
    return Object.prototype.toString.call(variable) === "[object Object]" && !isFunction(variable) && variable instanceof Object;
      // protect against prototype pollution, defense 1
      if (key === "__proto__") { continue; }

  function formatValue(pre, value, options, axis) {
    var suffix = options.suffix || "";
    var precision = options.precision;
    var round = options.round;

    if (options.byteScale) {
      var baseValue = axis ? options.byteScale : value;
      if (baseValue >= 1099511627776) {
        value /= 1099511627776;
        suffix = " TB";
      } else if (baseValue >= 1073741824) {
        value /= 1073741824;
        suffix = " GB";
      } else if (baseValue >= 1048576) {
        value /= 1048576;
        suffix = " MB";
      } else if (baseValue >= 1024) {
        value /= 1024;
        suffix = " KB";
      } else {
        suffix = " bytes";
      }

      if (precision === undefined && round === undefined) {
        precision = 3;
      }
    }

    if (precision !== undefined && round !== undefined) {
      throw Error("Use either round or precision, not both");
    }

    if (!axis) {
      if (precision !== undefined) {
        value = value.toPrecision(precision);
        if (!options.zeros) {
          value = parseFloat(value);
        }
      }

      if (round !== undefined) {
        if (round < 0) {
          var num = Math.pow(10, -1 * round);
          value = parseInt((1.0 * value / num).toFixed(0)) * num;
        } else {
          value = value.toFixed(round);
          if (!options.zeros) {
            value = parseFloat(value);
          }
        }
      }
    }

    return pre + value + suffix;
      decimal: chart.options.decimal,
      precision: chart.options.precision,
      round: chart.options.round,
      zeros: chart.options.zeros
    if (chart.options.bytes) {
      var series = chart.data;
      if (chartType === "pie") {
        series = [{data: series}];
      }

      // calculate max
      var max = 0;
      for (var i = 0; i < series.length; i++) {
        var s = series[i];
        for (var j = 0; j < s.data.length; j++) {
          if (s.data[j][1] > max) {
            max = s.data[j][1];
          }
        }
      }

      // calculate scale
      var scale = 1;
      while (max >= 1024) {
        scale *= 1024;
        max /= 1024;
      }

      // set step size
      formatOptions.byteScale = scale;
    }

      if (formatOptions.byteScale) {
        if (!myAxes[0].ticks.stepSize) {
          myAxes[0].ticks.stepSize = formatOptions.byteScale / 2;
        }
        if (!myAxes[0].ticks.maxTicksLimit) {
          myAxes[0].ticks.maxTicksLimit = 4;
        }
      }

          return formatValue("", value, formatOptions, true);
      decimal: chart.options.decimal,
      precision: chart.options.precision,
      round: chart.options.round,
      zeros: chart.options.zeros
})));