refactor: extract normalizeUrls into src/kilocode/util/url.ts

Move Kilo-specific URL normalization logic out of shared upstream files
and into a mirror file under src/kilocode/, with kilocode_change markers
at each call site per the fork merge minimization convention.
This commit is contained in:
Catriel Müller
2026-05-11 11:57:12 -03:00
parent 862fed158f
commit 9fe37aeb39
4 changed files with 22 additions and 34 deletions
@@ -19,21 +19,10 @@ import { useDialog } from "../../ui/dialog"
import { getScrollAcceleration } from "../../util/scroll"
import { useTuiConfig } from "../../context/tui-config"
import { ConfigProtection } from "@/kilocode/permission/config-paths" // kilocode_change
import { normalizeUrls } from "@/kilocode/util/url" // kilocode_change
type PermissionStage = "permission" | "always" | "reject"
// Convert IDN/Unicode hostnames to punycode ASCII in any http/https URLs found
// in the given string, to prevent homograph attacks in permission dialogs.
function normalizeUrls(text: string) {
return text.replace(/https?:\/\/\S+/g, (match) => {
try {
return new URL(match).href
} catch {
return match
}
})
}
function normalizePath(input?: string) {
if (!input) return ""
@@ -0,0 +1,18 @@
/**
* Normalize any http/https URLs in a string so that IDN/Unicode hostnames are
* converted to their punycode ASCII form, preventing homograph attacks in
* permission dialogs where visually identical Unicode characters (e.g. Cyrillic
* 'а' U+0430) could impersonate trusted domains (e.g. 'apitest.com').
*
* Example: "curl https://аpitest.com/status" (Cyrillic а)
* → "curl https://xn--pitest-2nf.com/status"
*/
export function normalizeUrls(text: string) {
return text.replace(/https?:\/\/\S+/g, (match) => {
try {
return new URL(match).href
} catch {
return match
}
})
}
+1 -12
View File
@@ -20,6 +20,7 @@ import { Shell } from "@/shell/shell"
import { BashArity } from "@/permission/arity"
import * as Truncate from "./truncate"
import { Plugin } from "@/plugin"
import { normalizeUrls } from "@/kilocode/util/url" // kilocode_change
import { Effect, Stream } from "effect"
import { ChildProcess } from "effect/unstable/process"
import { ChildProcessSpawner } from "effect/unstable/process/ChildProcessSpawner"
@@ -238,18 +239,6 @@ function preview(text: string) {
return "...\n\n" + text.slice(-MAX_METADATA_LENGTH)
}
// Normalize any http/https URLs in a command string so that IDN/Unicode hostnames
// are converted to their punycode ASCII form, preventing homograph attacks in
// permission dialogs where "аpitest.com" (Cyrillic) looks identical to "apitest.com".
function normalizeUrls(text: string) {
return text.replace(/https?:\/\/\S+/g, (match) => {
try {
return new URL(match).href
} catch {
return match
}
})
}
function tail(text: string, maxLines: number, maxBytes: number) {
const lines = text.split("\n")
+2 -10
View File
@@ -4,6 +4,7 @@ import * as Tool from "./tool"
import TurndownService from "turndown"
import DESCRIPTION from "./webfetch.txt"
import { isImageAttachment } from "@/util/media"
import { normalizeUrls } from "@/kilocode/util/url" // kilocode_change
const MAX_RESPONSE_SIZE = 5 * 1024 * 1024 // 5MB
const DEFAULT_TIMEOUT = 30 * 1000 // 30 seconds
@@ -34,16 +35,7 @@ export const WebFetchTool = Tool.define(
throw new Error("URL must start with http:// or https://")
}
// Normalize URL: convert IDN/Unicode hostnames to punycode ASCII to prevent
// homograph attacks where visually similar Unicode characters impersonate trusted domains.
// e.g. "аpitest.com" (Cyrillic а) → "xn--pitest-n5b.com"
const url = (() => {
try {
return new URL(params.url).href
} catch {
return params.url
}
})()
const url = normalizeUrls(params.url) // kilocode_change
yield* ctx.ask({
permission: "webfetch",