Repository navigation
feat(plugins): disclose Developer Mode settings changed outside Navide and ask again (A2-5) - #537
Open
nt-nerdtechnic wants to merge 6 commits into
Open
nt-nerdtechnic wants to merge 6 commits into
nt-nerdtechnic wants to merge 6 commits into
Conversation
…e and ask again DESIGN-A2 slice A2-5 (gap G5). The Developer Mode settings file is unsigned, so any unsandboxed process of the user (an agent CLI included) could turn the switch on and add a "consented" folder that the next start loaded without the consent dialog and without an activity log entry. - Navide keeps an HMAC-SHA256 of each entry it writes itself (the switch when on, each folder consent) in its own file, .navide-plugin-developer-mode.sig.json; the key is random and wrapped by Electron safeStorage. The store file keeps its 0.2.27 shape (downgrade-safe). - An entry Navide did not write is not applied: the switch reads as off until the user turns it on in Settings (with the usual confirmation), and the folder is listed as "Added or edited outside Navide; consent again" and loads only after the user consents again (Reload opens the consent dialog). Nothing is blocked; the other program's write is just not the user's consent. - Disclosed in the launch reminder and on the Navide Plugins page, and as one Host activity event developerMode.externalChange (backend allowlist updated). - No crypto is touched while Developer Mode was never used; nothing is checked without secure storage or before the app is ready. The startup load of developer folders now waits for app ready so it is checked. A file from before 0.2.28 is signed once as it is. Limits are documented. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ernal-change # Conflicts: # src/main/index.ts
…s an outside on Review of #537: - MED-2: an encrypt/decrypt or signature-file failure never leaves isEnabled() or folders(). Navide's own write is still written, unsigned, so it reads as "ask again" with its own notice (reason signing-unavailable, shown in the launch reminder and on the Navide Plugins page). - LOW-2: turning Developer Mode off writes over a switch another program turned on, so that entry and its notice go. - LOW-3: covered by a test that the two stores the app keeps report an outside change once. - MED-1 / LOW-1: replay of an older copy of both files, the pre-ready window and Linux basic_text are disclosed in plugin-development-v2.md. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…f trusting Review HIGH-1 on #537, option (a): with no signature file, every entry of a non-empty settings file was signed as Navide's own, so deleting .navide-plugin-developer-mode.sig.json made any outside edit trusted. Now a missing signature means every entry is asked about again once (switch reads as off, each folder needs consent) with its own notice (reason signature-missing). Cost: a 0.2.27 Developer Mode user consents once per folder after upgrading. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…disclosed and asked again en-US, zh-TW, ja-JP: replace "unsigned file, changes are not recorded" with the behaviour after #537 and HIGH-1 (a), including the one-time re-consent after upgrading or when the signature file is missing. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ce after upgrading Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
nt-nerdtechnic
marked this pull request as ready for review
October 20, 2026 22:52
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
DESIGN-A2 slice A2-5 (gap G5) — security-related, needs its own independent review.
The Developer Mode settings file (
.navide-plugin-developer-mode.json) is unsigned: any unsandboxed process of the user, an agent CLI included, could turn the switch on and add a "consented" developer folder, which the next start loaded without the consent dialog and without an activity log entry..navide-plugin-developer-mode.sig.json. The key is 32 random bytes wrapped by ElectronsafeStorage. The store file keeps its 0.2.27 shape (downgrade-safe; 0.2.27 ignores the new file).assertNoDeveloperFolder/assertFolderIdFreeuseanyFolder), and turning Developer Mode off unloads it too if it was loaded in this session.DeveloperModeReminder) and arole="alert"banner on the Navide Plugins page with the detection time; one Host activity eventdeveloperMode.externalChangethe first time it is seen (backend_HOST_EVENT_ADDRESSESupdated).Known limits (documented in plugin-development-v2.md)
appis ready and while secure storage is available. The startup load of developer folders therefore moved intoapp.whenReady(); the pre-ready self-hosted Registry override read (index.tstop level) is not checked (it also needs env vars in Navide's own environment). Linux without a keyring: no check.A pre-0.2.28 file is signed once as it is→ HIGH-1 (a), user decision 01:44: a missing signature file with a non-empty settings file is fail-closed: the switch reads as off and every folder asks again once (notice reasonsignature-missing). 0.2.27 Developer Mode users re-consent each local folder once after upgrading (CHANGELOG, user guide en-US/zh-TW/ja-JP).isEnabled()/folders(); the user's write is still written, unsigned, reads as "ask again" and is disclosed (reasonsigning-unavailable).Review round 1 fixes (7b976fa, 6128e04, d47a324, 143d053)
pluginIpc.developerMode.test.ts+ store 42/42;pluginIpc.developerMode+DeveloperMode.test.ts33/33;pnpm typecheckexit 0 (on 7b976fa's code).Why
Approved DESIGN-A2 §2.5, Approval (b) "G5 要做".
Test plan (red → green)
src/main/plugins/pluginDeveloperModeStore.integrity.test.ts(new, 9 tests): 9/9 red before the store change, 9/9 green after.src/main/plugins/pluginIpc.developerMode.test.tsnew describe (3 tests): with main'spluginIpc.tsswapped in, 2 red / 1 green (the third is a regression guard that also passes on main); with the branch, green.pnpm vitest run src/main/plugins/pluginIpc.developerMode.test.ts src/main/plugins/pluginDeveloperModeStore.integrity.test.ts --maxWorkers 1→ 38 passed (38) (all 26 existing developer-mode tests unchanged and green). Run before merging origin/main (fix(plugins): activate a first install staged without Restart on the next launch #505).DeveloperMode.test.ts,ExtensionsPane.test.ts(new tests added),backend/tests/test_plugin_activity_host_event.py(new case), typecheck, and the full suites. Will run them locally once load < 60 and report any difference from CI.Regression: existing plugins
Pending local run (load); CI runs the full frontend and backend suites. Behaviour with Developer Mode never used: no new file read beyond the store, no crypto, identical state shape (
externalChange/externallyChangedare only added when present, sotoEqual({ enabled: false, folders: [] })still holds).Protection check
git diff $(git merge-base HEAD origin/main) HEAD -- backend/agent_team_backend/credential_*.py quota_*.py usage_*.py→ empty. No account-switching code touched. The HMAC key is a new file under the plugins root, not a CLI credential.PluginDeveloperModeStoreconstructor gains optionalintegrity; privatewritegains optionalevaluated/decision;registerPluginIpcoptions gain optionaldeveloperModeIntegrity;HostEventAddressgains'developerMode.externalChange'; newFrontendPluginManager.recordDeveloperModeExternalChange. New store methods:untrustedFolders,anyFolder,externalChange.src/main/index.tsresolved keeping both — developer folders load atapp.whenReady(), fix(plugins): activate a first install staged without Restart on the next launch #505's staged first-install activation unchanged.Overlaps with A2-1/A2-2/A2-4 in
pluginIpc.ts(developerModeState,setDeveloperMode(false),reloadDeveloperPlugin); whichever lands second merges main normally.🤖 Generated with Claude Code