Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/build-preview-docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@ jobs:

steps:
- name: Checkout code (commit from CI run)
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
ref: ${{ github.event.workflow_run.head_sha }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
Expand All @@ -49,14 +49,14 @@ jobs:
version: 10

- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: "pnpm"
cache-dependency-path: ui/pnpm-lock.yaml

- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ env.GO_VERSION }}
cache: true
Expand All @@ -75,7 +75,7 @@ jobs:
run: make cross-compile

- name: Build and push Docker image
uses: docker/build-push-action@v6
uses: docker/build-push-action@v7
with:
context: .
file: ./Dockerfile.binary
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,20 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5

- uses: pnpm/action-setup@v4
with:
version: 10
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: "pnpm"
cache-dependency-path: ui/pnpm-lock.yaml

- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ env.GO_VERSION }}
cache: true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0
- uses: pnpm/action-setup@v3
Expand Down
18 changes: 9 additions & 9 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,36 +24,36 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to Docker hub Registry
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v3
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4

- uses: pnpm/action-setup@v4
with:
version: 10
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: "pnpm"
cache-dependency-path: ui/pnpm-lock.yaml

- name: Setup Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: ${{ env.GO_VERSION }}
cache: true
Expand All @@ -75,7 +75,7 @@ jobs:
run: make package-binaries

- name: Build and push image
uses: docker/build-push-action@v6
uses: docker/build-push-action@v7
with:
context: .
file: ./Dockerfile.binary
Expand Down Expand Up @@ -117,7 +117,7 @@ jobs:
contents: write
steps:
- name: Checkout gh-pages
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
ref: gh-pages
fetch-depth: 0
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:20-alpine AS frontend-builder
FROM node:24-alpine AS frontend-builder

WORKDIR /app/ui

Expand Down
11 changes: 10 additions & 1 deletion pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"k8s.io/apimachinery/pkg/util/rand"
)

const kiteAssetBasePlaceholder = "__KITE_ASSET_BASE__"

func InjectAnalytics(htmlContent string) string {
analyticsScript := `<script defer src="https://cloud.umami.is/script.js" data-website-id="c3d8a914-abbc-4eed-9699-a9192c4bef9e" data-exclude-search="true" data-exclude-hash="true" data-do-not-track="true"></script>`

Expand All @@ -16,7 +18,14 @@ func InjectAnalytics(htmlContent string) string {
}

func InjectKiteBase(htmlContent string, base string) string {
baseScript := fmt.Sprintf(`<script>window.__dynamic_base__='%s';</script>`, base)
assetBase := base
if assetBase == "/" {
assetBase = ""
}

htmlContent = strings.ReplaceAll(htmlContent, kiteAssetBasePlaceholder, assetBase)

Comment on lines +22 to +28
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assetBase is inserted into HTML attribute values via a raw string replacement. While baseScript uses %q (safe for JS), the attribute injection path isn’t escaped/validated, so a misconfigured KITE_BASE containing quotes/</whitespace could break the HTML or enable XSS. Consider validating base to a safe URL-path subset and/or HTML-escaping assetBase before replacing it into href/src attributes.

Copilot uses AI. Check for mistakes.
baseScript := fmt.Sprintf(`<script>window.__dynamic_base__=%q;</script>`, assetBase)
re := regexp.MustCompile(`<head>`)
return re.ReplaceAllString(htmlContent, "<head>\n "+baseScript)
}
Expand Down
39 changes: 39 additions & 0 deletions pkg/utils/utils_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,50 @@
package utils

import (
"strings"
"testing"

"k8s.io/apimachinery/pkg/util/validation"
)

func TestInjectKiteBase(t *testing.T) {
html := `<html><head><link rel="modulepreload" href="__KITE_ASSET_BASE__/assets/index.js"><script type="module" src="__KITE_ASSET_BASE__/assets/main.js"></script></head></html>`

t.Run("subpath", func(t *testing.T) {
got := InjectKiteBase(html, "/kite")

if strings.Contains(got, "__KITE_ASSET_BASE__") {
t.Fatalf("placeholder should be replaced: %s", got)
}
if strings.Contains(got, "<base ") {
t.Fatalf("base tag should not be injected anymore: %s", got)
}
if !strings.Contains(got, `href="/kite/assets/index.js"`) {
t.Fatalf("expected asset href to include subpath: %s", got)
}
if !strings.Contains(got, `src="/kite/assets/main.js"`) {
t.Fatalf("expected asset src to include subpath: %s", got)
}
if !strings.Contains(got, `<script>window.__dynamic_base__="/kite";</script>`) {
t.Fatalf("expected runtime base script: %s", got)
}
})

t.Run("root", func(t *testing.T) {
got := InjectKiteBase(html, "")

if !strings.Contains(got, `href="/assets/index.js"`) {
t.Fatalf("expected root asset href: %s", got)
}
if !strings.Contains(got, `src="/assets/main.js"`) {
t.Fatalf("expected root asset src: %s", got)
}
if !strings.Contains(got, `<script>window.__dynamic_base__="";</script>`) {
t.Fatalf("expected empty runtime base script: %s", got)
}
})
}

func TestGetImageRegistryAndRepo(t *testing.T) {
testcase := []struct {
image string
Expand Down
10 changes: 6 additions & 4 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
"private": true,
"version": "0.0.0",
"type": "module",
"engines": {
"node": "^20.19.0 || >=22.12.0"
Comment on lines +6 to +7

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bump the Docker builder image to a supported Node patch

After this upgrade, the UI explicitly requires Node ^20.19.0 || >=22.12.0 (ui/package.json:6-7), and the new lockfile entries for vite / @vitejs/plugin-react carry the same floor (ui/pnpm-lock.yaml:1485-1487, 2617-2619). The source-build path in Dockerfile:1-11 still starts from node:20-alpine, so any machine or CI runner that has a cached 20.18.x image and runs docker build without --pull will now fail during pnpm install or pnpm run build. Please update/pin that builder image alongside the dependency bump so local/source image builds remain reproducible.

Useful? React with 👍 / 👎.

},
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
Expand All @@ -29,7 +32,7 @@
"@radix-ui/react-toggle-group": "^1.1.11",
"@radix-ui/react-tooltip": "^1.2.8",
"@tabler/icons-react": "^3.40.0",
"@tailwindcss/vite": "^4.2.1",
"@tailwindcss/vite": "^4.2.2",
"@tanstack/react-query": "^5.90.21",
"@tanstack/react-table": "^8.21.3",
"@xterm/addon-fit": "^0.11.0",
Expand Down Expand Up @@ -57,7 +60,7 @@
"remark-gfm": "^4.0.1",
"sonner": "^2.0.7",
"tailwind-merge": "^3.5.0",
"tailwindcss": "^4.2.1"
"tailwindcss": "^4.2.2"
},
"devDependencies": {
"@eslint/js": "^9.39.4",
Expand All @@ -78,7 +81,6 @@
"tw-animate-css": "^1.4.0",
"typescript": "~5.9.3",
"typescript-eslint": "^8.57.1",
"vite": "^7.3.1",
"vite-plugin-dynamic-base": "^1.3.0"
"vite": "^8.0.1"
}
}
Loading
Loading