Skip to content

Commit adcf629

Browse files
authored
Update Deno to 2.9.8 to distrust compromised eMudhra certificates (#15186)
Deno 2.7.14 still trusts the eight eMudhra and emSign intermediates whose private keys are recoverable, so every HTTPS request Quarto makes from Deno (quarto publish, quarto add, quarto use template, and tool installers) accepts certificates minted with them. Deno 2.9.8 is the first release that rejects these paths (denoland/deno#37046). Earlier 2.9.x releases do not, and DENO_TLS_CA_STORE cannot work around it, because Quarto's launchers always set it to system,mozilla. - Bump the bundled Deno to 2.9.8. - Vendor scripts use --allow-import instead of --allow-all. Deno 2.9 rejects permission flags on a non-global deno install (denoland/deno#36489), and the vendor scripts continue on error, so configure finished without filling the cache. - Fix the TypeScript 6 errors that failed deno test: JSON imports move from assert to with, the Posit Connect Cloud client takes Uint8Array<ArrayBuffer> for fetch bodies, and test timer handles use ReturnType<typeof setTimeout>. - findOpenPort skips port 4190 instead of 4160. 4190 is the Fetch standard's blocked sieve port, and Deno 2.9 refuses to fetch it. The port test reads the runtime's blocked list instead of a copy. - logError prints the error cause chain. Deno 2.9 reports every failed fetch as "fetch failed" with the reason in cause, so TLS and DNS errors stay visible. - Regenerate the editor tooling bundles for the import attribute change. Fixes #15157 See #15152. Builds on #15180, which covers the cross-version Deno KV cache problem (caches written by 2.9.8 breaking older Quarto).
1 parent 623cd99 commit adcf629

30 files changed

Lines changed: 236 additions & 78 deletions

File tree

‎configuration‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
# IMPORTANT: When these are updated, you must also update the versions
1111
# in src/command/check/check.ts
1212
# Binary dependencies
13-
export DENO=v2.7.14
13+
export DENO=v2.9.8
1414
# TODO figure out where 0.1.41 apple silicon libs are available
1515
export DENO_DOM=v0.1.41-alpha-artifacts
1616
export PANDOC=3.10

‎dev-docs/runtime-migration/HANDOFF.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ These were throwaway and are recreated by the plans when needed:
4646
`REVIEW-2026-10-15.md` is the principal review of the first draft (13 structural findings, per-plan defects, the landing strategy, the decisions taken in its section 6).
4747
Every plan was then reworked against it: six new PRs (00a, 00b, 00c, 02b, 14b, 20b, 27b), PR 21 folded into 25, PR 07 and PR 39 rewritten and renamed, `SPIKES.md` added, `_TEMPLATE.md` vocabulary updated, `00-assessment.md` given an errata section.
4848
`README.md` carries the new table, dependency graph, conventions and baseline.
49-
The plans are now executable in the README order; PR 02 (#15135) and 02c (#15153) are merged, 02d (the ratchet also counts `Deno` reached through optional chaining and `globalThis`) is in progress, and the next to run are 00a, then 00b.
49+
The plans are now executable in the README order; PR 02 (#15135), 02c (#15153) and 02d (#15218) are merged; 00a is in progress as the Deno 2.9.8 security bump (#15152), and 00b runs next.
5050

5151
## Reconciliation pass (bucket B of `TRIAGE-2026-10-16.md`): done on 2026-10-16
5252

@@ -78,7 +78,7 @@ Two notes for whoever continues: the B1 commit carries the maintainer's author i
7878
2. Read `README.md`, then `00-assessment.md` sections 10 and 11, then `_TEMPLATE.md`.
7979
3. The section 9 decisions are taken (`REVIEW-2026-10-15.md` section 6); the test runner is decided by Spike V in `SPIKES.md` before PR 31.
8080
4. Apply the local corrections of `TRIAGE-2026-10-16.md` bucket C (one task per plan file, in parallel where the triage marks it), then the re-read of 02, 25, 26, 27, 29, 33, 35, 36 the triage's step 4 asks for (02, 25, 26, 27 and 29 done 2026-10-16, 33, 35 and 36 done 2026-10-17: step 4 is complete).
81-
5. PR 02 and 02c are merged, 02d is in progress; open the remaining plans as PRs against `main` in the README order: 00a and 00b, then 03–06 in parallel, then 07.
81+
5. PR 02, 02c and 02d are merged, and 00a is in progress; open the remaining plans as PRs against `main` in the README order: 00b, then 03–06 in parallel, then 07.
8282
Each plan names its branch, executor and verification commands.
8383
For the per-worktree session ritual (window model, trust, fresh conversation, concurrency ceiling), check
8484
`local/multi-worktree-workflow.md` if it exists — it is a maintainer-local, untracked note.

‎dev-docs/runtime-migration/README.md‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ The rows below are the ones that still need a named person or an external answer
134134
| PR 19 Task 1, PR 27b | both replace the whole body of `platform.ts`: keep the `v8Branch` export (`_TEMPLATE.md`, "`platform.ts`"); PR 27b computes it from `process.versions.v8` | coordinator | step 0 of each |
135135
| PR 02c (from #15202, which turned `main` red) | Decided 2026-10-27: PR runs fail on any increase that leaves a count above their own `tools/runtime-boundary-baseline.json` (exactly what the push check on `main` will compare), instead of only warning; an increase that still fits because `main` sits below its baseline is a notice; 02c's "everything else is a warning for the maintainer" and its "exit 1 if any error, else 0" no longer hold. Per-line findings stay warnings saying the contributor has nothing to change, plus one `::error` saying a maintainer pushes the baseline update before merging; the remedy is unchanged (update the branch with `main`, `--update-baseline --accept-increase`, push to the PR). Rejected: an acceptance label (the merged tree still carries the old baseline, so `main` fails anyway) and warn-only with a merge checklist (the human step is what failed). A plan whose expected delta raises a count runs `--accept-increase` in its PR (PRs 01 and 05 already do) | maintainer | step 0 of any plan that raises a count |
136136
| PR 30 | tagged `v8-<branch>/` directories are left behind like the untagged `.kv` files; remove `v8Branch` and its contract-test line together with its last consumer. What "damaged" means for the JSON index (unparsable or truncated file): keep the miss-with-warning versus fail-naming-the-folder split or not. The Deno KV damage tests (`tests/unit/kv-damage.test.ts` and the damaged-store cases in `sass-cache.test.ts` and `project-cache.test.ts`, from the #15119 fix) build real SQLite damage: they are replaced or deleted here, because PR 32 runs the full unit suite on Node, where neither `Deno.openKv` nor its damage exists, and "`sass-cache.test.ts` stays green" is restated accordingly | maintainer (damage semantics), coordinator (the rest) | PR 30 step 0 |
137+
| PR 00b, vendor script steps | Deno 2.9 rejects permission flags on a non-global `deno install` (denoland/deno#36489), and the vendor scripts keep going after a failed entrypoint, so `--allow-all` vendors nothing. Every `deno install` line the plan adds uses `--allow-import`, as the current vendor scripts do since #15152; its `deno run` and `deno bundle` lines keep `--allow-all` | executor | step 0 of PR 00b |
138+
| PR 01 | The `assert` → `with` half landed with #15152 (TypeScript 6 in Deno 2.9 rejects `assert`, TS2880), and it changed the IDE bundles: esbuild now wraps the JSON module as ESM (same data, same `.default`). Skip those edits and the "bundles unchanged" check; the PR keeps only the bslib ordering | executor | step 0 of PR 01 |
139+
| PR 15 Task 2 | The replacement `port.ts` listing has `4160, // sieve` and a private `isPortSafe`. Since #15152 the list has `4190` (the Fetch standard's bad port, which Deno 2.9's `fetch` refuses) and `isPortSafe` is exported for `tests/unit/core/port.test.ts`. Retain port `4190` and the exported `isPortSafe`, and ensure `tests/unit/core/port.test.ts` still passes. | executor | step 0 of PR 15 |
140+
| PRs 15, 16, 23 and 31, sanitizer checks | Deno 2.9 disables test sanitizers by default, and `tests/test.ts` does not enable them. Enabling them causes every test to fail because the harness leaks an open file and a timer; these leaks also occur on Deno 2.7.14. Fix the harness leaks and re-enable sanitizers before relying on the plans' "no sanitizer failures" checks or PR 31's "Leak guarantees". | maintainer | before PR 15 runs |
137141

138142
## Shared rules and tables
139143

@@ -201,11 +205,11 @@ Every PR that changes a count lands after 02c; preparing it earlier is fine.
201205
|---|---|---|---|---|---|---|
202206
| 02 | [02-runtime-boundary-check.md](02-runtime-boundary-check.md) | CI ratchet counting `Deno.*` and direct std imports in five scopes (`src`, `src-js`, `resources`, `package/src`, `tests`); `tests/asserts.ts`; lands first | none | Sonnet | S | merged |
203207
| 02c | [02c-ratchet-pr-delta-and-guidance.md](02c-ratchet-pr-delta-and-guidance.md) | PR runs compare with the base branch; findings name a working replacement or ask the maintainer to accept; `--accept-increase` | 02 | Sonnet | S | merged |
204-
| 02d | [02d-ratchet-counts-indirect-deno.md](02d-ratchet-counts-indirect-deno.md) | The ratchet also counts `Deno?.x`, `globalThis["Deno"]` and a bare `globalThis.Deno` | 02c | Sonnet | S | in progress |
205-
| 00a | [00a-deno-bump.md](00a-deno-bump.md) | Deno 2.7.14 → newest 2.9.x everywhere the version appears | 02 | Sonnet | S | planned |
208+
| 02d | [02d-ratchet-counts-indirect-deno.md](02d-ratchet-counts-indirect-deno.md) | The ratchet also counts `Deno?.x`, `globalThis["Deno"]` and a bare `globalThis.Deno` | 02c | Sonnet | S | merged |
209+
| 00a | [00a-deno-bump.md](00a-deno-bump.md) | Deno 2.7.14 → newest 2.9.x everywhere the version appears | 02 | Sonnet | S | in progress |
206210
| 00b | [00b-lockfile-and-bundle-gate.md](00b-lockfile-and-bundle-gate.md) | Committed `deno.lock` with `--frozen` (six entrypoints); `tools/check-test-imports.ts` keeps the unlocked tests inside that graph; three-OS bundle gate (cold cache, external-specifier grep, five renders) | 02, 00a | Opus | M | planned |
207211
| 00c | [00c-quarto-run-deprecation-notice.md](00c-quarto-run-deprecation-notice.md) | One-time notice when `quarto run` or a pre/post-render `.ts` script runs on Deno; `QUARTO_RUN_DENO_NOTICE=0` | 02 | Sonnet | S | planned |
208-
| 01 | [01-quick-fixes-from-spike.md](01-quick-fixes-from-spike.md) | `assert`→`with` on two JSON imports; deterministic bslib Sass ordering | 02 | Sonnet | S | planned |
212+
| 01 | [01-quick-fixes-from-spike.md](01-quick-fixes-from-spike.md) | Deterministic bslib Sass ordering (the `assert`→`with` half landed with 00a) | 02 | Sonnet | S | planned |
209213
| 03 | [03-deps-skypack-to-npm.md](03-deps-skypack-to-npm.md) | Replace every `cdn.skypack.dev` import-map entry with `npm:`; CommonJS bundling proof | 02, 00b | Sonnet | M | planned |
210214
| 04 | [04-deps-deno-land-x-small.md](04-deps-deno-land-x-small.md) | Replace semver, media_types, xmlp, xml, cache, events; cookie jar on tough-cookie | 02, 00b | Opus | M | planned |
211215
| 05 | [05-deps-deno-dom-jsr.md](05-deps-deno-dom-jsr.md) | deno_dom from `deno.land/x` to `jsr:@b-fuze/deno-dom` 0.1.56; `parseHtml` timing baseline on the native plugin | 02, 00b | Opus | M | planned |

‎dev-docs/upgrade-dependencies.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Change version numbers in `./configuration` to correspond to new versions.
22

3-
Update hardcoded version strings in `src/command/check/check.ts` (`versionConstraints` array, ~line 249) so that they match the new versions in `configuration`. The `configuration` file warns about this in a comment.
3+
Update hardcoded version strings in `src/command/check/check.ts` (the `versionConstraints` array in `checkVersions`) so that they match the new versions in `configuration`. The `configuration` file warns about this in a comment, and `tests/smoke/check/check-versions-no-mismatch.test.ts` fails until they match.
44

55
## Verify installer signing & notarization before merging (bundled binaries)
66

‎news/changelog-1.11.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ All changes included in 1.11:
1414
## Dependencies
1515

1616
- ([#15043](https://github.com/quarto-dev/quarto-cli/issues/15043)): Update the OJS runtime to acorn 8.17, Observable Inspector 5.0.1, and Observable Inputs 0.10.6. `FileAttachment(...).mimeType` now reports `text/javascript` instead of `application/javascript` for `.js` and `.mjs` files.
17+
- ([#15152](https://github.com/quarto-dev/quarto-cli/issues/15152)): Update `deno` to v2.9.8 to stop trusting the compromised eMudhra / emSign certificate authorities, whose exposed private keys allow network attackers to impersonate HTTPS sites, protecting HTTPS requests made by Quarto commands and TypeScript scripts from these attacks.
1718

1819
## Accessibility
1920

@@ -204,5 +205,6 @@ All changes included in 1.11:
204205
- ([#15126](https://github.com/quarto-dev/quarto-cli/issues/15126)): Translate the `revealjs-menu-button-label` language key in French. (author: @D3ller)
205206
- ([#15126](https://github.com/quarto-dev/quarto-cli/issues/15126)): Translate the `revealjs-menu-button-label` language key in Greek. (author: @sogav21)
206207
- ([#15140](https://github.com/quarto-dev/quarto-cli/pull/15140)): Add support for definition lists written as a `definition-list` div holding a nested bullet list, the definition list syntax of Quarto 2.
208+
- ([#15157](https://github.com/quarto-dev/quarto-cli/issues/15157)): Fix `quarto preview` and other commands sometimes starting a local server on port 4190, which browsers refuse to connect to.
207209
- ([#15180](https://github.com/quarto-dev/quarto-cli/pull/15180)): Fix older Quarto versions failing to render with `RangeError: could not deserialize value` once a Quarto built on a newer Deno has used the same cache. Also fix a project cache that already has entries failing to clear with `Path must be a string`.
208210
- ([#15198](https://github.com/quarto-dev/quarto-cli/issues/15198)): Fix `quarto add`, `quarto use template`, `quarto use brand` and `quarto install tinytex` failing to unzip on Windows when a Group Policy blocks running `.bat` files from the temporary folder, and when a path contains an apostrophe.

‎package/scripts/vendoring/vendor.cmd‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ IF EXIST "!DENO_DIR!" (
2929
PUSHD "!QUARTO_SRC_PATH!"
3030

3131
FOR %%E IN (quarto.ts vendor_deps.ts ..\tests\test-deps.ts ..\package\scripts\deno_std\deno_std.ts) DO (
32-
CALL !DENO_BIN_PATH! install --allow-all --no-config --entrypoint %%E --importmap="!QUARTO_SRC_PATH!\import_map.json" || (
32+
CALL !DENO_BIN_PATH! install --allow-import --no-config --entrypoint %%E --importmap="!QUARTO_SRC_PATH!\import_map.json" || (
3333
ECHO Warning: Failed to vendor %%E, continuing...
3434
)
3535
)

‎package/scripts/vendoring/vendor.sh‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ fi
2424
pushd "${QUARTO_SRC_PATH}"
2525
set +e
2626
for entrypoint in quarto.ts vendor_deps.ts ../tests/test-deps.ts ../package/scripts/deno_std/deno_std.ts; do
27-
$DENO_BIN_PATH install --allow-all --no-config --entrypoint $entrypoint "--importmap=$QUARTO_SRC_PATH/import_map.json"
27+
$DENO_BIN_PATH install --allow-import --no-config --entrypoint $entrypoint "--importmap=$QUARTO_SRC_PATH/import_map.json"
2828
done
2929
set -e
3030
popd

‎src/command/check/check.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ async function checkVersions(conf: CheckConfiguration) {
302302
const versionConstraints: [string | undefined, string, string][] = [
303303
[pandocVersion, "3.10.0", "Pandoc"],
304304
[sassVersion, "1.101.0", "Dart Sass"],
305-
[denoVersion, "2.7.14", "Deno"],
305+
[denoVersion, "2.9.8", "Deno"],
306306
[typstVersion, "0.15.1", "Typst"],
307307
];
308308
const checkData: [string | undefined, string, string][] = versionConstraints

‎src/core/lib/yaml-intelligence/parsing.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export async function getTreeSitter(): Promise<any> {
5656

5757
const treeSitterYamlJson = (await import(
5858
"../../../resources/editor/tools/yaml/tree-sitter-yaml.json",
59-
{ assert: { type: "json" } }
59+
{ with: { type: "json" } }
6060
)).default as { data: number[] };
6161

6262
const YAML = await Parser.Language.load(

‎src/core/lib/yaml-intelligence/yaml-intelligence.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1208,7 +1208,7 @@ async function init(
12081208
const ideInit = async () => {
12091209
const resourceModule = (await import(
12101210
"../../../resources/editor/tools/yaml/yaml-intelligence-resources.json",
1211-
{ assert: { type: "json" } }
1211+
{ with: { type: "json" } }
12121212
)).default as Record<string, unknown>;
12131213

12141214
await getTreeSitter();

0 commit comments

Comments
 (0)