2011-04-27 15:17:11 -07:00
|
|
|
{
|
2014-01-27 14:01:27 -08:00
|
|
|
"name": "bowser",
|
2017-04-04 23:17:27 +03:00
|
|
|
"description": "Lightweight browser detector",
|
2026-02-09 00:03:04 +02:00
|
|
|
"files": [
|
2026-08-30 00:10:11 +03:00
|
|
|
"src",
|
2026-02-09 00:03:04 +02:00
|
|
|
"es5.js",
|
|
|
|
|
"bundled.js",
|
2026-08-30 00:10:11 +03:00
|
|
|
"bowser.mjs",
|
|
|
|
|
"index.d.ts",
|
|
|
|
|
"index.d.mts"
|
2026-02-09 00:03:04 +02:00
|
|
|
],
|
2014-01-27 14:01:27 -08:00
|
|
|
"keywords": [
|
|
|
|
|
"browser",
|
2017-04-04 23:17:27 +03:00
|
|
|
"useragent",
|
|
|
|
|
"user-agent",
|
|
|
|
|
"parser",
|
|
|
|
|
"ua",
|
|
|
|
|
"detection",
|
|
|
|
|
"ender",
|
|
|
|
|
"sniff"
|
2014-01-27 14:01:27 -08:00
|
|
|
],
|
2025-11-30 18:58:23 +02:00
|
|
|
"homepage": "https://github.com/bowser-js/bowser",
|
2014-01-27 14:01:27 -08:00
|
|
|
"author": "Dustin Diaz <dustin@dustindiaz.com> (http://dustindiaz.com)",
|
2018-06-27 23:04:25 +03:00
|
|
|
"contributors": [
|
|
|
|
|
{
|
|
|
|
|
"name": "Denis Demchenko",
|
|
|
|
|
"url": "http://twitter.com/lancedikson"
|
2025-11-23 00:08:32 +02:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"name": "Naor Peled",
|
|
|
|
|
"url": "https://github.com/naorpeled"
|
2018-06-27 23:04:25 +03:00
|
|
|
}
|
|
|
|
|
],
|
2018-08-02 21:36:41 +03:00
|
|
|
"main": "es5.js",
|
2019-09-10 19:02:13 +03:00
|
|
|
"browser": "es5.js",
|
2019-09-05 18:17:01 -03:00
|
|
|
"module": "src/bowser.js",
|
2019-07-30 11:18:59 +10:00
|
|
|
"types": "index.d.ts",
|
2026-08-30 00:10:11 +03:00
|
|
|
"exports": {
|
|
|
|
|
".": {
|
|
|
|
|
"import": {
|
|
|
|
|
"types": "./index.d.mts",
|
|
|
|
|
"default": "./bowser.mjs"
|
|
|
|
|
},
|
|
|
|
|
"require": {
|
|
|
|
|
"types": "./index.d.ts",
|
|
|
|
|
"default": "./es5.js"
|
|
|
|
|
},
|
|
|
|
|
"default": "./es5.js"
|
|
|
|
|
},
|
|
|
|
|
"./es5.js": "./es5.js",
|
|
|
|
|
"./es5": "./es5.js",
|
|
|
|
|
"./bundled.js": "./bundled.js",
|
|
|
|
|
"./bundled": "./bundled.js",
|
|
|
|
|
"./bowser.mjs": {
|
|
|
|
|
"types": "./index.d.mts",
|
|
|
|
|
"default": "./bowser.mjs"
|
|
|
|
|
},
|
|
|
|
|
"./src/bowser.js": "./src/bowser.js",
|
|
|
|
|
"./src/bowser": "./src/bowser.js",
|
|
|
|
|
"./src/constants.js": "./src/constants.js",
|
|
|
|
|
"./src/constants": "./src/constants.js",
|
|
|
|
|
"./src/parser.js": "./src/parser.js",
|
|
|
|
|
"./src/parser": "./src/parser.js",
|
|
|
|
|
"./src/parser-browsers.js": "./src/parser-browsers.js",
|
|
|
|
|
"./src/parser-browsers": "./src/parser-browsers.js",
|
|
|
|
|
"./src/parser-engines.js": "./src/parser-engines.js",
|
|
|
|
|
"./src/parser-engines": "./src/parser-engines.js",
|
|
|
|
|
"./src/parser-os.js": "./src/parser-os.js",
|
|
|
|
|
"./src/parser-os": "./src/parser-os.js",
|
|
|
|
|
"./src/parser-platforms.js": "./src/parser-platforms.js",
|
|
|
|
|
"./src/parser-platforms": "./src/parser-platforms.js",
|
|
|
|
|
"./src/utils.js": "./src/utils.js",
|
|
|
|
|
"./src/utils": "./src/utils.js",
|
|
|
|
|
"./package.json": "./package.json"
|
|
|
|
|
},
|
2014-01-27 14:01:27 -08:00
|
|
|
"repository": {
|
|
|
|
|
"type": "git",
|
2025-11-30 18:58:23 +02:00
|
|
|
"url": "git+https://github.com/bowser-js/bowser.git"
|
2014-01-27 14:01:27 -08:00
|
|
|
},
|
|
|
|
|
"devDependencies": {
|
2026-08-30 00:10:11 +03:00
|
|
|
"@arethetypeswrong/cli": "^0.18.5",
|
|
|
|
|
"@babel/cli": "^7.29.7",
|
|
|
|
|
"@babel/core": "^7.29.7",
|
|
|
|
|
"@babel/preset-env": "^7.29.7",
|
|
|
|
|
"@babel/register": "^7.29.7",
|
|
|
|
|
"@eslint/js": "^10.0.1",
|
|
|
|
|
"@rolldown/plugin-babel": "0.2.3",
|
2020-01-19 15:21:06 +00:00
|
|
|
"ava": "^3.0.0",
|
2026-08-30 00:10:11 +03:00
|
|
|
"babel-plugin-add-module-exports": "^1.0.4",
|
|
|
|
|
"babel-plugin-istanbul": "^8.0.0",
|
|
|
|
|
"core-js": "^3.49.0",
|
fix: resolve open GitHub security findings
Code scanning (js/polynomial-redos, alerts #16 and #17)
-------------------------------------------------------
bowser applies these regexps to attacker-controlled User-Agent strings, and
four of them ran in quadratic time:
* The "Something else" fallback used /^(.*)\/(.*) / and
/^(.*)\/(.*)[ \t]\((.*)/. Two unbounded `.*` before a required literal
make the split ambiguous, so a UA of "/a" repeated backtracks O(n^2).
Greedy `(.*)` always picks the last `/` that still has the delimiter
after it, so the second group can never span a `/` -- narrowing it to
`[^/]*` is exactly equivalent and removes the ambiguity. Verified
identical on 1,000,000 fuzzed inputs and on the full acceptance corpus.
* The Linespider and SlackBot version regexps used `(?:-[-\w]+)?` before a
required `[\s/]`. Since `[-\w]` and `[\s/]` are disjoint the backtracking
is pure waste, but the engine still walks it once per start position, so
"linespider-" repeated is quadratic. Bounding the run to `{1,64}` makes
it linear; no real bot-name suffix approaches 64 characters.
A sweep of all 253 regexp literals in src/ (fuzzed for superlinear scaling,
with the four pre-fix patterns used to confirm the detector works) reports no
remaining superlinear regexps. test/unit/redos.js locks this in.
Actions (actions/missing-workflow-permissions, alerts #5 and #15)
-----------------------------------------------------------------
merge-to-master.yml and draft-or-update-next-release.yml had no `permissions`
block and so inherited the default token. Both now declare least privilege,
matching publish.yml and pull-request.yml.
Dependabot (22 open alerts, all development scope)
--------------------------------------------------
bowser ships no runtime dependencies, so none of these reached consumers, but
they were live in CI. `pnpm audit` goes from 29 advisories to 0:
* jsdoc 3 -> 4 (with docdash 1 -> 2) drops taffydb, which has no patched
release, and picks up current markdown-it/linkify-it.
* coveralls -> coveralls-next 6 drops `request`, which is deprecated with no
patched release, along with form-data, qs 6.5.x, uuid 3 and tough-cookie 2.
Same `coveralls` bin and same stdin contract; lcov conversion verified.
* gh-pages 3 -> 6 clears the critical prototype pollution advisory.
* pnpm overrides pin the remaining transitive-only advisories to the lowest
patched release on each existing major.
Verified: pnpm audit clean, lint clean, 346 tests pass (the acceptance corpus
runs against both src/ and the built es5.js), build, package smoke test, and
doc generation.
2026-08-30 20:37:19 +03:00
|
|
|
"coveralls-next": "^6.0.2",
|
|
|
|
|
"docdash": "^2.0.2",
|
2026-08-30 00:10:11 +03:00
|
|
|
"eslint": "^10.8.0",
|
|
|
|
|
"eslint-config-airbnb-extended": "^3.1.0",
|
|
|
|
|
"eslint-plugin-ava": "^17.0.1",
|
|
|
|
|
"eslint-plugin-import": "^2.32.0",
|
fix: resolve open GitHub security findings
Code scanning (js/polynomial-redos, alerts #16 and #17)
-------------------------------------------------------
bowser applies these regexps to attacker-controlled User-Agent strings, and
four of them ran in quadratic time:
* The "Something else" fallback used /^(.*)\/(.*) / and
/^(.*)\/(.*)[ \t]\((.*)/. Two unbounded `.*` before a required literal
make the split ambiguous, so a UA of "/a" repeated backtracks O(n^2).
Greedy `(.*)` always picks the last `/` that still has the delimiter
after it, so the second group can never span a `/` -- narrowing it to
`[^/]*` is exactly equivalent and removes the ambiguity. Verified
identical on 1,000,000 fuzzed inputs and on the full acceptance corpus.
* The Linespider and SlackBot version regexps used `(?:-[-\w]+)?` before a
required `[\s/]`. Since `[-\w]` and `[\s/]` are disjoint the backtracking
is pure waste, but the engine still walks it once per start position, so
"linespider-" repeated is quadratic. Bounding the run to `{1,64}` makes
it linear; no real bot-name suffix approaches 64 characters.
A sweep of all 253 regexp literals in src/ (fuzzed for superlinear scaling,
with the four pre-fix patterns used to confirm the detector works) reports no
remaining superlinear regexps. test/unit/redos.js locks this in.
Actions (actions/missing-workflow-permissions, alerts #5 and #15)
-----------------------------------------------------------------
merge-to-master.yml and draft-or-update-next-release.yml had no `permissions`
block and so inherited the default token. Both now declare least privilege,
matching publish.yml and pull-request.yml.
Dependabot (22 open alerts, all development scope)
--------------------------------------------------
bowser ships no runtime dependencies, so none of these reached consumers, but
they were live in CI. `pnpm audit` goes from 29 advisories to 0:
* jsdoc 3 -> 4 (with docdash 1 -> 2) drops taffydb, which has no patched
release, and picks up current markdown-it/linkify-it.
* coveralls -> coveralls-next 6 drops `request`, which is deprecated with no
patched release, along with form-data, qs 6.5.x, uuid 3 and tough-cookie 2.
Same `coveralls` bin and same stdin contract; lcov conversion verified.
* gh-pages 3 -> 6 clears the critical prototype pollution advisory.
* pnpm overrides pin the remaining transitive-only advisories to the lowest
patched release on each existing major.
Verified: pnpm audit clean, lint clean, 346 tests pass (the acceptance corpus
runs against both src/ and the built es5.js), build, package smoke test, and
doc generation.
2026-08-30 20:37:19 +03:00
|
|
|
"gh-pages": "^6.3.0",
|
|
|
|
|
"jsdoc": "^4.0.5",
|
2026-08-30 00:10:11 +03:00
|
|
|
"nyc": "^18.0.0",
|
|
|
|
|
"publint": "^0.3.22",
|
|
|
|
|
"regenerator-runtime": "^0.14.1",
|
|
|
|
|
"sinon": "^22.0.0",
|
|
|
|
|
"terser": "^5.49.0",
|
fix: resolve open GitHub security findings
Code scanning (js/polynomial-redos, alerts #16 and #17)
-------------------------------------------------------
bowser applies these regexps to attacker-controlled User-Agent strings, and
four of them ran in quadratic time:
* The "Something else" fallback used /^(.*)\/(.*) / and
/^(.*)\/(.*)[ \t]\((.*)/. Two unbounded `.*` before a required literal
make the split ambiguous, so a UA of "/a" repeated backtracks O(n^2).
Greedy `(.*)` always picks the last `/` that still has the delimiter
after it, so the second group can never span a `/` -- narrowing it to
`[^/]*` is exactly equivalent and removes the ambiguity. Verified
identical on 1,000,000 fuzzed inputs and on the full acceptance corpus.
* The Linespider and SlackBot version regexps used `(?:-[-\w]+)?` before a
required `[\s/]`. Since `[-\w]` and `[\s/]` are disjoint the backtracking
is pure waste, but the engine still walks it once per start position, so
"linespider-" repeated is quadratic. Bounding the run to `{1,64}` makes
it linear; no real bot-name suffix approaches 64 characters.
A sweep of all 253 regexp literals in src/ (fuzzed for superlinear scaling,
with the four pre-fix patterns used to confirm the detector works) reports no
remaining superlinear regexps. test/unit/redos.js locks this in.
Actions (actions/missing-workflow-permissions, alerts #5 and #15)
-----------------------------------------------------------------
merge-to-master.yml and draft-or-update-next-release.yml had no `permissions`
block and so inherited the default token. Both now declare least privilege,
matching publish.yml and pull-request.yml.
Dependabot (22 open alerts, all development scope)
--------------------------------------------------
bowser ships no runtime dependencies, so none of these reached consumers, but
they were live in CI. `pnpm audit` goes from 29 advisories to 0:
* jsdoc 3 -> 4 (with docdash 1 -> 2) drops taffydb, which has no patched
release, and picks up current markdown-it/linkify-it.
* coveralls -> coveralls-next 6 drops `request`, which is deprecated with no
patched release, along with form-data, qs 6.5.x, uuid 3 and tough-cookie 2.
Same `coveralls` bin and same stdin contract; lcov conversion verified.
* gh-pages 3 -> 6 clears the critical prototype pollution advisory.
* pnpm overrides pin the remaining transitive-only advisories to the lowest
patched release on each existing major.
Verified: pnpm audit clean, lint clean, 346 tests pass (the acceptance corpus
runs against both src/ and the built es5.js), build, package smoke test, and
doc generation.
2026-08-30 20:37:19 +03:00
|
|
|
"testem": "^3.20.2",
|
2026-08-30 00:10:11 +03:00
|
|
|
"tsdown": "^0.22.14",
|
|
|
|
|
"typescript": "^5.9.3",
|
2017-08-20 18:21:17 +03:00
|
|
|
"yamljs": "^0.3.0"
|
2017-04-09 17:13:00 +03:00
|
|
|
},
|
|
|
|
|
"ava": {
|
|
|
|
|
"require": [
|
2019-01-19 12:07:15 +02:00
|
|
|
"@babel/register"
|
2026-08-30 00:10:11 +03:00
|
|
|
],
|
|
|
|
|
"files": [
|
|
|
|
|
"test/**/*.js",
|
|
|
|
|
"!test/package/**"
|
2019-01-19 12:07:15 +02:00
|
|
|
]
|
2015-05-03 13:14:06 +02:00
|
|
|
},
|
|
|
|
|
"bugs": {
|
2025-11-30 18:58:23 +02:00
|
|
|
"url": "https://github.com/bowser-js/bowser/issues"
|
2015-05-03 13:14:06 +02:00
|
|
|
},
|
|
|
|
|
"directories": {
|
|
|
|
|
"test": "test"
|
|
|
|
|
},
|
|
|
|
|
"scripts": {
|
2026-08-30 00:10:11 +03:00
|
|
|
"build": "tsdown",
|
|
|
|
|
"generate-and-deploy-docs": "pnpm generate-docs && gh-pages --dist docs --dest docs",
|
|
|
|
|
"watch": "tsdown --watch",
|
2023-11-13 11:11:28 +02:00
|
|
|
"lint:check": "eslint ./src",
|
|
|
|
|
"lint:fix": "eslint --fix ./src",
|
2017-08-20 18:37:01 +03:00
|
|
|
"testem": "testem",
|
2018-09-09 14:01:45 +03:00
|
|
|
"test": "nyc --reporter=html --reporter=text ava",
|
2018-12-27 17:49:58 +01:00
|
|
|
"test:watch": "ava --watch",
|
2026-08-30 00:10:11 +03:00
|
|
|
"test:package": "node test/package/smoke.cjs",
|
2018-07-05 22:44:43 +03:00
|
|
|
"coverage": "nyc report --reporter=text-lcov | coveralls",
|
2019-07-16 21:56:06 +03:00
|
|
|
"generate-docs": "jsdoc -c jsdoc.json"
|
2015-05-03 13:14:06 +02:00
|
|
|
},
|
2026-08-30 00:10:11 +03:00
|
|
|
"license": "MIT",
|
|
|
|
|
"packageManager": "pnpm@11.18.0"
|
2011-04-27 15:17:11 -07:00
|
|
|
}
|