# browserslist@4.28.9 security report (npm)

- Verdict: **Needs review** (risk level: medium)
- Scanned: 2026-10-06T14:14:00.000Z
- Files reviewed: 6
- Findings: 1 medium, 3 low severity findings
- Report: https://security.togoder.click/npm/browserslist
- Source: Togoder Security (https://security.togoder.click), AI source-code review

## Summary

Togoder Security scanned the npm package browserslist@4.28.9 on Oct 6, 2026. An AI review of 6 source files produced 1 medium, 3 low severity findings. The overall verdict is medium: the findings flag risky but common patterns (dynamic code, unsafe defaults, broad file or network access) rather than confirmed malware.

## Findings

### [medium] Dynamic module loading with computed input

Finding ID: `NPS-8B833FCA6B46`

File: `node.js:212`

loadQueries uses require(require.resolve(name, { paths: ['.', ctx.path] })) where name comes from external configuration/environment; this allows arbitrary module resolution and execution. Although checkExtend applies restrictive regex patterns and can be bypassed via dangerousExtend or BROWSERSLIST_DANGEROUS_EXTEND env var, it is still a dynamic require of external input.

### [low] Dynamic require based on sanitized input

Finding ID: `NPS-8B14D17F2748`

File: `node.js:283`

loadCountry and loadFeature perform require('caniuse-lite/data/regions/' + code + '.js') and require('caniuse-lite/data/features/' + name + '.js') after stripping non-word/non-dash characters; path traversal is mitigated by the regex but still constitutes computed dynamic module loading.

### [low] File system access outside package scope

Finding ID: `NPS-D1C50838406D`

File: `node.js:322`

Functions read package.json, browserslist, .browserslistrc, and browserslist-stats.json files from parent directories up to BROWSERSLIST_ROOT_PATH (or filesystem root). readConfig/parsePackage read arbitrary user-specified config paths via opts.config or BROWSERSLIST_CONFIG.

### [low] Environment variable harvesting

Finding ID: `NPS-2512E7C19589`

File: `node.js:341`

Multiple process.env variables are read (BROWSERSLIST, BROWSERSLIST_CONFIG, BROWSERSLIST_ENV, BROWSERSLIST_STATS, BROWSERSLIST_ROOT_PATH, NODE_ENV, etc.), and module.exports.env exposes process.env directly. This is standard configuration behavior but exposes environment state and can be abused if the object is leaked.

## Files reviewed

- `node.js` (medium): The code is a legitimate browserslist configuration loader but contains several dynamic require calls and broad environment/filesystem reads that could be abused if attacker-controlled inputs reach these functions.
- `browser.js` (safe): Cleared by Jev triage; no further analysis needed
- `cli.js` (safe): Standard browserslist CLI implementation with no malicious patterns detected; it reads local config/stats files and prints query results, only performing a deprecation-triggered DB update via the legitimate update-browserslist-db dependency.
- `error.js` (safe): Cleared by Jev triage; no further analysis needed
- `index.js` (safe): No malicious patterns detected; the code is a standard browserslist query parser with only static requires and no network, filesystem, or process execution activity.
- `parse.js` (safe): Cleared by Jev triage; no further analysis needed

AI analysis is guidance, not a guarantee. Methodology: https://security.togoder.click/methodology
