fix(app): swallow URIError in assistant file link parser on bare '%'

decodeURIComponent throws on '%' not followed by two hex digits. The two
calls inside parseAssistantFileLink and normalizeFileUrlPath had no
try/catch, so any timeline message containing strings like '100% packet
loss' (ping output), '%PATH%' or '0% off' could escape into the React
tree and unmount the agent route, leaving the renderer blank.

Wrap both calls in a local safeDecodeURIComponent that returns the input
unchanged when decoding fails, mirroring the helper already used in
host-routes.ts.

Closes #1148
This commit is contained in:
ElliotWu
2026-05-25 10:05:00 +00:00
committed by GitHub
parent 178708a44e
commit 8a2e5c786e
2 changed files with 29 additions and 2 deletions
@@ -360,6 +360,25 @@ describe("parseAssistantFileLink", () => {
}),
).toBeNull();
});
it("does not throw when the input contains a literal '%' that is not a valid percent-escape", () => {
// Regressions for tool output strings like ping's "100% packet loss",
// Windows "%PATH%" references, and percentages such as "0% off".
// decodeURIComponent throws URIError on these; the parser must swallow
// it and return null rather than crash the renderer.
const cases = [
"/tmp/100% packet loss",
"/Users/test/project/0% off",
"/var/log/%PATH%/x.log",
"file:///tmp/100% packet loss",
];
for (const value of cases) {
expect(() =>
parseAssistantFileLink(value, { workspaceRoot: "/Users/test/project" }),
).not.toThrow();
}
expect(() => parseFileProtocolUrl("file:///tmp/100% packet loss")).not.toThrow();
});
});
describe("normalizeInlinePathTarget", () => {