security(main): dialog-grant admission for local paths, explicit webPreferences
New localPathGrants.ts: an in-memory registry of paths the user picked in a native dialog. Every check resolves realpath + stat at grant and use time; Windows case folding; missing files, directories-as-files, devices and symlinked parents can never pass. SFTP upload/download and zmodem send/ receive now refuse renderer-supplied local paths that were never granted, returning the resolved path so callers never re-traverse a symlink. keyPath is validated as a regular file <= 1MB before reading (a device node would have blocked the UI thread forever). Tests inject a stub policy via setLocalPathPolicy; production always defaults to the real registry. Also: webPreferences now explicitly pins contextIsolation/nodeIntegration/ webSecurity instead of relying on defaults. New offline test tests/local-path-grants.mjs (37 assertions incl. symlink escape); offline suite grows to 13. i18n: 6 main.sftp/main.key error keys in 4 languages.
This commit is contained in:
1 parent
9c75cdc7d4
commit
d22923aedd
14 files changed
+612
-18
No files matched your search
@@ -5,11 +5,29 @@
|
||||
import { createRequire } from 'module'
|
||||
import { randomUUID } from 'crypto'
|
||||
import { promises as fsp } from 'fs'
|
||||
import { join } from 'path'
|
||||
const require_ = createRequire(import.meta.url)
|
||||
const sessionLayer = require_('./.session-e2e.cjs')
|
||||
const sftpMod = await import('./.sftp-svc.mjs')
|
||||
sftpMod.registerSftpClientProvider((id) => sessionLayer.getSshClient(id))
|
||||
|
||||
/**
|
||||
* Local-path admission. In the app the default policy only accepts paths the
|
||||
* user granted through a native dialog (localPathGrants.ts); this harness picks
|
||||
* its own temp paths and has no dialog to grant from, so it supplies a
|
||||
* permissive double. It is NOT a re-export of the real policy — the admission
|
||||
* rules have their own test (tests/local-path-grants.mjs) and these scenarios
|
||||
* stay about transfer mechanics.
|
||||
*/
|
||||
sftpMod.setLocalPathPolicy({
|
||||
readSource: (p) => (typeof p === 'string' ? p : null),
|
||||
readDirectory: (d) => (typeof d === 'string' && d !== '' ? d : null),
|
||||
writeTarget: (dir, name) =>
|
||||
typeof dir === 'string' && dir !== '' && typeof name === 'string' && name !== ''
|
||||
? join(dir, name)
|
||||
: null
|
||||
})
|
||||
|
||||
const events = []
|
||||
sessionLayer.configureSessionRuntime({
|
||||
broadcast: (channel, payload) => events.push({ channel, payload }),
|
||||
|
||||
Reference in new issue
Block a user