You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: correct three claims the code stopped supporting
The security threat model called the extension host a sandbox in three
places, while the root `SECURITY.md` says the opposite in as many words:
it is a fault boundary, not a security one, and an extension reaches
app-private storage and the network exactly as the app does. A threat
model that asserts a boundary the project says does not exist is the
direction that gets a reader to under-protect, so the three rows now
name what actually bounds an extension, the Android app sandbox and the
SAF grants the user gave.
The landing page was the last surface quoting 875 MB and promising a
one-time unpack. Both were corrected everywhere else; the page a
prospective user reads first kept them. It now says 873 MB, which is
what the storage gate asks for, and that extraction repeats after an
update.
Four comments in `FirstRunSetup.kt` still said setup is keyed on
versionName alone. It is keyed on versionName or versionCode, and the
difference is expensive: a versionCode bump on its own re-runs the whole
extraction, which a reader trusting these comments would conclude it
does not.
Two rows of the release plan described `r8.yml` as cron or dispatch
only. It also runs on pushes to main and on pull requests, filtered to
the files that configure the shrinkers, which is why a Kotlin-only
change still waits for the cron.
One line in MILESTONES.md blamed a noexec mount for npm being a bash
function. It is SELinux denying execute_no_trans under filesDir, and the
distinction is load-bearing: a noexec mount would also block the .node
addons loaded from the same directory.
Swept the tree rather than the files a report named. Two candidates were
checked and left alone: the file-tree annotations in the implementation
plan describe what `ToolchainActivity.kt` is, which is accurate, and the
remaining noexec mentions are inside dated records.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
13
13
14
14
### Changed
15
15
16
+
- The security document no longer calls the extension host a sandbox. It is a fault boundary, and an extension reaches app-private storage exactly as the app does.
17
+
- The landing page quotes the storage figure the app computes and says extraction repeats after an update, which every other document already said.
16
18
- The design documents now describe the build that ships: two on-demand toolchains, terminals that spawn bash on a real PTY, and how the server is actually patched and built.
17
19
- Seven documents named a "Settings > Toolchains" screen the app has never had. They now name the real route, the launcher icon's **Manage toolchains** shortcut.
18
20
- Three documents no longer list file-type "Open with" intent filters as shipped. A `content://` URI has no POSIX path, so every save would reach a copy.
-[x] npm/npx defined as bash functions in `.bashrc` (not script wrappers — Android noexec restriction)
284
+
-[x] npm/npx defined as bash functions in `.bashrc` (not script wrappers; SELinux denies `execute_no_trans` under `filesDir`, while `dlopen` of a `.node` addon there still works)
285
285
-[x] Functions invoke Node.js with `npm-cli.js` entry point from `usr/lib/node_modules/npm/`
286
286
-[x]`.npmrc` created with `script-shell` pointing to `libbash.so`
| Other app connects to localhost server |**Spoofing**| Medium | Low | localhost-only binding, plus a connection token required on all but three routes |
47
47
| Malicious extension impersonates trusted extension |**Spoofing**| Medium | Low | Open VSX publisher verification, user review |
48
-
| Malicious extension steals files |**Tampering**| High | Medium |Extension sandbox (Extension Host only), user awareness |
48
+
| Malicious extension steals files |**Tampering**| High | Medium |**Not mitigated.** The extension host is a fault boundary, not a security one: an extension reaches app-private storage and the network exactly as the app does. What bounds it is the Android app sandbox and the SAF grants the user gave|
49
49
| Man-in-middle on Open VSX downloads |**Tampering**| High | Low | HTTPS only, certificate pinning (future) |
50
50
| No audit trail for file changes by extensions |**Repudiation**| Low | Medium | VS Code timeline/git history, extension activity logging (future) |
51
51
| User denies executing destructive terminal command |**Repudiation**| Low | Low | Accepted, no audit trail. Each terminal spawns bash directly on a PTY through node-pty, and the only record is bash's own history file in app-private storage, which the user can edit or clear |
@@ -55,7 +55,7 @@ flowchart TD
55
55
| Malicious extension consuming all memory/CPU |**Denial of Service**| Medium | Low | Extension Host resource limits, idle-kill for LS |
56
56
| WebView XSS via malicious file content |**Elevation of Privilege**| Medium | Low | VS Code CSP, WebView sandboxing |
57
57
| Extension/webview script abuses AndroidBridge methods |**Elevation of Privilege**| High | Medium | Per-session capability token on every bridge method, pinned by a reflection test |
58
-
| Extension escapes sandbox to access system files|**Elevation of Privilege**| High | Low | Android app sandbox, Extension Host isolation (a worker_thread inside the server process)|
58
+
| Extension reads files outside the app |**Elevation of Privilege**| High | Low | Android app sandbox, and SAF grants for anything outside it. The worker_thread the extension host runs in is not part of this: it exists so the host does not spend a phantom process slot|
| Extension Host isolation | Runs as a worker_thread inside the server process, applied by `patches/0004-exthost-as-worker-thread.patch`, so it does not spend one of Android's 32 phantom process slots |
91
-
|VS Code Extension API sandbox | Extensions can only access vscode.\* APIs|
91
+
| Extension reach |**No sandbox.** The extension host is Node, so an extension can `require('fs')` and reach whatever the app can. The `vscode.*` API is a convenience, not a boundary|
92
92
| AndroidBridge capability model | All bridge APIs require the valid per-session token; no origin component |
93
93
| File system scoping | Extensions see workspace folder by default |
94
94
| Open VSX moderation | Open VSX has publisher verification and abuse reporting |
| `patch-drift.yml` | Monday 04:00 UTC, or dispatched with a tag | Applies `patches/` against an upstream VS Code tag with `git apply --check` | Rebase the patch set before the next version bump |
104
-
| `r8.yml` | Monday 03:00 UTC, or dispatched | Runs R8, the resource shrinker and `lintVitalRelease`, so a dependency that arrives without its consumer rules is caught before a tag | Fix the keep rules, or the shrinker configuration, before tagging |
104
+
| `r8.yml` | Monday 03:00 UTC, pushes to main, pull requests, or dispatched. The three event triggers are filtered to the files that configure the shrinkers, so a change to Kotlin alone still waits for the cron | Runs R8, the resource shrinker and `lintVitalRelease`, so a dependency that arrives without its consumer rules is caught before a tag | Fix the keep rules, or the shrinker configuration, before tagging |
0 commit comments