mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-10-24 01:24:18 +08:00
test(vscode): extract CSP string building and add policy directive tests
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import * as crypto from "crypto"
|
||||
import * as vscode from "vscode"
|
||||
import { buildCspString } from "./webview-html-utils"
|
||||
|
||||
export function getNonce(): string {
|
||||
return crypto.randomBytes(16).toString("hex")
|
||||
@@ -17,18 +18,7 @@ export function buildWebviewHtml(
|
||||
},
|
||||
): string {
|
||||
const nonce = getNonce()
|
||||
const connectSrc = opts.port
|
||||
? `http://127.0.0.1:${opts.port} http://localhost:${opts.port} ws://127.0.0.1:${opts.port} ws://localhost:${opts.port}`
|
||||
: "http://127.0.0.1:* http://localhost:* ws://127.0.0.1:* ws://localhost:*"
|
||||
|
||||
const csp = [
|
||||
"default-src 'none'",
|
||||
`style-src 'unsafe-inline' ${webview.cspSource}`,
|
||||
`script-src 'nonce-${nonce}' 'wasm-unsafe-eval'`,
|
||||
`font-src ${webview.cspSource}`,
|
||||
`connect-src ${connectSrc}`,
|
||||
`img-src ${webview.cspSource} data: https:`,
|
||||
].join("; ")
|
||||
const csp = buildCspString(webview.cspSource, nonce, opts.port)
|
||||
|
||||
return `<!DOCTYPE html>
|
||||
<html lang="en" data-theme="kilo-vscode">
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Build the Content-Security-Policy connect-src directive value.
|
||||
* If a port is specified, restricts connections to that port.
|
||||
* Otherwise, allows any localhost/127.0.0.1 port.
|
||||
*/
|
||||
export function buildConnectSrc(port?: number): string {
|
||||
if (port) {
|
||||
return `http://127.0.0.1:${port} http://localhost:${port} ws://127.0.0.1:${port} ws://localhost:${port}`
|
||||
}
|
||||
return "http://127.0.0.1:* http://localhost:* ws://127.0.0.1:* ws://localhost:*"
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an array of CSP directives into a policy string.
|
||||
*/
|
||||
export function joinCspDirectives(directives: string[]): string {
|
||||
return directives.join("; ")
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the full CSP policy string for a webview.
|
||||
*/
|
||||
export function buildCspString(cspSource: string, nonce: string, port?: number): string {
|
||||
const connectSrc = buildConnectSrc(port)
|
||||
const directives = [
|
||||
"default-src 'none'",
|
||||
`style-src 'unsafe-inline' ${cspSource}`,
|
||||
`script-src 'nonce-${nonce}' 'wasm-unsafe-eval'`,
|
||||
`font-src ${cspSource}`,
|
||||
`connect-src ${connectSrc}`,
|
||||
`img-src ${cspSource} data: https:`,
|
||||
]
|
||||
return joinCspDirectives(directives)
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import { describe, it, expect } from "bun:test"
|
||||
import { buildConnectSrc, buildCspString } from "../../src/webview-html-utils"
|
||||
|
||||
describe("buildConnectSrc", () => {
|
||||
it("uses wildcard ports when no port specified", () => {
|
||||
const result = buildConnectSrc()
|
||||
expect(result).toContain("http://127.0.0.1:*")
|
||||
expect(result).toContain("http://localhost:*")
|
||||
expect(result).toContain("ws://127.0.0.1:*")
|
||||
expect(result).toContain("ws://localhost:*")
|
||||
})
|
||||
|
||||
it("restricts to specific port when port provided", () => {
|
||||
const result = buildConnectSrc(3000)
|
||||
expect(result).toContain("http://127.0.0.1:3000")
|
||||
expect(result).toContain("http://localhost:3000")
|
||||
expect(result).toContain("ws://127.0.0.1:3000")
|
||||
expect(result).toContain("ws://localhost:3000")
|
||||
})
|
||||
|
||||
it("does not include wildcard when port is provided", () => {
|
||||
const result = buildConnectSrc(3000)
|
||||
expect(result).not.toContain(":*")
|
||||
})
|
||||
|
||||
it("uses the exact port number", () => {
|
||||
expect(buildConnectSrc(54321)).toContain(":54321")
|
||||
})
|
||||
})
|
||||
|
||||
describe("buildCspString", () => {
|
||||
const cspSource = "vscode-resource://test"
|
||||
const nonce = "abc123"
|
||||
|
||||
it("includes default-src 'none'", () => {
|
||||
expect(buildCspString(cspSource, nonce)).toContain("default-src 'none'")
|
||||
})
|
||||
|
||||
it("includes nonce in script-src", () => {
|
||||
const result = buildCspString(cspSource, nonce)
|
||||
expect(result).toContain(`'nonce-${nonce}'`)
|
||||
expect(result).toContain("'wasm-unsafe-eval'")
|
||||
})
|
||||
|
||||
it("includes cspSource in style-src and font-src", () => {
|
||||
const result = buildCspString(cspSource, nonce)
|
||||
expect(result).toContain(`style-src 'unsafe-inline' ${cspSource}`)
|
||||
expect(result).toContain(`font-src ${cspSource}`)
|
||||
})
|
||||
|
||||
it("includes cspSource and https: in img-src", () => {
|
||||
const result = buildCspString(cspSource, nonce)
|
||||
expect(result).toContain("img-src")
|
||||
expect(result).toContain(cspSource)
|
||||
expect(result).toContain("https:")
|
||||
expect(result).toContain("data:")
|
||||
})
|
||||
|
||||
it("uses wildcard connect-src when no port provided", () => {
|
||||
const result = buildCspString(cspSource, nonce)
|
||||
expect(result).toContain("http://127.0.0.1:*")
|
||||
})
|
||||
|
||||
it("uses specific port in connect-src when port provided", () => {
|
||||
const result = buildCspString(cspSource, nonce, 9000)
|
||||
expect(result).toContain("http://127.0.0.1:9000")
|
||||
expect(result).not.toContain(":*")
|
||||
})
|
||||
|
||||
it("joins directives with semicolons", () => {
|
||||
const result = buildCspString(cspSource, nonce)
|
||||
const parts = result.split(";")
|
||||
expect(parts.length).toBeGreaterThanOrEqual(5)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user