Compare commits

...
23 Commits
Author SHA1 Message Date
cdrci 2cb3ad3e25 Update Code to 1.145.0 (#8109) 2026-11-04 13:00:37 -09:00
Asher 3798a42dc9 Set HttpOnly on cookies (#8110) 2026-11-04 12:59:44 -09:00
Asher cc7388533d Strip cookie from web socket requests (#8111)
This matches what we already do for regular HTTP requests.
2026-11-04 12:59:36 -09:00
Pham Quang Dinh c587540721 Add Vietnamese locale (#8107) 2026-11-03 20:43:25 +00:00
dependabot[bot] e0a7057ff4 Bump js-yaml from 5.4.3 to 5.5.0 (#8100) 2026-11-02 17:31:20 -09:00
dependabot[bot] 7c77a28768 Bump actions/setup-node from 7.0.0 to 7.1.0 (#8103) 2026-11-02 23:34:30 +00:00
dependabot[bot] 74c1e34fe2 Bump @eslint/compat from 1.4.1 to 2.1.1 (#8029) 2026-11-02 14:19:03 -09:00
dependabot[bot] fd571e6c61 Bump i18next from 26.3.1 to 26.5.11 (#8101) 2026-11-02 14:16:22 -09:00
dependabot[bot] d4d1288212 Bump globals from 17.6.0 to 17.13.0 (#8099) 2026-11-02 14:15:04 -09:00
Andy Piper 79d2c29c49 Add --disable-file-cache flag (#8085)
The browser writes some workspace files to the client disk during normal
use. The webview service worker stores resources that have an ETag in
Cache Storage, and responses from /vscode-remote-resource can end up in
the HTTP disk cache. --disable-file-downloads does not cover either.

With --disable-file-cache, the webview resource loader sends no ETag for
a resource outside the webview's own extension, so the service worker
does not store it. /vscode-remote-resource responds with
`Cache-Control: no-store` for files outside the extension directories.
Extension files keep their ETags, so webviews still load extension code
from the cache. The flag is off by default.
2026-11-02 14:14:26 -09:00
dependabot[bot] ee16a40e41 Bump softprops/action-gh-release from 3.0.2 to 3.0.3 (#8105) 2026-11-02 13:33:33 -09:00
dependabot[bot] e73622adaf Bump actions/upload-artifact from 7.0.1 to 7.0.2 (#8104) 2026-11-02 13:33:09 -09:00
dependabot[bot] 734cdc9947 Bump aquasecurity/trivy-action (#8102) 2026-11-02 13:32:22 -09:00
dependabot[bot] 1c435fa2f5 Bump argon2 from 0.44.0 to 0.45.1 (#8095) 2026-11-02 13:28:23 -09:00
Asher 74d06e2e36 Update remaining codeql actions
Also add a group since they have to all be updated together.
2026-11-02 13:20:36 -09:00
dependabot[bot] f65b229eab Bump typescript-eslint from 8.69.0 to 8.72.1 (#8092) 2026-11-02 12:47:41 -09:00
dependabot[bot] 973937ecf2 Bump github/codeql-action/upload-sarif from 4.37.6 to 4.39.1 (#8093) 2026-11-02 12:46:59 -09:00
dependabot[bot] 739bda2970 Bump @types/node from 24.13.3 to 24.19.2 (#8091) 2026-11-02 12:34:55 -09:00
dependabot[bot] c88b56cddc Bump docker/setup-qemu-action from 4.3.0 to 4.4.0 (#8090) 2026-11-02 12:33:59 -09:00
dependabot[bot] cad47a78f1 Bump github/codeql-action/analyze from 4.38.2 to 4.39.1 (#8096) 2026-11-02 12:33:20 -09:00
dependabot[bot] b4725f8be9 Bump docker/login-action from 4.6.0 to 4.7.0 (#8097) 2026-11-02 12:32:39 -09:00
dependabot[bot] 68d5f022a5 Bump actions/download-artifact from 8.0.1 to 8.0.2 (#8098) 2026-11-02 12:32:06 -09:00
cdrci 68810a6bd6 Update Helm chart and changelog with 4.144.0 (#8088) 2026-10-29 13:35:10 -08:00
28 changed files with 579 additions and 154 deletions
+4
View File
@@ -9,6 +9,10 @@ updates:
cooldown:
default-days: 7
labels: []
groups:
codeql-action:
patterns:
- "github/codeql-action/*"
- package-ecosystem: "npm"
directory: "/"
+12 -12
View File
@@ -58,7 +58,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
with:
node-version-file: .node-version
cache: npm
@@ -75,7 +75,7 @@ jobs:
if: needs.changes.outputs.docs == 'true'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
with:
node-version-file: .node-version
cache: npm
@@ -104,7 +104,7 @@ jobs:
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.ci == 'true' || needs.changes.outputs.npm == 'true'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
with:
node-version-file: .node-version
cache: npm
@@ -135,7 +135,7 @@ jobs:
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.npm == 'true'
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
with:
node-version-file: .node-version
cache: npm
@@ -173,7 +173,7 @@ jobs:
with:
submodules: true
- run: quilt push -a
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
with:
node-version-file: .node-version
cache: npm
@@ -217,7 +217,7 @@ jobs:
# Push up an artifact containing the linux-x64 release.
- run: KEEP_MODULES=1 npm run release
- run: tar -czf package.tar.gz release
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
with:
name: linux-x64-package
path: ./package.tar.gz
@@ -232,7 +232,7 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
with:
node-version-file: .node-version
cache: npm
@@ -245,13 +245,13 @@ jobs:
./test/node_modules/.bin/playwright install-deps
./test/node_modules/.bin/playwright install
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
with:
name: linux-x64-package
- run: tar -xzf package.tar.gz
- run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
if: always()
with:
name: failed-test-videos
@@ -282,7 +282,7 @@ jobs:
tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
with:
node-version-file: .node-version
cache: npm
@@ -295,7 +295,7 @@ jobs:
./test/node_modules/.bin/playwright install-deps
./test/node_modules/.bin/playwright install
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
with:
name: linux-x64-package
- run: tar -xzf package.tar.gz
@@ -304,7 +304,7 @@ jobs:
- run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e:proxy
- run: ~/.cache/caddy/caddy stop --config ./ci/Caddyfile
if: always()
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
if: always()
with:
name: failed-test-videos-proxy
+4 -4
View File
@@ -34,7 +34,7 @@ jobs:
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
with:
node-version-file: .node-version
@@ -109,14 +109,14 @@ jobs:
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: docker/setup-qemu-action@1f40c72289eff860ee54a304f1438e3cff362e0a # v4.3.0
- uses: docker/setup-qemu-action@99012661954931238ded8c8b007157a8430204e1 # v4.4.0
- uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
- uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4.7.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
- uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4.7.0
with:
registry: ghcr.io
username: ${{ github.actor }}
+4 -4
View File
@@ -83,7 +83,7 @@ jobs:
# which requires secrets.
allow-unsafe-pr-checkout: true
- run: quilt push -a
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
with:
node-version-file: .node-version
cache: npm
@@ -180,7 +180,7 @@ jobs:
# which requires secrets.
allow-unsafe-pr-checkout: true
- run: quilt push -a
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
with:
node-version-file: .node-version
cache: npm
@@ -253,7 +253,7 @@ jobs:
git apply --whitespace=nowarn "patches/$patch"
done < patches/series
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
with:
node-version-file: .node-version
cache: npm
@@ -347,7 +347,7 @@ jobs:
esac
npm run package
- uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
- uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
with:
draft: true
discussion_category_name: "📣 Announcements"
+6 -6
View File
@@ -30,7 +30,7 @@ jobs:
fetch-depth: 0
- name: Install Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v6
with:
node-version-file: .node-version
@@ -51,7 +51,7 @@ jobs:
fetch-depth: 0
- name: Run Trivy vulnerability scanner in repo mode
uses: aquasecurity/trivy-action@d2a0b60797ff03db6132bd4e2b293f9b37081297 # latest
uses: aquasecurity/trivy-action@8f28faec26515256b6d22074d1d2a8986f4cbd87 # latest
with:
scan-type: "fs"
scan-ref: "."
@@ -62,7 +62,7 @@ jobs:
severity: "HIGH,CRITICAL"
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
uses: github/codeql-action/upload-sarif@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
with:
sarif_file: "trivy-repo-results.sarif"
@@ -80,13 +80,13 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
with:
config-file: ./.github/codeql-config.yml
languages: javascript
- name: Autobuild
uses: github/codeql-action/autobuild@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
uses: github/codeql-action/autobuild@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
uses: github/codeql-action/analyze@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
+2 -2
View File
@@ -49,7 +49,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- name: Run Trivy vulnerability scanner in image mode
uses: aquasecurity/trivy-action@d2a0b60797ff03db6132bd4e2b293f9b37081297 # latest
uses: aquasecurity/trivy-action@8f28faec26515256b6d22074d1d2a8986f4cbd87 # latest
with:
image-ref: "docker.io/codercom/code-server:latest"
ignore-unfixed: true
@@ -58,6 +58,6 @@ jobs:
severity: "HIGH,CRITICAL"
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
uses: github/codeql-action/upload-sarif@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4
with:
sarif_file: "trivy-image-results.sarif"
+24
View File
@@ -22,6 +22,30 @@ Code v99.99.999
## Unreleased
Code v1.145.0
### Security
- Strip code-server's cookie from web socket requests going over the built-in
proxy. We were already doing this for regular proxied HTTP requests, but not
for proxied web sockets.
- Add HttpOnly to cookies to prevent them from being accessed by JavaScript
proxied over the built-in proxy.
### Changed
- Update to Code 1.145.0
### Added
- Vietnamese locale.
- New flag `--disable-file-cache` that keeps workspace files out of the browser
cache. It stops the webview service worker from storing them in Cache Storage
and serves them from `/vscode-remote-resource` with `Cache-Control: no-store`.
Extension files will still be cached.
## [4.144.0](https://github.com/coder/code-server/releases/tag/v4.144.0) - 2026-10-29
Code v1.144.0
### Changed
+2 -2
View File
@@ -15,9 +15,9 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 3.57.0
version: 3.58.0
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
appVersion: 4.143.1
appVersion: 4.144.0
+1 -1
View File
@@ -6,7 +6,7 @@ replicaCount: 1
image:
repository: codercom/code-server
tag: '4.143.1'
tag: '4.144.0'
pullPolicy: Always
# Specifies one or more secrets to be used when pulling images from a
+128 -98
View File
@@ -11,7 +11,7 @@
"license": "MIT",
"dependencies": {
"@coder/logger": "^3.0.1",
"argon2": "^0.44.0",
"argon2": "^0.45.1",
"compression": "^1.7.4",
"cookie": "^1.1.1",
"cookie-parser": "^1.4.6",
@@ -35,7 +35,7 @@
"code-server": "out/node/entry.js"
},
"devDependencies": {
"@eslint/compat": "^1.2.0",
"@eslint/compat": "^2.1.1",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.12.0",
"@types/compression": "^1.7.3",
@@ -170,19 +170,19 @@
}
},
"node_modules/@eslint/compat": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.4.1.tgz",
"integrity": "sha512-cfO82V9zxxGBxcQDr1lfaYB7wykTa0b00mGa36FrJl7iTFd0Z2cHfEYuxcBRP/iNijCsWsEkA+jzT8hGYmv33w==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-2.1.1.tgz",
"integrity": "sha512-rMcy8GSrwNzcISX/BlTDY/GLB4eCopEuy9woIls3To+15OLxykZrxxq+WUcylCPCQ6F4MujjBM1DX5V1aqI3Vw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@eslint/core": "^0.17.0"
"@eslint/core": "^1.2.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
"node": "^20.19.0 || ^22.13.0 || >=24"
},
"peerDependencies": {
"eslint": "^8.40 || 9"
"eslint": "^8.40 || 9 || 10"
},
"peerDependenciesMeta": {
"eslint": {
@@ -190,6 +190,19 @@
}
}
},
"node_modules/@eslint/compat/node_modules/@eslint/core": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz",
"integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@types/json-schema": "^7.0.15"
},
"engines": {
"node": "^20.19.0 || ^22.13.0 || >=24"
}
},
"node_modules/@eslint/config-array": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
@@ -754,13 +767,13 @@
}
},
"node_modules/@types/node": {
"version": "24.13.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz",
"integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==",
"version": "24.19.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.19.2.tgz",
"integrity": "sha512-93d49wCWJkCyN87MxLpNN6KXPCwFw7bVUg79mGUV1OS40JGWwVCr8n61DXCSqz7CV6/VfPkb7xec7uP2M+QHWQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.18.0"
"undici-types": ">=7.24.0 <7.24.7"
}
},
"node_modules/@types/pem": {
@@ -857,17 +870,17 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.69.0.tgz",
"integrity": "sha512-t5jQTKPIgVW1PE6dR6H6Qz5gm8zjMlX5/2gRaOGd9eO6V7J+tQc6iWKukEe7dY8u9HyYasQ0yfF0/FSSTEO2gA==",
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.72.1.tgz",
"integrity": "sha512-5CokTWXpmbylfFabsbvHC0CAw3XLaGnoa+nFJX5FR592h/LoZsENUE6p/rg5xvkKrFEXz6pYmgI29AgXc2N3BQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.12.2",
"@typescript-eslint/scope-manager": "8.69.0",
"@typescript-eslint/type-utils": "8.69.0",
"@typescript-eslint/utils": "8.69.0",
"@typescript-eslint/visitor-keys": "8.69.0",
"@typescript-eslint/scope-manager": "8.72.1",
"@typescript-eslint/type-utils": "8.72.1",
"@typescript-eslint/utils": "8.72.1",
"@typescript-eslint/visitor-keys": "8.72.1",
"ignore": "^7.0.5",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.5.0"
@@ -880,15 +893,15 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.69.0",
"@typescript-eslint/parser": "^8.72.1",
"eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
"typescript": ">=4.8.4 <6.1.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
"version": "7.0.8",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.8.tgz",
"integrity": "sha512-YYNsSlXBjMk92SKnkwvB5LOVSa6OznlFUGcsvrFgNJbJCd0M1XKeFVRc8ZByeCqz32FivYNHJVooLmdqrmvp/Q==",
"version": "7.0.14",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.14.tgz",
"integrity": "sha512-wCBiZ77u1tuWde6G/nfOtLaCTYcFDU5yCzARzK10y+rLhzYoL7a7yEemcopcc2Mzow7gZOIjnV2ym1NYmdiJOQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -896,16 +909,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.69.0.tgz",
"integrity": "sha512-l4b0DhWioGg6Gt2ebGlvfkFMOjRsauxtsnDRwUSRX1qHq3HdTfQHV8wW9zEXeciai6HfeaKOedQn2Zoofx3WBw==",
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.72.1.tgz",
"integrity": "sha512-ZGwZP4OCfyA0AQTpEAMWz+rtX01DRhQWW5hB0ucKDEIX5U7jdmPSaMx94rQfaPAQzIYz2BimOgKOJtjfpRFQ9g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/scope-manager": "8.69.0",
"@typescript-eslint/types": "8.69.0",
"@typescript-eslint/typescript-estree": "8.69.0",
"@typescript-eslint/visitor-keys": "8.69.0",
"@typescript-eslint/scope-manager": "8.72.1",
"@typescript-eslint/types": "8.72.1",
"@typescript-eslint/typescript-estree": "8.72.1",
"@typescript-eslint/visitor-keys": "8.72.1",
"debug": "^4.4.3"
},
"engines": {
@@ -921,14 +934,14 @@
}
},
"node_modules/@typescript-eslint/project-service": {
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.69.0.tgz",
"integrity": "sha512-yi4obFrHMmnsesWehHbkg9zMA7Jt8cXT+mKM08G999pH1yT6nqgsHx7MYm0uY1wAj8CqiBXYRJ7WAT0QdQHQXg==",
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.72.1.tgz",
"integrity": "sha512-fAuVMkwdO/huI8nyo/WKnNKf6Gag93S56Rh3Ts5mGcavwSdaN8tRg1gCeIGX8PF+nzp1BjGfO4gHhGzW1J6jTg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.69.0",
"@typescript-eslint/types": "^8.69.0",
"@typescript-eslint/tsconfig-utils": "^8.72.1",
"@typescript-eslint/types": "^8.72.1",
"debug": "^4.4.3"
},
"engines": {
@@ -943,14 +956,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.69.0.tgz",
"integrity": "sha512-ewfspqWvSxKSOaplqAUNbaSFO0eB6w1EtQ+esfYFRm3614Ty4uNtExkcbgd6nWsXphbqKyf9ZYdbZdv2xEoWEQ==",
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.72.1.tgz",
"integrity": "sha512-lC/t6eMCZZQAAKZEYGL6RDVSuFehpdmMT6h+nJIjIa6oylN/PwDgDVtEIbB7O9xFfZYtZAYLoLlDNWKJhtF+uQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.69.0",
"@typescript-eslint/visitor-keys": "8.69.0"
"@typescript-eslint/types": "8.72.1",
"@typescript-eslint/visitor-keys": "8.72.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -961,9 +974,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.69.0.tgz",
"integrity": "sha512-xNqK7YTDZsLniQMV/4rpFR8Z5JlqeRvVjuG1YgF/mdPVH84HSD19L8CczMA0qg2RfwEV231GHH3VnToJDo4MfQ==",
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.72.1.tgz",
"integrity": "sha512-e4D5R5vpeAEPBxT2BAzsFQL3sbwyeeeo5+aczgNSRK1V734jE7pTqaGFU+fXapWEQwnZbpFaTn32+Z8DwS6OTg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -978,15 +991,15 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.69.0.tgz",
"integrity": "sha512-ZfoJAVg3JZndQEpEl9petVlxau3lRuElc4HRMuAlLCf8to04/iHz692RUSNmXKDjEuJmIL+KZ2/BsOcBc16dsA==",
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.72.1.tgz",
"integrity": "sha512-iY2wlmyrXJmx4yxUGP3aYCFF3cA/6ShddOKmLU2dx7LnEykbAM8WThlxZEfd1NddqceF6eJmZUayxx9oKIYNlg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.69.0",
"@typescript-eslint/typescript-estree": "8.69.0",
"@typescript-eslint/utils": "8.69.0",
"@typescript-eslint/types": "8.72.1",
"@typescript-eslint/typescript-estree": "8.72.1",
"@typescript-eslint/utils": "8.72.1",
"debug": "^4.4.3",
"ts-api-utils": "^2.5.0"
},
@@ -1003,9 +1016,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.69.0.tgz",
"integrity": "sha512-K3VrubUPhlo9VDBS6QdI8YB5j7ClpqLRdefcz6PFrhnwicehBweqQ9Evhl4l+FYz0HdDmMqIiSX0aldGRYtDCA==",
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.72.1.tgz",
"integrity": "sha512-LmE5IhQet1BWOWEXqBrVtBPsMAOQ6Nzk35d+WLh3mk4EUF33sqlfxjio1MdYeSvKSG5skactKKuixBIKXhL4Rw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1017,16 +1030,16 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.69.0.tgz",
"integrity": "sha512-AdFkgqck3Vudb/kWnxlyafU/4aBhHrbQ9locP2N4psXTy5mOBg0SHJumnLvx7r6g1gV4DKvUFwV2nJZBoqOD8w==",
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.72.1.tgz",
"integrity": "sha512-DAlUoUV93hIvrtIQLwCbmZQYVZwOMhiHJrOVUUIWicFZaIYjTRqlY3I/NZevfkLmSqkNHRu2qYDcq9lrn16oOQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.69.0",
"@typescript-eslint/tsconfig-utils": "8.69.0",
"@typescript-eslint/types": "8.69.0",
"@typescript-eslint/visitor-keys": "8.69.0",
"@typescript-eslint/project-service": "8.72.1",
"@typescript-eslint/tsconfig-utils": "8.72.1",
"@typescript-eslint/types": "8.72.1",
"@typescript-eslint/visitor-keys": "8.72.1",
"debug": "^4.4.3",
"minimatch": "^10.2.2",
"semver": "^7.7.3",
@@ -1084,16 +1097,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.69.0.tgz",
"integrity": "sha512-tUbx60BBqQa31kXF5MCsOOLL5E/WzUuxIn7YpAvq+eaUlqvk8/NXnXMBNAdLCr0icjkzem7iUA5QqWHe/hJ1aw==",
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.72.1.tgz",
"integrity": "sha512-5v5liypurJBFHCBNqh/RjsymAD+VWcE0djuGY/BUqp5fC3Qn+luWDEksjuTtWjPn6i5zQlUtkZCRG/CYG0yCkA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
"@typescript-eslint/scope-manager": "8.69.0",
"@typescript-eslint/types": "8.69.0",
"@typescript-eslint/typescript-estree": "8.69.0"
"@typescript-eslint/scope-manager": "8.72.1",
"@typescript-eslint/types": "8.72.1",
"@typescript-eslint/typescript-estree": "8.72.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1108,13 +1121,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.69.0.tgz",
"integrity": "sha512-+rmdgPA+EXkNgKYvHvFfhrs35utXbwaC5PGpDquSXcoXQDKUA5UjV0LmTucG/4JXkM31BTu4TilHtrN8IVBe8w==",
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.72.1.tgz",
"integrity": "sha512-SB8xqipSzZHUePCCLNeYxqnxq83X61/qzNhjQGbTfjxGZIeOEP7tBgWYX05Tcd6CgE02WdTJnh5b8kMZJ/+bnQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.69.0",
"@typescript-eslint/types": "8.72.1",
"eslint-visitor-keys": "^5.0.0"
},
"engines": {
@@ -1526,15 +1539,15 @@
"license": "MIT"
},
"node_modules/argon2": {
"version": "0.44.0",
"resolved": "https://registry.npmjs.org/argon2/-/argon2-0.44.0.tgz",
"integrity": "sha512-zHPGN3S55sihSQo0dBbK0A5qpi2R31z7HZDZnry3ifOyj8bZZnpZND2gpmhnRGO1V/d555RwBqIK5W4Mrmv3ig==",
"version": "0.45.1",
"resolved": "https://registry.npmjs.org/argon2/-/argon2-0.45.1.tgz",
"integrity": "sha512-skm+/WCjkGqCQxF7FG1LuZXM5yvbFjgbfiCGsud2oLgaDhh6b6dbH0b1EkghbM+xx4Bj8Ape+KKgixoIlWZicQ==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@phc/format": "^1.0.0",
"cross-env": "^10.0.0",
"node-addon-api": "^8.5.0",
"cross-env": "^10.1.0",
"node-addon-api": "^8.9.0",
"node-gyp-build": "^4.8.4"
},
"engines": {
@@ -1545,6 +1558,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true,
"license": "Python-2.0"
},
"node_modules/array-buffer-byte-length": {
@@ -3453,9 +3467,9 @@
}
},
"node_modules/globals": {
"version": "17.6.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz",
"integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==",
"version": "17.13.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-17.13.0.tgz",
"integrity": "sha512-RwMTC61u7hrG3ZJMkZQOK4JLJrKS8QtoTii63EmWvFXHqycY9FObBJQCbsLxSO8kjKhWE5kV1GC+Vb1g3RI0Zg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3675,9 +3689,9 @@
}
},
"node_modules/i18next": {
"version": "26.3.1",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.3.1.tgz",
"integrity": "sha512-txQqd5EULsqEh9OJqRH15aCaOuy/nLJyhw5EHCSKLKJE1aBbb3Zve2+uQIxgWhPm1QqUQoWyQBm2kfmmIrzkcQ==",
"version": "26.5.11",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.5.11.tgz",
"integrity": "sha512-Wc0klBPKxqZ2tL2qdAnF8xvvnWgr1IMGSY2ikTiAvaFVbz7xiFARtkoU4RidBDw1SyziGROp0qxu6qnJ7l2Wug==",
"funding": [
{
"type": "individual",
@@ -3694,7 +3708,7 @@
],
"license": "MIT",
"peerDependencies": {
"typescript": "^5 || ^6"
"typescript": "^5 || ^6 || ^7"
},
"peerDependenciesMeta": {
"typescript": {
@@ -4270,9 +4284,9 @@
"license": "ISC"
},
"node_modules/js-yaml": {
"version": "5.4.3",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.4.3.tgz",
"integrity": "sha512-yzzNtgczwgoVHNigCyKTXcQJU4Y8t/ikU4UxXW0BvrLfHTGWZhsNcOT2s/a7vn81/4KqVnNmHjaUEPlvWnNwVw==",
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.5.0.tgz",
"integrity": "sha512-paNr4LFIFPjeeSmwNYdrb8FafLLG/Cr2Af3GjbsHJ5CxIjH4r0c2emlmRdAtpPAieP1gRVzk6buBbVP5gBMGAg==",
"funding": [
{
"type": "github",
@@ -4285,12 +4299,28 @@
],
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
"argparse": "^3.0.3"
},
"bin": {
"js-yaml": "bin/js-yaml.mjs"
}
},
"node_modules/js-yaml/node_modules/argparse": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-3.0.4.tgz",
"integrity": "sha512-fwWK3Zq22l4XJJjx5mcBHGikIk+hJqO+32dPm0Jur7+rtG5x1scOjSfdT9ZKeWHPpsya/l0HHK4tDImBkTrtvA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/nodeca"
}
],
"license": "PSF-2.0"
},
"node_modules/json-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
@@ -4885,9 +4915,9 @@
}
},
"node_modules/node-addon-api": {
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.6.0.tgz",
"integrity": "sha512-gBVjCaqDlRUk0EwoPNKzIr9KkS9041G/q31IBShPs1Xz6UTA+EXdZADbzqAJQrpDRq71CIMnOP5VMut3SL0z5Q==",
"version": "8.9.2",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.9.2.tgz",
"integrity": "sha512-VijLXbi3UACN69I0JVXJsX4tjACjNoQDgv2gTF6sx2wWEi8tkSg2eX8p5gSIFi8z2+DL3oHmY6OyKce38SDolg==",
"license": "MIT",
"engines": {
"node": "^18 || ^20 || >= 21"
@@ -6373,16 +6403,16 @@
}
},
"node_modules/typescript-eslint": {
"version": "8.69.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.69.0.tgz",
"integrity": "sha512-B3MltX0VqjUBNEe3b3sSuiRbfa6XrfHFtBiPamjT5AsW/dfq+y+bc0wyuS9DxAS1LyzCxRp2+rxzpLUvqM2BvA==",
"version": "8.72.1",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.72.1.tgz",
"integrity": "sha512-3Li9FfPmQp45nxEtFD1ZCrYFI3cYK5kpyNtmm1H7lMagm8u9sy6PTjy3ytwQZs7KNukOyKFHAZ6z6GjYFeaeXw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.69.0",
"@typescript-eslint/parser": "8.69.0",
"@typescript-eslint/typescript-estree": "8.69.0",
"@typescript-eslint/utils": "8.69.0"
"@typescript-eslint/eslint-plugin": "8.72.1",
"@typescript-eslint/parser": "8.72.1",
"@typescript-eslint/typescript-estree": "8.72.1",
"@typescript-eslint/utils": "8.72.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -6416,9 +6446,9 @@
}
},
"node_modules/undici-types": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
"version": "7.24.6",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
"integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
"dev": true,
"license": "MIT"
},
+2 -2
View File
@@ -36,7 +36,7 @@
},
"main": "out/node/entry.js",
"devDependencies": {
"@eslint/compat": "^1.2.0",
"@eslint/compat": "^2.1.1",
"@eslint/eslintrc": "^3.1.0",
"@eslint/js": "^9.12.0",
"@types/compression": "^1.7.3",
@@ -67,7 +67,7 @@
},
"dependencies": {
"@coder/logger": "^3.0.1",
"argon2": "^0.44.0",
"argon2": "^0.45.1",
"compression": "^1.7.4",
"cookie": "^1.1.1",
"cookie-parser": "^1.4.6",
+1 -1
View File
@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/src/vs/base/common/network.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/base/common/network.ts
+++ code-server/lib/vscode/src/vs/base/common/network.ts
@@ -262,7 +262,9 @@ class RemoteAuthoritiesImpl {
@@ -263,7 +263,9 @@ class RemoteAuthoritiesImpl {
return URI.from({
scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,
authority: `${host}:${port}`,
+2 -2
View File
@@ -6,8 +6,8 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy"
- content="default-src 'none'; script-src 'sha256-Q3Tfcw0dGu/YD4dGBrRqBeOnmRMAH8HbKxArK4YSXBc=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
+ content="default-src 'none'; script-src 'sha256-BmcTt6YZr75RujSQ3gF/UQL77e1RrOx62jNeikpwtxc=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
- content="default-src 'none'; script-src 'sha256-29YeDbmHnhN2BgMJKVq7vDCMiuya6rpEctI6SkJFfJc=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
+ content="default-src 'none'; script-src 'sha256-PrK0S1PGjGJseEIewxhvBTIw2x6Ci21IJIkOZ3gFWMg=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
<!-- Disable pinch zooming -->
<meta name="viewport"
+188
View File
@@ -0,0 +1,188 @@
Add option to keep workspace files out of the browser cache
This patch adds support for a new CLI flag called `--disable-file-cache`. When
set, workspace files are not stored on the client disk through two caches:
- The webview resource loader sends no ETag for a resource outside the
webview's own extension, and the webview service worker only stores responses
that have an ETag, so these resources stay out of Cache Storage.
- `/vscode-remote-resource` responds with `Cache-Control: no-store` for files
outside the extension directories.
Extension resources keep their ETags so webviews still load extension code from
the cache. The default value for this is `false`.
To test, start code-server with `--disable-file-cache`, open a Markdown file
that embeds an image from the workspace, and open the preview. In the browser
dev tools, the `vscode-resource-cache-*` Cache Storage of the webview service
worker should have no entry for the image, and a request to
`/vscode-remote-resource?path=<image>` should respond with
`Cache-Control: no-store`.
Index: code-server/lib/vscode/src/vs/server/node/remoteExtensionHostAgentServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/remoteExtensionHostAgentServer.ts
+++ code-server/lib/vscode/src/vs/server/node/remoteExtensionHostAgentServer.ts
@@ -177,15 +177,14 @@ class RemoteExtensionHostAgentServer ext
const requestOrigin = req.headers['origin'];
const responseHeaders = getRemoteResourceResponseHeaders(requestOrigin, origin => this._webEndpointOriginChecker.matches(origin));
- if (this._environmentService.isBuilt) {
- if (isEqualOrParent(filePath, this._environmentService.builtinExtensionsPath, !platform.isLinux)
- || isEqualOrParent(filePath, this._environmentService.extensionsPath, !platform.isLinux)
- ) {
- responseHeaders['Cache-Control'] = 'public, max-age=31536000';
- }
+ const isExtensionFile = isEqualOrParent(filePath, this._environmentService.builtinExtensionsPath, !platform.isLinux)
+ || isEqualOrParent(filePath, this._environmentService.extensionsPath, !platform.isLinux);
+ if (this._environmentService.isBuilt && isExtensionFile) {
+ responseHeaders['Cache-Control'] = 'public, max-age=31536000';
}
- return serveFile(filePath, CacheControl.ETAG, this._logService, req, res, responseHeaders);
+ const cacheControl = this._environmentService.args['disable-file-cache'] && !isExtensionFile ? CacheControl.NO_CACHING : CacheControl.ETAG;
+ return serveFile(filePath, cacheControl, this._logService, req, res, responseHeaders);
}
// workbench web UI
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
@@ -37,6 +37,7 @@ export const serverOptions: OptionDescri
'auth': { type: 'string' },
'disable-file-downloads': { type: 'boolean' },
'disable-file-uploads': { type: 'boolean' },
+ 'disable-file-cache': { type: 'boolean' },
'disable-getting-started-override': { type: 'boolean' },
'locale': { type: 'string' },
'link-protection-trusted-domains': { type: 'string[]' },
@@ -139,6 +140,7 @@ export interface ServerParsedArgs {
'auth'?: string;
'disable-file-downloads'?: boolean;
'disable-file-uploads'?: boolean;
+ 'disable-file-cache'?: boolean;
'disable-getting-started-override'?: boolean,
'locale'?: string
'link-protection-trusted-domains'?: string[],
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -442,6 +442,7 @@ export class WebClientServer {
userDataPath: this._environmentService.userDataPath,
isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'],
+ isEnabledFileCache: !this._environmentService.args['disable-file-cache'],
isEnabledCoderGettingStarted: !this._environmentService.args['disable-getting-started-override'],
_wrapWebWorkerExtHostInIframe,
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -330,6 +330,11 @@ export interface IWorkbenchConstructionO
readonly isEnabledFileUploads?: boolean
/**
+ * Whether the browser may cache workspace files.
+ */
+ readonly isEnabledFileCache?: boolean
+
+ /**
* Whether to use Coder's custom Getting Started text.
*/
readonly isEnabledCoderGettingStarted?: boolean
Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/webviewElement.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/webviewElement.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/webviewElement.ts
@@ -15,7 +15,7 @@ import { Lazy } from '../../../../base/c
import { Disposable, DisposableStore, IDisposable, MutableDisposable, toDisposable } from '../../../../base/common/lifecycle.js';
import { COI, Schemas } from '../../../../base/common/network.js';
import { observableValue } from '../../../../base/common/observable.js';
-import { isEqualAuthority } from '../../../../base/common/resources.js';
+import { isEqualAuthority, isEqualOrParent } from '../../../../base/common/resources.js';
import { listenStream } from '../../../../base/common/stream.js';
import { URI } from '../../../../base/common/uri.js';
import { generateUuid } from '../../../../base/common/uuid.js';
@@ -32,6 +32,7 @@ import { INotificationService } from '..
import { IRemoteAuthorityResolverService } from '../../../../platform/remote/common/remoteAuthorityResolver.js';
import { ITunnelService } from '../../../../platform/tunnel/common/tunnel.js';
import { WebviewPortMappingManager } from '../../../../platform/webview/common/webviewPortMapping.js';
+import { IBrowserWorkbenchEnvironmentService } from '../../../services/environment/browser/environmentService.js';
import { IWorkbenchEnvironmentService } from '../../../services/environment/common/environmentService.js';
import { IRemoteAgentService } from '../../../services/remote/common/remoteAgentService.js';
import { decodeAuthority, webviewGenericCspSource, webviewMouseActivityEvent, webviewRootResourceAuthority } from '../common/webview.js';
@@ -868,6 +869,8 @@ export class WebviewElement extends Disp
const rangeHeader = range
? `bytes ${range.start}-${rangeEnd}/${result.size}`
: undefined;
+ // The service worker only stores responses that have an etag.
+ const etag = this._isFileCacheAllowed(uri) ? result.etag : undefined;
if (WebviewElement._supportsTransferableStreams.value) {
let controller: ReadableStreamDefaultController<Uint8Array<ArrayBuffer>> | undefined;
let closed = false;
@@ -919,7 +922,7 @@ export class WebviewElement extends Disp
status: range ? 206 : 200,
path: uri.path,
mime: result.mimeType,
- etag: result.etag,
+ etag,
mtime: result.mtime,
range: rangeHeader,
stream,
@@ -931,7 +934,7 @@ export class WebviewElement extends Disp
status: range ? 206 : 200,
path: uri.path,
mime: result.mimeType,
- etag: result.etag,
+ etag,
mtime: result.mtime,
range: rangeHeader,
});
@@ -988,6 +991,14 @@ export class WebviewElement extends Disp
});
}
+ private _isFileCacheAllowed(uri: URI): boolean {
+ if ((this._environmentService as IBrowserWorkbenchEnvironmentService).isEnabledFileCache) {
+ return true;
+ }
+ const extensionLocation = this.extension?.location;
+ return !!extensionLocation && isEqualOrParent(uri, extensionLocation);
+ }
+
private async localLocalhost(id: string, origin: string) {
const authority = this._environmentService.remoteAuthority;
const resolveAuthority = authority ? await this._remoteAuthorityResolverService.resolveAuthority(authority) : undefined;
Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
@@ -49,6 +49,11 @@ export interface IBrowserWorkbenchEnviro
readonly isEnabledFileUploads?: boolean;
/**
+ * Allow the browser to cache workspace files.
+ */
+ readonly isEnabledFileCache?: boolean;
+
+ /**
* Enable Coder's custom getting started text.
*/
readonly isEnabledCoderGettingStarted?: boolean;
@@ -145,6 +150,13 @@ export class BrowserWorkbenchEnvironment
return this.options.isEnabledFileUploads;
}
+ get isEnabledFileCache(): boolean {
+ if (typeof this.options.isEnabledFileCache === "undefined") {
+ throw new Error('isEnabledFileCache was not provided to the browser');
+ }
+ return this.options.isEnabledFileCache;
+ }
+
get isEnabledCoderGettingStarted(): boolean {
if (typeof this.options.isEnabledCoderGettingStarted === "undefined") {
throw new Error('isEnabledCoderGettingStarted was not provided to the browser');
+4 -4
View File
@@ -239,8 +239,8 @@ Index: code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFi
@IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService,
@IPathService protected readonly pathService: IPathService,
@IKeybindingService private readonly keybindingService: IKeybindingService,
@@ -362,21 +362,23 @@ export class SimpleFileDialog extends Di
this.filePickBox.placeholder = nls.localize('remoteFileDialog.placeholder', "Folder path");
@@ -365,21 +365,23 @@ export class SimpleFileDialog extends Di
: nls.localize('remoteFileDialog.placeholder', "Folder path");
this.filePickBox.ok = true;
this.filePickBox.okLabel = typeof this.options.openLabel === 'string' ? this.options.openLabel : this.options.openLabel?.withoutMnemonic;
- if ((this.scheme !== Schemas.file) && this.options && this.options.availableFileSystems && (this.options.availableFileSystems.length > 1) && (this.options.availableFileSystems.indexOf(Schemas.file) > -1)) {
@@ -290,7 +290,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/views/explo
import { WorkbenchCompressibleAsyncDataTree } from '../../../../../platform/list/browser/listService.js';
import { ISearchService, QueryType, getExcludes, ISearchConfiguration, ISearchComplete, IFileQuery } from '../../../../services/search/common/search.js';
import { CancellationToken } from '../../../../../base/common/cancellation.js';
@@ -1515,7 +1516,8 @@ export class FileDragAndDrop implements
@@ -1543,7 +1544,8 @@ export class FileDragAndDrop implements
@IConfigurationService private configurationService: IConfigurationService,
@IInstantiationService private instantiationService: IInstantiationService,
@IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService,
@@ -300,7 +300,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/views/explo
) {
const updateDropEnablement = (e: IConfigurationChangeEvent | undefined) => {
if (!e || e.affectsConfiguration('explorer.enableDragAndDrop')) {
@@ -1740,15 +1742,17 @@ export class FileDragAndDrop implements
@@ -1768,15 +1770,17 @@ export class FileDragAndDrop implements
// External file DND (Import/Upload file)
if (data instanceof NativeDragAndDropData) {
+2 -2
View File
@@ -169,7 +169,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
@@ -65,6 +65,7 @@ import { IOpenerService } from '../../pl
@@ -67,6 +67,7 @@ import { IOpenerService } from '../../pl
import { mixin, safeStringify } from '../../base/common/objects.js';
import { IndexedDB } from '../../base/browser/indexedDB.js';
import { WebFileSystemAccess } from '../../platform/files/browser/webFileSystemAccess.js';
@@ -177,7 +177,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
import { IProgressService } from '../../platform/progress/common/progress.js';
import { DelayedLogChannel } from '../services/output/common/delayedLogChannel.js';
import { dirname, joinPath } from '../../base/common/resources.js';
@@ -141,6 +142,9 @@ export class BrowserMain extends Disposa
@@ -143,6 +144,9 @@ export class BrowserMain extends Disposa
// Startup
const instantiationService = workbench.startup();
+3 -3
View File
@@ -196,7 +196,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
serviceCollection.set(IStorageService, service);
return service;
})
@@ -610,7 +611,21 @@ export class BrowserMain extends Disposa
@@ -613,7 +614,21 @@ export class BrowserMain extends Disposa
}));
}
@@ -223,7 +223,7 @@ Index: code-server/lib/vscode/src/vs/sessions/browser/web.main.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/sessions/browser/web.main.ts
+++ code-server/lib/vscode/src/vs/sessions/browser/web.main.ts
@@ -39,9 +39,9 @@ export class SessionsBrowserMain extends
@@ -41,9 +41,9 @@ export class SessionsBrowserMain extends
_workspace: IAnyWorkspaceIdentifier,
environmentService: IBrowserWorkbenchEnvironmentService,
userDataProfileService: IUserDataProfileService,
@@ -235,7 +235,7 @@ Index: code-server/lib/vscode/src/vs/sessions/browser/web.main.ts
uriIdentityService: IUriIdentityService,
policyService: IPolicyService,
logService: ILogService,
@@ -82,7 +82,7 @@ export class SessionsBrowserMain extends
@@ -84,7 +84,7 @@ export class SessionsBrowserMain extends
serviceCollection.set(IWorkbenchConfigurationService, configurationService);
// Storage
+1
View File
@@ -26,4 +26,5 @@ copilot.diff
app-name.diff
remote-storage.diff
remote-secret-storage.diff
disable-file-cache.diff
csp-hashes.diff
+2 -2
View File
@@ -53,7 +53,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
@@ -266,7 +266,7 @@
@@ -272,7 +272,7 @@
}
const swPath = encodeURI(`service-worker.js?v=${expectedWorkerVersion}&vscode-resource-base-authority=${searchParams.get('vscode-resource-base-authority')}&remoteAuthority=${searchParams.get('remoteAuthority') ?? ''}&platform=${searchParams.get('platform')}`);
@@ -62,7 +62,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
.then(async registration => {
if (navigator.serviceWorker.controller) {
// A previous SW is already controlling. Force an update
@@ -345,6 +345,12 @@
@@ -351,6 +351,12 @@
const hostname = location.hostname;
+5
View File
@@ -51,6 +51,7 @@ export interface UserProvidedCodeArgs {
"disable-update-check"?: boolean
"disable-file-downloads"?: boolean
"disable-file-uploads"?: boolean
"disable-file-cache"?: boolean
"disable-workspace-trust"?: boolean
"disable-getting-started-override"?: boolean
"disable-proxy"?: boolean
@@ -193,6 +194,10 @@ export const options: Options<Required<UserProvidedArgs>> = {
type: "boolean",
description: "Disable file uploads.",
},
"disable-file-cache": {
type: "boolean",
description: "Keep workspace files out of the browser cache.",
},
"disable-workspace-trust": {
type: "boolean",
description: "Disable Workspace Trust feature. This switch only affects the current session.",
+1
View File
@@ -330,6 +330,7 @@ export const getCookieOptions = (req: express.Request): express.CookieOptions =>
domain: getCookieDomain(url.host, req.args["proxy-domain"]),
path: normalize(url.pathname) || "/",
sameSite: "lax",
httpOnly: true,
}
}
+4
View File
@@ -5,6 +5,7 @@ import * as ja from "./locales/ja.json"
import * as th from "./locales/th.json"
import * as tr from "./locales/tr.json"
import * as ur from "./locales/ur.json"
import * as vi from "./locales/vi.json"
import * as zhCn from "./locales/zh-cn.json"
const defaultResources = {
@@ -26,6 +27,9 @@ const defaultResources = {
ur: {
translation: ur,
},
vi: {
translation: vi,
},
}
export async function loadCustomStrings(filePath: string): Promise<void> {
+13
View File
@@ -0,0 +1,13 @@
{
"LOGIN_TITLE": "Đăng nhập {{app}}",
"LOGIN_BELOW": "Vui lòng đăng nhập bên dưới.",
"WELCOME": "Chào mừng bạn đến với {{app}}",
"LOGIN_PASSWORD": "Xem mật khẩu trong tệp cấu hình.",
"LOGIN_USING_ENV_PASSWORD": "Mật khẩu đã được đặt từ $PASSWORD.",
"LOGIN_USING_HASHED_PASSWORD": "Mật khẩu đã được đặt từ $HASHED_PASSWORD.",
"SUBMIT": "GỬI",
"PASSWORD_PLACEHOLDER": "MẬT KHẨU",
"LOGIN_RATE_LIMIT": "Đã vượt quá giới hạn số lần đăng nhập!",
"MISS_PASSWORD": "Thiếu mật khẩu",
"INCORRECT_PASSWORD": "Mật khẩu không đúng"
}
+6 -2
View File
@@ -1,5 +1,6 @@
import * as cookie from "cookie"
import type { Request } from "express"
import http from "http"
import proxyServer from "http-proxy"
import { getCookieSessionName, HttpCode } from "../common/http"
@@ -26,7 +27,7 @@ function identity<T>(val: T): T {
// Strip the code-server cookie if it exists to avoid transmitting the cookie
// to potentially malicious local ports.
proxy.on("proxyReq", (preq, req) => {
function stripCookie(preq: http.ClientRequest, req: http.IncomingMessage) {
if (req.headers.cookie) {
const cookieSessionName = getCookieSessionName((req as Request).args["cookie-suffix"])
// Encoding and decoding are no-ops; we just want to remove the token
@@ -45,7 +46,10 @@ proxy.on("proxyReq", (preq, req) => {
),
)
}
})
}
proxy.on("proxyReq", stripCookie)
proxy.on("proxyReqWs", stripCookie)
// Intercept the response to rewrite absolute redirects against the base path.
// Is disabled when the request has no base path which means /absproxy is in use.
+132
View File
@@ -0,0 +1,132 @@
import { promises as fs } from "fs"
import * as path from "path"
import { Page } from "playwright"
import { clean, getMaybeProxiedCodeServer } from "../utils/helpers"
import { describe, test, expect } from "./baseFixture"
import { CodeServerPage } from "./models/CodeServer"
// A 1x1 PNG.
const png = Buffer.from(
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==",
"base64",
)
/**
* Open a Markdown preview that embeds a PNG from the workspace and wait for
* the image to render.
*/
async function previewMarkdownWithImage(codeServerPage: CodeServerPage, imageName: string): Promise<Page> {
const dir = await codeServerPage.workspaceDir
await fs.writeFile(path.join(dir, imageName), png)
const markdown = path.join(dir, `${imageName}.md`)
await fs.writeFile(markdown, `# Preview\n\n![workspace image](${imageName})\n`)
await codeServerPage.openFile(markdown)
await codeServerPage.executeCommandViaMenus("Markdown: Open Preview to the Side")
await codeServerPage.waitForTab(`Preview ${markdown}`)
const image = codeServerPage.page
.frameLocator("iframe.webview.ready")
.frameLocator("#active-frame")
.locator(`img[alt="workspace image"]`)
await expect.poll(() => image.evaluate((img: HTMLImageElement) => img.naturalWidth)).toBeGreaterThan(0)
return codeServerPage.page
}
/**
* URLs in the webview service worker's Cache Storage.
*/
async function cachedWebviewUrls(page: Page): Promise<string[]> {
const frame = await (await page.locator("iframe.webview.ready").elementHandle())?.contentFrame()
if (!frame) {
throw new Error("webview frame not found")
}
return frame.evaluate(async () => {
const urls: string[] = []
for (const name of await caches.keys()) {
if (name.startsWith("vscode-resource-cache-")) {
for (const request of await (await caches.open(name)).keys()) {
urls.push(request.url)
}
}
}
return urls
})
}
async function fetchRemoteResource(codeServerPage: CodeServerPage, file: string) {
const address = await getMaybeProxiedCodeServer(codeServerPage)
const url = new URL(`vscode-remote-resource?path=${encodeURIComponent(file)}`, address)
return codeServerPage.page.request.get(url.toString())
}
/**
* Write a workspace file and a file in the user extensions directory.
*/
async function writeResourceFiles(codeServerPage: CodeServerPage, name: string) {
const dir = await codeServerPage.workspaceDir
const workspaceFile = path.join(dir, `${name}-workspace.txt`)
const extensionDir = path.join(dir, "extensions", `${name}-extension`)
const extensionFile = path.join(extensionDir, "resource.txt")
await fs.writeFile(workspaceFile, "workspace")
await fs.mkdir(extensionDir, { recursive: true })
await fs.writeFile(extensionFile, "extension")
return { workspaceFile, extensionFile }
}
describe("File cache (enabled)", ["--disable-workspace-trust"], {}, async () => {
const testName = "file-cache-enabled"
test.beforeAll(async () => {
await clean(testName)
})
test("should cache workspace files in the webview Cache Storage", async ({ codeServerPage }) => {
const page = await previewMarkdownWithImage(codeServerPage, "cache-enabled.png")
await expect
.poll(async () => (await cachedWebviewUrls(page)).filter((url) => url.includes("cache-enabled.png")))
.toHaveLength(1)
})
test("should serve /vscode-remote-resource with an ETag and without no-store", async ({ codeServerPage }) => {
const { workspaceFile, extensionFile } = await writeResourceFiles(codeServerPage, "enabled")
for (const file of [workspaceFile, extensionFile]) {
const response = await fetchRemoteResource(codeServerPage, file)
expect(response.status()).toBe(200)
expect(response.headers()["etag"]).toBeTruthy()
expect(response.headers()["cache-control"] ?? "").not.toContain("no-store")
}
})
})
describe("File cache (disabled)", ["--disable-workspace-trust", "--disable-file-cache"], {}, async () => {
const testName = "file-cache-disabled"
test.beforeAll(async () => {
await clean(testName)
})
test("should keep workspace files out of the webview Cache Storage but cache extension files", async ({
codeServerPage,
}) => {
const page = await previewMarkdownWithImage(codeServerPage, "cache-disabled.png")
// Cached extension files show that the flag, not a cache failure, keeps the image out.
await expect
.poll(async () => (await cachedWebviewUrls(page)).filter((url) => url.includes("markdown-language-features")))
.not.toHaveLength(0)
expect((await cachedWebviewUrls(page)).filter((url) => url.includes("cache-disabled.png"))).toHaveLength(0)
})
test("should serve /vscode-remote-resource with no-store for workspace files and an ETag for extension files", async ({
codeServerPage,
}) => {
const { workspaceFile, extensionFile } = await writeResourceFiles(codeServerPage, "disabled")
const workspaceResponse = await fetchRemoteResource(codeServerPage, workspaceFile)
expect(workspaceResponse.status()).toBe(200)
expect(workspaceResponse.headers()["cache-control"]).toBe("no-store")
expect(workspaceResponse.headers()["etag"]).toBeUndefined()
const extensionResponse = await fetchRemoteResource(codeServerPage, extensionFile)
expect(extensionResponse.status()).toBe(200)
expect(extensionResponse.headers()["etag"]).toBeTruthy()
expect(extensionResponse.headers()["cache-control"] ?? "").not.toContain("no-store")
})
})
+3
View File
@@ -109,6 +109,8 @@ describe("parser", () => {
"--disable-file-downloads",
"--disable-file-cache",
"--disable-getting-started-override",
"--disable-proxy",
@@ -137,6 +139,7 @@ describe("parser", () => {
cert: {
value: path.resolve("path/to/cert"),
},
"disable-file-cache": true,
"disable-file-downloads": true,
"disable-getting-started-override": true,
"disable-proxy": true,
+22 -6
View File
@@ -303,6 +303,13 @@ describe("proxy", () => {
res.end(req.headers.cookie)
})
wsRouter.ws("/wsup/cookies", async (req) => {
wss.handleUpgrade(req, req.ws, req.head, (ws) => {
ws.on("message", () => ws.send(req.headers.cookie || ""))
req.ws.resume()
})
})
const cookies = [
"cookie2=hello",
// Cookies should pass through unchanged, neither encoded nor decoded.
@@ -316,13 +323,22 @@ describe("proxy", () => {
for (let i = 0; i <= cookies.length; ++i) {
const left = cookies.slice(0, i)
const right = cookies.slice(i)
const resp = await codeServer.fetch(proxyPath + "/cookies", {
headers: {
cookie: [...left, `code-server-session=${token}`, ...right].join("; "),
},
})
const expected = cookies.join("; ")
const headers = {
cookie: [...left, `code-server-session=${token}`, ...right].join("; "),
}
// Regular HTTP request.
const resp = await codeServer.fetch(proxyPath + "/cookies", { headers })
expect(resp.status).toBe(200)
expect(await resp.text()).toBe(cookies.join("; "))
expect(await resp.text()).toBe(expected)
// Web socket request.
const ws = await codeServer.wsWait(proxyPath + "/cookies", { headers })
const got = await new Promise((resolve) => {
ws.send("init")
ws.on("message", (msg) => resolve(msg))
})
ws.terminate()
expect(got).toBe(expected)
}
})