Compare commits

..

1 Commits

Author SHA1 Message Date
Nick Vigilante
299e566813 docs: fix 7 broken relative links in CONTRIBUTING.md
Relative paths like ../test/unit resolve correctly on GitHub but produce
404s when the page is rendered at coder.com/docs/code-server/CONTRIBUTING.
Replace all 7 with absolute github.com/coder/code-server/tree/main/... URLs.

Closes https://linear.app/codercom/issue/DOCS-244

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 19:00:17 -04:00
26 changed files with 153 additions and 281 deletions

View File

@@ -26,7 +26,7 @@ jobs:
helm: ${{ steps.filter.outputs.helm }} helm: ${{ steps.filter.outputs.helm }}
steps: steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 - uses: dorny/paths-filter@d1c1ffe0248fe513906c8e24db8ea791d46f8590 # v3
id: filter id: filter
with: with:
filters: | filters: |
@@ -144,7 +144,7 @@ jobs:
test/package-lock.json test/package-lock.json
- run: SKIP_SUBMODULE_DEPS=1 npm ci - run: SKIP_SUBMODULE_DEPS=1 npm ci
- run: npm run test:unit - run: npm run test:unit
- uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 - uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5
if: success() if: success()
with: with:
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
@@ -163,7 +163,7 @@ jobs:
steps: steps:
- run: sudo apt update && sudo apt install -y libkrb5-dev - run: sudo apt update && sudo apt install -y libkrb5-dev
- uses: awalsh128/cache-apt-pkgs-action@acb598e5ddbc6f68a970c5da0688d2f3a9f04d05 # latest - uses: awalsh128/cache-apt-pkgs-action@2c09a5e66da6c8016428a2172bd76e5e4f14bb17 # latest
with: with:
packages: quilt packages: quilt
version: 1.0 version: 1.0

View File

