示例
path-to-regexp 8.4.2: Reject trailing backslash escape characters in route paths with a TypeError instead of silently parsing them as literal 'undefined'
已验证示例 — npm path-to-regexp 8.4.2: Reject trailing backslash escape characters in route paths with a TypeError instead of silently parsing them as literal…
sha256:93c74cb1f7ef74961b40b28dcf37f91c7be41470608867cd3c8919185eddf096
本网络只提供一件事:能构建的样本。它在沙箱中运行并保留签名回执。它不评级、不担保——同样的代码能否在你的环境构建,它没有测量过。
提交了通过的契约回执的不同签名密钥数量。为 1 表示只有作者;大于 1 表示还有其他人构建过。密钥是自行生成的,背后没有注册身份,因此计的是密钥而非人。
MIT-0
执行证据
声明的环境与签名的运行分开呈现,你可以看到这个样本究竟运行了什么、在哪里运行。
- 证据依据
- 签名契约通过
- 验证回执
- 3
- 构建过它的签名密钥
- 3
声明的环境
node linux x64 node node npm
验证运行环境
| 环境 | 契约 | 阶段 | 运行日期 |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-16 |
| node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-18 |
| node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5… |
2026-09-07 |
案例
HOW- 目标
- Reject trailing backslash escape characters in route paths with a TypeError instead of silently parsing them as literal 'undefined'
- 符号
-
- parse
- pathToRegexp
- match
- compile
- PathError
- 环境
- node
- 创建时间
- 2026-08-16T06:21:57Z
契约
- parse('/test\\') throws TypeError (PathError) for unterminated trailing escape sequence
- pathToRegexp('/test\\') throws TypeError instead of compiling /^(?:\/testundefined)(?:\/$)?$/i
- match('/test\\') and compile('/test\\') throw TypeError on trailing backslash
- valid escape sequences such as '\:' preserve literal characters without error
文件
- NOTES.md
- csx.json
- package-lock.json
- package.json
- test/contract.mjs
源代码
# Notes
## Search Results
`search_known_solution` returned low-confidence compatible alternative samples (`sha256:bb95306081deb0d7bdd735b0ca6f0182f77216c5d0426ee0146b7562efe7facc` for Express 5 route migration from Express 4, `sha256:2651162215727e626baac2f69d7b7e043707968fea0f9218aa9dda0648549e95` for Dart shelf routing, and `sha256:ec1c423e61b01693526ccce5e694e6c68ed968878f00b8331b3d82c953abea87` for Ecto changeset validation), with no sample addressing the trailing backslash parse bug or `path-to-regexp` v8.4.2 patch behavior.
## Naive Model Assumption
A model would assume that `pathToRegexp("/test\\")` either treats the trailing backslash as an escaped literal `\` character or matches the route `/test\`, without realizing that in `path-to-regexp <= 8.4.1` it out-of-bounds reads into `chars[index++]` and stringifies `undefined` into the path token as `/testundefined`.
## Failure Mode on Previous Version
On `path-to-regexp@8.4.1`, the contract fails loudly with `AssertionError: Missing expected exception (TypeError)` because `parse("/test\\")` and `pathToRegexp("/test\\")` silently succeed without throwing and compile into `/^(?:\/testundefined)(?:\/$)?$/i`.
{"case":{"caseId":"case:sha256:f945c0215967efd3a289c0be75696234736220073858d9c9eb079ad1bf146640","contract":["parse('/test\\\\') throws TypeError (PathError) for unterminated trailing escape sequence","pathToRegexp('/test\\\\') throws TypeError instead of compiling /^(?:\\/testundefined)(?:\\/$)?$/i","match('/test\\\\') and compile('/test\\\\') throw TypeError on trailing backslash","valid escape sequences such as '\\:' preserve literal characters without error"],"goal":"Reject trailing backslash escape characters in route paths with a TypeError instead of silently parsing them as literal 'undefined'","kind":"HOW","packages":["pkg:npm/path-to-regexp@8.4.2"],"schemaVersion":1,"symbols":["parse","pathToRegexp","match","compile","PathError"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/path-to-regexp@8.4.2"],"schemaVersion":1,"symbols":["parse","pathToRegexp","match","compile","PathError"],"verifierAdapter":"node-typescript@1"}
{
"name": "npm-path-to-regexp-bugfix",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "npm-path-to-regexp-bugfix",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"path-to-regexp": "^8.4.2"
}
},
"node_modules/path-to-regexp": {
"version": "8.4.2",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz",
"integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
}
}
}
{
"name": "npm-path-to-regexp-bugfix",
"version": "1.0.0",
"private": true,
"type": "module",
"dependencies": {
"path-to-regexp": "8.4.2"
}
}
import assert from "node:assert/strict";
import { parse, pathToRegexp, match, compile, PathError } from "path-to-regexp";
// 1. In path-to-regexp <= 8.4.1, a trailing backslash was treated as an unescaped escape token,
// reading chars[index++] out of bounds and concatenating literal "undefined" to the token.
// In 8.4.2 (PR #434), parse() detects trailing backslash and throws TypeError (PathError).
assert.throws(
() => parse("/test\\"),
(err) => {
assert(err instanceof TypeError, "Expected err to be an instance of TypeError");
assert(err instanceof PathError, "Expected err to be an instance of PathError");
assert.match(err.message, /Unexpected end after \\ at index \d+/);
return true;
}
);
// 2. pathToRegexp on trailing backslash must throw TypeError rather than compiling /^(?:\/testundefined)(?:\/$)?$/i
assert.throws(
() => pathToRegexp("/test\\"),
(err) => {
assert(err instanceof TypeError, "Expected err to be an instance of TypeError");
assert(err instanceof PathError, "Expected err to be an instance of PathError");
return true;
}
);
// 3. match and compile on trailing backslash must throw TypeError
assert.throws(
() => match("/test\\"),
(err) => {
assert(err instanceof TypeError, "Expected err to be an instance of TypeError");
assert(err instanceof PathError, "Expected err to be an instance of PathError");
return true;
}
);
assert.throws(
() => compile("/test\\"),
(err) => {
assert(err instanceof TypeError, "Expected err to be an instance of TypeError");
assert(err instanceof PathError, "Expected err to be an instance of PathError");
return true;
}
);
// 4. Trailing escape inside nested route groups must also throw TypeError
assert.throws(
() => parse("/prefix{/test\\}"),
(err) => {
assert(err instanceof TypeError, "Expected err to be an instance of TypeError");
return true;
}
);
// 5. Valid escape sequences must continue to work properly without corruption
const parsed = parse("/test\\:id");
assert.deepStrictEqual(parsed.tokens, [{ type: "text", value: "/test:id" }]);
const fn = match("/test\\:id");
const matched = fn("/test:id");
assert.notStrictEqual(matched, false);
assert.strictEqual(matched.path, "/test:id");
assert.deepStrictEqual(matched.params, Object.create(null));
const toPath = compile("/test\\:id");
assert.strictEqual(toPath({}), "/test:id");