VYPR
High severityNVD Advisory· Published Dec 31, 2022· Updated Aug 5, 2024

rgb2hex redos

CVE-2018-25061

Description

A vulnerability was found in rgb2hex up to 0.1.5. It has been rated as problematic. This issue affects some unknown processing. The manipulation leads to inefficient regular expression complexity. The attack may be initiated remotely. Upgrading to version 0.1.6 is able to address this issue. The patch is named 9e0c38594432edfa64136fdf7bb651835e17c34f. It is recommended to upgrade the affected component. The associated identifier of this vulnerability is VDB-217151.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

CVE-2018-25061 is a regular expression denial-of-service (ReDoS) vulnerability in rgb2hex up to 0.1.5, patched in version 0.1.6.

Vulnerability

Details

CVE-2018-25061 describes a regular expression denial-of-service (ReDoS) vulnerability in the rgb2hex library, versions 0.1.5 and earlier. The root cause lies in an inefficient regular expression used to parse RGB/RGBA color strings. As shown in the patch [3], the original regex /rgba?\((\d+),(\d+),(\d+)(,(\d+)?\.?(\d+))?\);?/ could be forced into catastrophic backtracking when processing specially crafted input, leading to excessive CPU consumption.

Attack

Vector

The vulnerability is remotely exploitable with no authentication required. An attacker can supply a malformed but valid-looking color string to any application using the vulnerable rgb2hex library. Because the library is commonly used in web browsers and Node.js servers to convert color formats, any endpoint that accepts user-supplied color values (e.g., form fields, API parameters) could trigger the ReDoS condition. The fix [2] introduces a rewritten regex that constrains the number of digits and removes ambiguous quantifiers, eliminating the exponential backtracking path.

Impact

Successful exploitation causes the application to become unresponsive while the regex engine processes the malicious input, effectively resulting in a denial-of-service (DoS). The attack can tie up server threads or browser event loops, degrading service availability for legitimate users. No data confidentiality or integrity is affected, but the availability impact can be severe in multi-tenant environments.

Remediation

The rgb2hex project released version 0.1.6 on July 5, 2018, which includes the patch commit 9e0c38594432edfa64136fdf7bb651835e17c34f [3]. All users are strongly advised to upgrade to 0.1.6 or later. No other workarounds are documented. The vulnerability does not appear on CISA's Known Exploited Vulnerabilities (KEV) catalog as of this writing.

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
rgb2hexnpm
< 0.1.60.1.6

Affected products

3

Patches

1
9e0c38594432

prevent Regular Expression Denial of Service attacks