@@ -109,14 +109,14 @@ jobs:
echo "VERSION=${TAG#v}" >> $GITHUB_ENV echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 - uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with: with:
username: ${{ secrets.DOCKER_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
- uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
@@ -159,7 +159,7 @@ jobs:
git config --global user.email opensource@coder.com git config --global user.email opensource@coder.com
git checkout -b "helm/$VERSION" git checkout -b "helm/$VERSION"
git add . git add .
git commit -m "Update Helm chart and changelog with $VERSION" git commit -m "Update to $VERSION"
git push -u origin "$(git branch --show)" git push -u origin "$(git branch --show)"
gh pr create \ gh pr create \
--repo coder/code-server \ --repo coder/code-server \

View File

@@ -39,6 +39,9 @@ jobs:
- npm_arch: arm64 - npm_arch: arm64
vscode_arch: arm64 vscode_arch: arm64
package_arch: arm64 package_arch: arm64
- npm_arch: arm
vscode_arch: armhf
package_arch: armv7l
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -59,7 +62,7 @@ jobs:
steps: steps:
- run: sudo apt update && sudo apt install -y libkrb5-dev - run: sudo apt update && sudo apt install -y libkrb5-dev
- uses: awalsh128/cache-apt-pkgs-action@acb598e5ddbc6f68a970c5da0688d2f3a9f04d05 # latest - uses: awalsh128/cache-apt-pkgs-action@2c09a5e66da6c8016428a2172bd76e5e4f14bb17 # latest
with: with:
packages: quilt packages: quilt
version: 1.0 version: 1.0
@@ -69,12 +72,10 @@ jobs:
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
echo "$HOME/.local/bin" >> $GITHUB_PATH echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Strip update/ and v from tag and set major version - name: Strip update/ and v from tag
run: | run: |
version=${TAG#update/} version=${TAG#update/}
version=${version#v} echo "VERSION=${version#v}" >> $GITHUB_ENV
version=4${version:1}
echo "VERSION=$version" >> $GITHUB_ENV
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:
@@ -147,7 +148,7 @@ jobs:
env: env:
VSCODE_TARGET: ${{ matrix.vscode_target }} VSCODE_TARGET: ${{ matrix.vscode_target }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ inputs.version || github.event.pull_request.head.ref || github.ref_name }} TAG: ${{ inputs.version || github.ref_name }}
# Ensure native modules are built from source to avoid prebuilds. # Ensure native modules are built from source to avoid prebuilds.
npm_config_build_from_source: true npm_config_build_from_source: true
@@ -163,12 +164,10 @@ jobs:
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
echo "$HOME/.local/bin" >> $GITHUB_PATH echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Strip update/ and v from tag and set major version - name: Strip update/ and v from tag
run: | run: |
version=${TAG#update/} version=${TAG#update/}
version=${version#v} echo "VERSION=${version#v}" >> $GITHUB_ENV
version=4${version:1}
echo "VERSION=$version" >> $GITHUB_ENV
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with: with:

View File

@@ -47,7 +47,7 @@ jobs:
echo done=false >> $GITHUB_OUTPUT echo done=false >> $GITHUB_OUTPUT
fi fi
- uses: awalsh128/cache-apt-pkgs-action@acb598e5ddbc6f68a970c5da0688d2f3a9f04d05 # latest - uses: awalsh128/cache-apt-pkgs-action@2c09a5e66da6c8016428a2172bd76e5e4f14bb17 # latest
if: steps.check.outputs.done == 'false' if: steps.check.outputs.done == 'false'
with: with:
packages: quilt packages: quilt

View File

@@ -1 +1 @@
24.15.0 22.22.1

View File

@@ -22,58 +22,6 @@ Code v99.99.999
## Unreleased ## Unreleased
## [4.124.2](https://github.com/coder/code-server/releases/tag/v4.124.2) - 2026-06-16
Code v1.124.2
### Security
- Strip code-server's session token from the cookie before proxying to a local
port. Previously, when you used built-in password authentication, the cookie
would be sent to the local proxied port, which meant if the service was
malicious and not already running as your code-server user it could use the
cookie to log into code-server and execute commands as your code-server user.
### Changed
- Update to Code 1.124.2
## [4.123.0](https://github.com/coder/code-server/releases/tag/v4.123.0) - 2026-06-03
Code v1.123.0
### Changed
- Update to Code 1.123.0
- Microsoft dropped support for armhf remotes so there will no longer be any
builds for armhf.
## [4.122.1](https://github.com/coder/code-server/releases/tag/v4.122.1) - 2026-06-02
Code v1.122.1
### Changed
- Update to Code 1.122.1
## [4.122.0](https://github.com/coder/code-server/releases/tag/v4.122.0) - 2026-05-29
Code v1.122.0
### Changed
- Update to Code 1.122.0
### Fixed
- `--app-name` will now affect window titles within the editor (it is now used
as the value for `${appName}` in the title template) as well as some other
places like the help > about dialog.
### Added
- App name can now be set with the `CODE_SERVER_APP_NAME` environment variable.
## [4.121.0](https://github.com/coder/code-server/releases/tag/v4.121.0) - 2026-05-20 ## [4.121.0](https://github.com/coder/code-server/releases/tag/v4.121.0) - 2026-05-20
Code v1.121.0 Code v1.121.0

View File

@@ -128,9 +128,7 @@ bundle_vscode() {
# Merge the package.json for the web/remote server so we can include # Merge the package.json for the web/remote server so we can include
# dependencies, since we want to ship this via NPM. # dependencies, since we want to ship this via NPM.
# Also override the name to prevent vulnerability scanners from jq --slurp '.[0] * .[1]' \
# misidentifying this package as VS Code (see #7071).
jq --slurp '.[0] * .[1] | .name = "code-oss-dev"' \
"$VSCODE_SRC_PATH/remote/package.json" \ "$VSCODE_SRC_PATH/remote/package.json" \
"$VSCODE_OUT_PATH/package.json" > "$VSCODE_OUT_PATH/package.json.merged" "$VSCODE_OUT_PATH/package.json" > "$VSCODE_OUT_PATH/package.json.merged"
mv "$VSCODE_OUT_PATH/package.json.merged" "$VSCODE_OUT_PATH/package.json" mv "$VSCODE_OUT_PATH/package.json.merged" "$VSCODE_OUT_PATH/package.json"

View File

@@ -2,65 +2,16 @@
set -Eeuo pipefail set -Eeuo pipefail
# Given versions $1 and $2 figure out the first component that is different
# (major, minor, patch).
function find_version_diff() {
# shellcheck disable=SC2206
local a=( ${1//./ } )
# shellcheck disable=SC2206
local b=( ${2//./ } )
if [[ ${a[0]} != "${b[0]}" ]] ; then
echo major
elif [[ ${a[1]} != "${b[1]}" ]] ; then
echo minor
else
echo patch
fi
}
# Bump $1 by the bump type (major, minor, patch) in $2.
function bump_version() {
# shellcheck disable=SC2206
local a=( ${1//./ } )
case $2 in
major)
((a[0]++))
a[1]=0
a[2]=0
;;
minor)
((a[1]++))
a[2]=0
;;
*)
((a[2]++))
;;
esac
echo "${a[0]}.${a[1]}.${a[2]}"
}
function update_helm() { function update_helm() {
local chart_version local current
chart_version=$(yq .version ci/helm-chart/Chart.yaml) current=$(yq .version ci/helm-chart/Chart.yaml)
local app_version local next
app_version=$(yq .appVersion ci/helm-chart/Chart.yaml) next=$(semver "$current" -i minor)
local image_version echo "Bumping version from $current to $next..."
image_version=$(yq .image.tag ci/helm-chart/values.yaml) sed -i.bak "s/^version: $current\$/version: $next/" ci/helm-chart/Chart.yaml
local bump_type echo "Setting app version and image to $version..."
bump_type=$(find_version_diff "$app_version" "$version")
local chart_version_bump
chart_version_bump=$(bump_version "$chart_version" "$bump_type")
# Use sed to replace because yq will reformat.
echo "Bumping version from $chart_version to $chart_version_bump..."
sed -i.bak "s/^version: $chart_version\$/version: $chart_version_bump/" ci/helm-chart/Chart.yaml
echo "Bumping app version from $app_version to $version..."
sed -i.bak "s/^appVersion: .\+\$/appVersion: $version/" ci/helm-chart/Chart.yaml sed -i.bak "s/^appVersion: .\+\$/appVersion: $version/" ci/helm-chart/Chart.yaml
echo "Bumping image version from $image_version to $version..."
sed -i.bak "s/^ tag: .\+\$/ tag: '$version'/" ci/helm-chart/values.yaml sed -i.bak "s/^ tag: .\+\$/ tag: '$version'/" ci/helm-chart/values.yaml
} }
@@ -86,8 +37,7 @@ function main() {
"Update changelog" "update_changelog" "Update changelog" "update_changelog"
) )
# Even if a step failed, still output the last checkmark. run-steps "${steps[@]}"
run-steps "${steps[@]}" || true
# This step is always manual. # This step is always manual.
echo "- [ ] https://github.com/coder/code-server-aur/pulls" >> .cache/checklist echo "- [ ] https://github.com/coder/code-server-aur/pulls" >> .cache/checklist

View File

@@ -146,8 +146,7 @@ function main() {
"Add changelog note" "add_changelog" "Add changelog note" "add_changelog"
) )
# Even if a step failed, still output the last checkmark. run-steps "${steps[@]}"
run-steps "${steps[@]}" || true
# This step is always manual. # This step is always manual.
echo "- [ ] Verify changelog" >> .cache/checklist echo "- [ ] Verify changelog" >> .cache/checklist

View File

@@ -15,9 +15,9 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes # 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. # to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/) # Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 3.39.0 version: 3.36.0
# This is the version number of the application being deployed. This version number should be # 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 # 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. # follow Semantic Versioning. They should reflect the version the application is using.
appVersion: 4.124.2 appVersion: 4.121.0

View File

@@ -6,7 +6,7 @@ replicaCount: 1
image: image:
repository: codercom/code-server repository: codercom/code-server
tag: '4.124.2' tag: '4.121.0'
pullPolicy: Always pullPolicy: Always
# Specifies one or more secrets to be used when pulling images from a # Specifies one or more secrets to be used when pulling images from a

View File

@@ -201,7 +201,7 @@ There are four kinds of tests in code-server:
Our unit tests are written in TypeScript and run using Our unit tests are written in TypeScript and run using
[Jest](https://jestjs.io/), the testing framework]. [Jest](https://jestjs.io/), the testing framework].
These live under [test/unit](../test/unit). These live under [test/unit](https://github.com/coder/code-server/tree/main/test/unit).
We use unit tests for functions and things that can be tested in isolation. The We use unit tests for functions and things that can be tested in isolation. The
file structure is modeled closely after `/src` so it's easy for people to know file structure is modeled closely after `/src` so it's easy for people to know
@@ -230,7 +230,7 @@ testing the CLI requires us to build and package code-server.
The end-to-end (e2e) tests are written in TypeScript and run using The end-to-end (e2e) tests are written in TypeScript and run using
[Playwright](https://playwright.dev/). [Playwright](https://playwright.dev/).
These live under [test/e2e](../test/e2e). These live under [test/e2e](https://github.com/coder/code-server/tree/main/test/e2e).
Before the e2e tests run, we run `globalSetup`, which eliminates the need to log Before the e2e tests run, we run `globalSetup`, which eliminates the need to log
in before each test by preserving the authentication state. in before each test by preserving the authentication state.
@@ -246,15 +246,15 @@ We also have a model where you can create helpers to use within tests. See
code-server essentially serves as an HTTP API for logging in and starting a code-server essentially serves as an HTTP API for logging in and starting a
remote Code process. remote Code process.
The CLI code is in [src/node](../src/node) and the HTTP routes are implemented The CLI code is in [src/node](https://github.com/coder/code-server/tree/main/src/node) and the HTTP routes are implemented
in [src/node/routes](../src/node/routes). in [src/node/routes](https://github.com/coder/code-server/tree/main/src/node/routes).
Most of the meaty parts are in the Code portion of the codebase under Most of the meaty parts are in the Code portion of the codebase under
[lib/vscode](../lib/vscode), which we describe next. [lib/vscode](https://github.com/coder/code-server/tree/main/lib/vscode), which we describe next.
### Modifications to Code ### Modifications to Code
Our modifications to Code can be found in the [patches](../patches) directory. Our modifications to Code can be found in the [patches](https://github.com/coder/code-server/tree/main/patches) directory.
We pull in Code as a submodule pointing to an upstream release branch. We pull in Code as a submodule pointing to an upstream release branch.
In v1 of code-server, we had Code as a submodule and used a single massive patch In v1 of code-server, we had Code as a submodule and used a single massive patch
@@ -277,7 +277,7 @@ requires us to ensure that our changes are still applied correctly and work as
intended. In the future, we'd like to run Code unit tests against our builds to intended. In the future, we'd like to run Code unit tests against our builds to
ensure that features work as expected. ensure that features work as expected.
> We have [extension docs](../ci/README.md) on the CI and build system. > We have [extension docs](https://github.com/coder/code-server/tree/main/ci) on the CI and build system.
If the functionality you're working on does NOT depend on code from Code, please If the functionality you're working on does NOT depend on code from Code, please
move it out and into code-server. move it out and into code-server.

85
package-lock.json generated
View File

@@ -13,7 +13,6 @@
"@coder/logger": "^3.0.1", "@coder/logger": "^3.0.1",
"argon2": "^0.44.0", "argon2": "^0.44.0",
"compression": "^1.7.4", "compression": "^1.7.4",
"cookie": "^1.1.1",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"env-paths": "^2.2.1", "env-paths": "^2.2.1",
"express": "^5.0.1", "express": "^5.0.1",
@@ -58,7 +57,7 @@
"eslint-import-resolver-typescript": "^4.4.4", "eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import": "^2.28.1", "eslint-plugin-import": "^2.28.1",
"eslint-plugin-prettier": "^5.0.0", "eslint-plugin-prettier": "^5.0.0",
"globals": "^17.6.0", "globals": "^16.1.0",
"prettier": "3.8.3", "prettier": "3.8.3",
"prettier-plugin-sh": "^0.18.0", "prettier-plugin-sh": "^0.18.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
@@ -969,9 +968,9 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "5.0.6", "version": "5.0.5",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
"integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -1640,9 +1639,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/basic-ftp": { "node_modules/basic-ftp": {
"version": "5.3.1", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz", "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.0.tgz",
"integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==", "integrity": "sha512-5K9eNNn7ywHPsYnFwjKgYH8Hf8B5emh7JKcPaVjjrMJFQQwGpwowEnZNEtHs7DfR7hCZsmaK3VA4HUK0YarT+w==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"
@@ -1937,16 +1936,12 @@
} }
}, },
"node_modules/cookie": { "node_modules/cookie": {
"version": "1.1.1", "version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18" "node": ">= 0.6"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
} }
}, },
"node_modules/cookie-parser": { "node_modules/cookie-parser": {
@@ -1962,15 +1957,6 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/cookie-parser/node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-signature": { "node_modules/cookie-signature": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
@@ -2967,15 +2953,6 @@
"url": "https://opencollective.com/express" "url": "https://opencollective.com/express"
} }
}, },
"node_modules/express/node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/express/node_modules/cookie-signature": { "node_modules/express/node_modules/cookie-signature": {
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
@@ -3333,9 +3310,9 @@
} }
}, },
"node_modules/globals": { "node_modules/globals": {
"version": "17.6.0", "version": "16.5.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz",
"integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==", "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -3660,9 +3637,9 @@
} }
}, },
"node_modules/ip-address": { "node_modules/ip-address": {
"version": "10.2.0", "version": "10.1.0",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
"integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 12" "node": ">= 12"
@@ -4153,19 +4130,9 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/js-yaml": { "node_modules/js-yaml": {
"version": "4.2.0", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/nodeca"
}
],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"argparse": "^2.0.1" "argparse": "^2.0.1"
@@ -5230,9 +5197,9 @@
} }
}, },
"node_modules/qs": { "node_modules/qs": {
"version": "6.15.2", "version": "6.15.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
"integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"side-channel": "^1.1.0" "side-channel": "^1.1.0"
@@ -6646,9 +6613,9 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/ws": { "node_modules/ws": {
"version": "8.21.0", "version": "8.20.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz",
"integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"

View File

@@ -59,7 +59,7 @@
"eslint-import-resolver-typescript": "^4.4.4", "eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import": "^2.28.1", "eslint-plugin-import": "^2.28.1",
"eslint-plugin-prettier": "^5.0.0", "eslint-plugin-prettier": "^5.0.0",
"globals": "^17.6.0", "globals": "^16.1.0",
"prettier": "3.8.3", "prettier": "3.8.3",
"prettier-plugin-sh": "^0.18.0", "prettier-plugin-sh": "^0.18.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
@@ -70,7 +70,6 @@
"@coder/logger": "^3.0.1", "@coder/logger": "^3.0.1",
"argon2": "^0.44.0", "argon2": "^0.44.0",
"compression": "^1.7.4", "compression": "^1.7.4",
"cookie": "^1.1.1",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"env-paths": "^2.2.1", "env-paths": "^2.2.1",
"express": "^5.0.1", "express": "^5.0.1",

View File

@@ -20,7 +20,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */ /* ----- server setup ----- */
@@ -124,6 +125,7 @@ export interface ServerParsedArgs { @@ -120,6 +121,7 @@ export interface ServerParsedArgs {
'disable-getting-started-override'?: boolean, 'disable-getting-started-override'?: boolean,
'locale'?: string 'locale'?: string
'link-protection-trusted-domains'?: string[], 'link-protection-trusted-domains'?: string[],

View File

@@ -263,7 +263,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
} }
private startListening(): void { private startListening(): void {
@@ -590,17 +591,6 @@ class WorkspaceProvider implements IWork @@ -584,17 +585,6 @@ class WorkspaceProvider implements IWork
} }
} }
@@ -281,7 +281,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
(function () { (function () {
// Find config by checking for DOM // Find config by checking for DOM
@@ -610,8 +600,8 @@ function readCookie(name: string): strin @@ -604,8 +594,8 @@ function readCookie(name: string): strin
if (!configElement || !configElementAttribute) { if (!configElement || !configElementAttribute) {
throw new Error('Missing web configuration element'); throw new Error('Missing web configuration element');
} }

View File

@@ -2,8 +2,8 @@ Index: code-server/lib/vscode/build/gulpfile.extensions.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/build/gulpfile.extensions.ts --- code-server.orig/lib/vscode/build/gulpfile.extensions.ts
+++ code-server/lib/vscode/build/gulpfile.extensions.ts +++ code-server/lib/vscode/build/gulpfile.extensions.ts
@@ -291,6 +291,29 @@ export const compileCopilotExtensionBuil @@ -294,6 +294,29 @@ export const compileCopilotExtensionBuil
task.task(compileCopilotExtensionBuildTask); gulp.task(compileCopilotExtensionBuildTask);
/** /**
+ * Compiles the built-in copilot extension with proper `.vscodeignore` filtering + * Compiles the built-in copilot extension with proper `.vscodeignore` filtering
@@ -26,7 +26,7 @@ Index: code-server/lib/vscode/build/gulpfile.extensions.ts
+ return Promise.resolve(); + return Promise.resolve();
+ }) + })
+)); +));
+task.task(compileCopilotExtensionFullBuildTask); +gulp.task(compileCopilotExtensionFullBuildTask);
+ +
+/** +/**
* Compiles the extensions for the build. * Compiles the extensions for the build.
@@ -36,15 +36,15 @@ Index: code-server/lib/vscode/build/lib/extensions.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/build/lib/extensions.ts --- code-server.orig/lib/vscode/build/lib/extensions.ts
+++ code-server/lib/vscode/build/lib/extensions.ts +++ code-server/lib/vscode/build/lib/extensions.ts
@@ -21,6 +21,7 @@ import { getProductionDependencies } fro @@ -24,6 +24,7 @@ import { getProductionDependencies } fro
import { type IExtensionDefinition, getExtensionStream } from './builtInExtensions.ts'; import { type IExtensionDefinition, getExtensionStream } from './builtInExtensions.ts';
import { fetchUrls, fetchGithub } from './fetch.ts'; import { fetchUrls, fetchGithub } from './fetch.ts';
import { createTsgoStream, spawnTsgo } from './tsgo.ts'; import { createTsgoStream, spawnTsgo } from './tsgo.ts';
+import { prepareBuiltInCopilotRipgrepShim } from './copilot.ts'; +import { prepareBuiltInCopilotRipgrepShim } from './copilot.ts';
import watcher from './watch/index.ts'; import vzip from 'gulp-vinyl-zip';
import { createRequire } from 'module'; import { createRequire } from 'module';
@@ -483,6 +484,116 @@ export function packageCopilotExtensionS @@ -492,6 +493,116 @@ export function packageCopilotExtensionS
).pipe(util2.setExecutableBit(['**/*.sh'])); ).pipe(util2.setExecutableBit(['**/*.sh']));
} }

View File

@@ -7,7 +7,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts --- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
@@ -345,6 +345,10 @@ export class Extension implements IExten @@ -342,6 +342,10 @@ export class Extension implements IExten
if (this.type === ExtensionType.System && this.productService.quality === 'stable' && !this.productService.builtInExtensionsEnabledWithAutoUpdates?.some(id => id.toLowerCase() === this.identifier.id.toLowerCase())) { if (this.type === ExtensionType.System && this.productService.quality === 'stable' && !this.productService.builtInExtensionsEnabledWithAutoUpdates?.some(id => id.toLowerCase() === this.identifier.id.toLowerCase())) {
return false; return false;
} }

View File

@@ -18,7 +18,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
import { ProtocolConstants } from '../../base/parts/ipc/common/ipc.net.js'; import { ProtocolConstants } from '../../base/parts/ipc/common/ipc.net.js';
import { IConfigurationService } from '../../platform/configuration/common/configuration.js'; import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
import { ConfigurationService } from '../../platform/configuration/common/configurationService.js'; import { ConfigurationService } from '../../platform/configuration/common/configurationService.js';
@@ -359,6 +359,9 @@ export async function setupServerService @@ -358,6 +358,9 @@ export async function setupServerService
socketServer.registerChannel('mcpManagement', new McpManagementChannel(mcpManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority))); socketServer.registerChannel('mcpManagement', new McpManagementChannel(mcpManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority)));

View File

@@ -104,7 +104,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
import type { IURLCallbackProvider } from '../../../workbench/services/url/browser/urlService.js'; import type { IURLCallbackProvider } from '../../../workbench/services/url/browser/urlService.js';
import { create } from '../../../workbench/workbench.web.main.internal.js'; import { create } from '../../../workbench/workbench.web.main.internal.js';
@@ -612,6 +613,39 @@ class WorkspaceProvider implements IWork @@ -606,6 +607,39 @@ class WorkspaceProvider implements IWork
settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined, settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined,
workspaceProvider: WorkspaceProvider.create(config), workspaceProvider: WorkspaceProvider.create(config),
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute), urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),

View File

@@ -6,7 +6,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/build/gulpfile.reh.ts --- code-server.orig/lib/vscode/build/gulpfile.reh.ts
+++ code-server/lib/vscode/build/gulpfile.reh.ts +++ code-server/lib/vscode/build/gulpfile.reh.ts
@@ -296,10 +296,15 @@ function packageTask(type: string, platf @@ -261,10 +261,15 @@ function packageTask(type: string, platf
const destination = path.join(BUILD_ROOT, destinationFolderName); const destination = path.join(BUILD_ROOT, destinationFolderName);
return () => { return () => {

View File

@@ -41,7 +41,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
=================================================================== ===================================================================
--- code-server.orig/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 +++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
@@ -226,7 +226,7 @@ export class BrowserWorkbenchEnvironment @@ -223,7 +223,7 @@ export class BrowserWorkbenchEnvironment
@memoize @memoize
get webviewExternalEndpoint(): string { get webviewExternalEndpoint(): string {
@@ -70,8 +70,8 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" <meta http-equiv="Content-Security-Policy"
- content="default-src 'none'; script-src 'sha256-nXjtuhBilO++r8hfxl5VjEScSmdm07wDAk6jw228DgM=' 'self'; frame-src 'self'; style-src 'unsafe-inline';"> - content="default-src 'none'; script-src 'sha256-q+WTr+fBXpLLE3++yWNaxT6BTWQtsKscoeIlynBRk4E=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
+ content="default-src 'none'; script-src 'sha256-A6/szVNdTzyi4hDa+9OLbzS8tSd2iUV4CqimLNWex2Y=' 'self'; frame-src 'self'; style-src 'unsafe-inline';"> + content="default-src 'none'; script-src 'sha256-m1DlJtsIJd46QuWYNcsaYIG1xI+9FyjKQu+cfp+zq5Q=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
<!-- Disable pinch zooming --> <!-- Disable pinch zooming -->
<meta name="viewport" <meta name="viewport"

View File

@@ -1,7 +1,5 @@
import * as cookie from "cookie"
import type { Request } from "express"
import proxyServer from "http-proxy" import proxyServer from "http-proxy"
import { getCookieSessionName, HttpCode } from "../common/http" import { HttpCode } from "../common/http"
export const proxy = proxyServer.createProxyServer({}) export const proxy = proxyServer.createProxyServer({})
@@ -20,19 +18,6 @@ proxy.on("error", (error, _, res) => {
} }
}) })
// Strip the code-server cookie if it exists to avoid transmitting the cookie
// to potentially malicious local ports.
proxy.on("proxyReq", (preq, req) => {
const cookieSessionName = getCookieSessionName((req as Request).args["cookie-suffix"])
preq.setHeader(
"Cookie",
cookie.stringifyCookie({
...(req as Request).cookies,
[cookieSessionName]: undefined,
}),
)
})
// Intercept the response to rewrite absolute redirects against the base path. // 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. // Is disabled when the request has no base path which means /absproxy is in use.
proxy.on("proxyRes", (res, req) => { proxy.on("proxyRes", (res, req) => {

View File

@@ -33,10 +33,12 @@ const config: PlaywrightTestConfig = {
// name: "Firefox", // name: "Firefox",
// use: { browserName: "firefox" }, // use: { browserName: "firefox" },
// }, // },
{ // Keeps failing with "Underlying ArrayBuffer has been detached from the view or out-of-bounds"
name: "WebKit", // Not sure what we can do about it...so skip for now.
use: { browserName: "webkit" }, // {
}, // name: "WebKit",
// use: { browserName: "webkit" },
// },
], ],
} }

View File

@@ -1,12 +1,15 @@
import * as express from "express" import * as express from "express"
import * as http from "http"
import nodeFetch from "node-fetch"
import { HttpCode } from "../../../src/common/http" import { HttpCode } from "../../../src/common/http"
import { proxy } from "../../../src/node/proxy"
import { wss, Router as WsRouter } from "../../../src/node/wsRouter" import { wss, Router as WsRouter } from "../../../src/node/wsRouter"
import { mockLogger } from "../../utils/helpers" import { getAvailablePort, mockLogger } from "../../utils/helpers"
import * as httpserver from "../../utils/httpserver" import * as httpserver from "../../utils/httpserver"
import * as integration from "../../utils/integration" import * as integration from "../../utils/integration"
describe("proxy", () => { describe("proxy", () => {
const proxyTarget = new httpserver.HttpServer() const nhooyrDevServer = new httpserver.HttpServer()
const wsApp = express.default() const wsApp = express.default()
const wsRouter = WsRouter() const wsRouter = WsRouter()
let codeServer: httpserver.HttpServer | undefined let codeServer: httpserver.HttpServer | undefined
@@ -16,22 +19,21 @@ describe("proxy", () => {
beforeAll(async () => { beforeAll(async () => {
wsApp.use("/", wsRouter.router) wsApp.use("/", wsRouter.router)
await proxyTarget.listen((req, res) => { await nhooyrDevServer.listen((req, res) => {
e(req, res) e(req, res)
}) })
proxyTarget.listenUpgrade(wsApp) nhooyrDevServer.listenUpgrade(wsApp)
proxyPath = `/proxy/${proxyTarget.port()}/wsup` proxyPath = `/proxy/${nhooyrDevServer.port()}/wsup`
absProxyPath = proxyPath.replace("/proxy/", "/absproxy/") absProxyPath = proxyPath.replace("/proxy/", "/absproxy/")
}) })
afterAll(async () => { afterAll(async () => {
await proxyTarget.dispose() await nhooyrDevServer.dispose()
}) })
beforeEach(() => { beforeEach(() => {
e = express.default() e = express.default()
mockLogger() mockLogger()
delete process.env.PASSWORD
}) })
afterEach(async () => { afterEach(async () => {
@@ -281,42 +283,65 @@ describe("proxy", () => {
const resp = await codeServer.fetch(proxyPath, { method: "OPTIONS" }) const resp = await codeServer.fetch(proxyPath, { method: "OPTIONS" })
expect(resp.status).toBe(200) expect(resp.status).toBe(200)
}) })
})
it("should return a 500 when no target is running ", async () => { // NOTE@jsjoeio
const target = new httpserver.HttpServer() // Both this test suite and the one above it are very similar
await target.listen(() => {}) // The main difference is this one uses http and node-fetch
const port = target.port() // and specifically tests the proxy in isolation vs. using
target.dispose() // the httpserver abstraction we've built.
codeServer = await integration.setup(["--auth=none"], "") //
const resp = await codeServer.fetch(`/proxy/${port}/wsup`) // Leaving this as a separate test suite for now because
expect(resp.status).toBe(HttpCode.ServerError) // we may consider refactoring the httpserver abstraction
expect(resp.statusText).toBe("Internal Server Error") // in the future.
//
// If you're writing a test specifically for code in
// src/node/proxy.ts, you should probably add it to
// this test suite.
describe("proxy (standalone)", () => {
let URL = ""
let PROXY_URL = ""
let testServer: http.Server
let proxyTarget: http.Server
beforeEach(async () => {
const PORT = await getAvailablePort()
const PROXY_PORT = await getAvailablePort()
URL = `http://localhost:${PORT}`
PROXY_URL = `http://localhost:${PROXY_PORT}`
// Define server and a proxy server
testServer = http.createServer((req, res) => {
proxy.web(req, res, {
target: PROXY_URL,
})
})
proxyTarget = http.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" })
res.end()
})
// Start both servers
proxyTarget.listen(PROXY_PORT)
testServer.listen(PORT)
}) })
it("should strip token cookie", async () => { afterEach(async () => {
const token = "my-super-secure-token" testServer.close()
process.env.HASHED_PASSWORD = token proxyTarget.close()
codeServer = await integration.setup(["--auth=password"]) })
// Set up a listener that just prints the cookies it got. it("should return a 500 when proxy target errors ", async () => {
e.get("/wsup/cookies", (req, res) => { // Close the proxy target so that proxy errors
res.writeHead(HttpCode.Ok, { "Content-Type": "text/plain" }) proxyTarget.close()
res.end(req.headers.cookie) const errorResp = await nodeFetch(`${URL}/error`)
}) expect(errorResp.status).toBe(HttpCode.ServerError)
expect(errorResp.statusText).toBe("Internal Server Error")
})
// Send the token along with other cookies which should be preserved. it("should proxy correctly", async () => {
// Encode one to make sure they are being re-encoded properly. const resp = await nodeFetch(`${URL}/route`)
const value = "hello=there"
const encodedValue = encodeURIComponent(value)
const resp = await codeServer.fetch(proxyPath + "/cookies", {
headers: {
cookie: `cookie1=${encodedValue}; code-server-session=${token}; cookie2=hello;`,
},
})
// The proxied listener should not have printed the code-server token.
expect(resp.status).toBe(200) expect(resp.status).toBe(200)
const text = await resp.text() expect(resp.statusText).toBe("OK")
expect(text).toBe(`cookie1=${encodedValue}; cookie2=hello`)
}) })
}) })