https://github.com/christian-bromann/rgb2hexchristian-bromannJul 5, 2018via ghsa
4 files changed · +28 16
  • index.js+7 7 modified
    @@ -28,21 +28,21 @@ var rgb2hex = module.exports = function rgb2hex(color) {
         /**
          * parse input
          */
    -    var digits = /rgba?\((\d+),(\d+),(\d+)(,(\d+)?\.?(\d+))?\);?/.exec(strippedColor);
    +    var digits = /(.*?)rgb(a)??\((\d{1,3}),(\d{1,3}),(\d{1,3})(,[01]??\.([0-9]{0,3}))??\)/.exec(strippedColor);
     
         if(!digits) {
             // or throw error if input isn't a valid rgb(a) color
             throw new Error('given color (' + color + ') isn\'t a valid rgb or rgba color');
         }
     
    -    var red = parseInt(digits[1], 10);
    -    var green = parseInt(digits[2], 10);
    -    var blue = parseInt(digits[3], 10);
    -    var alpha = digits[4] ? /([0-9\.]+)/.exec(digits[4])[0] : '1';
    +    var red = parseInt(digits[3], 10);
    +    var green = parseInt(digits[4], 10);
    +    var blue = parseInt(digits[5], 10);
    +    var alpha = digits[6] ? /([0-9\.]+)/.exec(digits[6])[0] : '1';
         var rgb = ((blue | green << 8 | red << 16) | 1 << 24).toString(16).slice(1);
     
         // parse alpha value into float
    -    if(alpha.substr(0,1) === '.') {
    +    if(alpha.substr(0,2) === ',.') {
             alpha = parseFloat('0' + alpha);
         }
     
    @@ -58,4 +58,4 @@ var rgb2hex = module.exports = function rgb2hex(color) {
             hex: '#' + rgb.toString(16),
             alpha: alpha
         };
    -};
    +};
    \ No newline at end of file
    
  • rgb2hex.js+6 6 modified
    @@ -21,21 +21,21 @@
             /**
              * parse input
              */
    -        var digits = /rgba?\((\d+),(\d+),(\d+)(,(\d+)?\.?(\d+))?\);?/.exec(strippedColor);
    +        var digits = /(.*?)rgb(a)??\((\d{1,3}),(\d{1,3}),(\d{1,3})(,[01]??\.([0-9]{0,3}))??\)/.exec(strippedColor);
     
             if(!digits) {
                 // or throw error if input isn't a valid rgb(a) color
                 throw new Error('given color (' + color + ') isn\'t a valid rgb or rgba color');
             }
     
    -        var red = parseInt(digits[1], 10);
    -        var green = parseInt(digits[2], 10);
    -        var blue = parseInt(digits[3], 10);
    -        var alpha = digits[4] ? /([0-9\.]+)/.exec(digits[4])[0] : '1';
    +        var red = parseInt(digits[3], 10);
    +        var green = parseInt(digits[4], 10);
    +        var blue = parseInt(digits[5], 10);
    +        var alpha = digits[6] ? /([0-9\.]+)/.exec(digits[6])[0] : '1';
             var rgb = ((blue | green << 8 | red << 16) | 1 << 24).toString(16).slice(1);
     
             // parse alpha value into float
    -        if(alpha.substr(0,1) === '.') {
    +        if(alpha.substr(0,2) === ',.') {
                 alpha = parseFloat('0' + alpha);
             }
     
    
  • rgb2hex.min.js+1 1 modified
    @@ -1 +1 @@
    -!function(r){var e=function(r){if("string"!=typeof r)throw new Error("color has to be type of `string`");if("#"===r.substr(0,1))return{hex:r,alpha:1};var e=r.replace(/\s+/g,""),t=/rgba?\((\d+),(\d+),(\d+)(,(\d+)?\.?(\d+))?\);?/.exec(e);if(!t)throw new Error("given color ("+r+") isn't a valid rgb or rgba color");var n=parseInt(t[1],10),o=parseInt(t[2],10),a=parseInt(t[3],10),i=t[4]?/([0-9\.]+)/.exec(t[4])[0]:"1",s=(a|o<<8|n<<16|1<<24).toString(16).slice(1);return"."===i.substr(0,1)&&(i=parseFloat("0"+i)),1<i&&(i=1),i=parseFloat(Math.round(100*i))/100,{hex:"#"+s.toString(16),alpha:i}};"function"==typeof define&&define.amd?define("rgb2hex",function(){return e}):r.rgb2hex=e}(window);
    \ No newline at end of file
    +!function(r){var e=function(r){if("string"!=typeof r)throw new Error("color has to be type of `string`");if("#"===r.substr(0,1))return{hex:r,alpha:1};var e=r.replace(/\s+/g,""),t=/(.*?)rgb(a)??\((\d{1,3}),(\d{1,3}),(\d{1,3})(,[01]??\.([0-9]{0,3}))??\)/.exec(e);if(!t)throw new Error("given color ("+r+") isn't a valid rgb or rgba color");var n=parseInt(t[3],10),o=parseInt(t[4],10),a=parseInt(t[5],10),i=t[6]?/([0-9\.]+)/.exec(t[6])[0]:"1",s=(a|o<<8|n<<16|1<<24).toString(16).slice(1);return",."===i.substr(0,2)&&(i=parseFloat("0"+i)),1<i&&(i=1),i=parseFloat(Math.round(100*i))/100,{hex:"#"+s.toString(16),alpha:i}};"function"==typeof define&&define.amd?define("rgb2hex",function(){return e}):r.rgb2hex=e}(window);
    \ No newline at end of file
    
  • test/rgb2hex.test.js+14 2 modified
    @@ -80,10 +80,22 @@ describe('rgb2hex should', () => {
             })
     
             it('by limiting alpha value to 1', () => {
    -            var input = 'rgba(12,173,22,12312.67)'
    +            var input = 'rgba(12,173,22,1.67)'
                 expect(rgb2hex(input).alpha).not.toBeGreaterThan(1)
             })
     
    +        it('by not accepting to big values', () => {
    +            var input = 'rgba(1123, 54, 4, 0.33)'
    +            expect(() => rgb2hex(input)).toThrow(invalidErrorMessage(input))
    +            input = 'rgba(113, 1154, 4, 0.33)'
    +            expect(() => rgb2hex(input)).toThrow(invalidErrorMessage(input))
    +            input = 'rgba(113, 154, 1114, 0.33)'
    +            expect(() => rgb2hex(input)).toThrow(invalidErrorMessage(input))
    +            input = 'rgba(113, 54, 4, 2.33)'
    +            expect(() => rgb2hex(input)).toThrow(invalidErrorMessage(input))
    +            input = 'rgbaaaaaa(113, 54, 4, .33)'
    +            expect(() => rgb2hex(input)).toThrow(invalidErrorMessage(input))
    +        })
         })
     
         describe('not care about', () => {
    @@ -132,4 +144,4 @@ describe('rgb2hex should', () => {
                 expect(rgb2hex(`${values}rgba(226,230,233,0.4)${values}`).hex)
             })
         })
    -})
    +})
    \ No newline at end of file
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.