Prevent authentication service capability downgrades
Co-Authored-By: GPT-5.6-Sol <noreply@openai.com>
This commit is contained in:
1 parent
203e1639c3
commit
f2b4731bb3
5 files changed
+40
-7
No files matched your search
@@ -4,6 +4,7 @@
|
||||
// a separate empty store rather than a shared path to credential-bearing QML.
|
||||
|
||||
var services = ({})
|
||||
var trustedIds = ({})
|
||||
|
||||
function has(id) {
|
||||
return services[String(id || "")] !== undefined
|
||||
@@ -12,11 +13,16 @@ function has(id) {
|
||||
function put(id, service) {
|
||||
var key = String(id || "")
|
||||
if (!key || !service) return
|
||||
trustedIds[key] = true
|
||||
if (services[key] && services[key] !== service && typeof services[key].destroy === "function")
|
||||
services[key].destroy()
|
||||
services[key] = service
|
||||
}
|
||||
|
||||
function isTrusted(id) {
|
||||
return trustedIds[String(id || "")] === true
|
||||
}
|
||||
|
||||
function ids() {
|
||||
return Object.keys(services)
|
||||
}
|
||||
|
||||
+9
-7
@@ -375,7 +375,7 @@ ShellRoot {
|
||||
if (!shell.pluginHasBarCapabilities(manifest)) return false
|
||||
var id = shell.pluginRegistry.resolveEnabledId(String(requestedId || ""))
|
||||
var target = shell.pluginRegistry.installedPlugins[id]
|
||||
if (!target || shell.isAuthenticationService(target)) return false
|
||||
if (!target || shell.isAuthenticationService(target, id)) return false
|
||||
if (shell.barEntryConfigured(id)) return true
|
||||
var uiKinds = ["bar-widget", "panel", "overlay", "menu"]
|
||||
for (var i = 0; i < uiKinds.length; i++)
|
||||
@@ -842,9 +842,11 @@ ShellRoot {
|
||||
return serviceFor(shell.pluginRegistry.resolveEnabledId(pluginId))
|
||||
}
|
||||
|
||||
function isAuthenticationService(manifest) {
|
||||
return !!manifest && Array.isArray(manifest.__hostCapabilities)
|
||||
&& manifest.__hostCapabilities.indexOf("authentication") !== -1
|
||||
function isAuthenticationService(manifest, pluginId) {
|
||||
var key = String(pluginId || (manifest && manifest.id) || "")
|
||||
return AuthServiceStore.isTrusted(key)
|
||||
|| (!!manifest && Array.isArray(manifest.__hostCapabilities)
|
||||
&& manifest.__hostCapabilities.indexOf("authentication") !== -1)
|
||||
}
|
||||
|
||||
function ensureService(pluginId) {
|
||||
@@ -857,7 +859,7 @@ ShellRoot {
|
||||
if (!manifest.entryPoints || !manifest.entryPoints.service) return null
|
||||
var url = pluginRegistry.entryPointUrl(manifest, "service")
|
||||
if (!url) return null
|
||||
var authenticationService = shell.isAuthenticationService(manifest)
|
||||
var authenticationService = shell.isAuthenticationService(manifest, key)
|
||||
if (authenticationService && AuthServiceStore.has(key)) return null
|
||||
|
||||
var comp = Qt.createComponent(url, Component.PreferSynchronous)
|
||||
@@ -908,7 +910,7 @@ ShellRoot {
|
||||
if (!Array.isArray(m.kinds) || m.kinds.indexOf("service") === -1) continue
|
||||
if (!m.entryPoints || !m.entryPoints.service) continue
|
||||
if (!pluginRegistry.isEnabled(id)) continue
|
||||
var authenticationService = shell.isAuthenticationService(m)
|
||||
var authenticationService = shell.isAuthenticationService(m, id)
|
||||
if (_services[id]) {
|
||||
if (authenticationService) {
|
||||
// A service that gains a trusted authentication capability must move
|
||||
@@ -965,7 +967,7 @@ ShellRoot {
|
||||
&& authenticationManifest.entryPoints
|
||||
&& authenticationManifest.entryPoints.service
|
||||
if (stillAuthenticationService && pluginRegistry.isEnabled(authenticationId)
|
||||
&& shell.isAuthenticationService(authenticationManifest)) continue
|
||||
&& shell.isAuthenticationService(authenticationManifest, authenticationId)) continue
|
||||
AuthServiceStore.destroy(authenticationId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,10 @@ QtObject {
|
||||
return AuthServiceStore.has(id)
|
||||
}
|
||||
|
||||
function isTrusted(id) {
|
||||
return AuthServiceStore.isTrusted(id)
|
||||
}
|
||||
|
||||
function updateManifest(id, manifest) {
|
||||
AuthServiceStore.updateManifest(id, manifest)
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ ShellRoot {
|
||||
ownSettings: api.updateEntryInline(caller, {}) === true,
|
||||
foreignSettings: api.updateEntryInline("omarchy.lock", {}) === false,
|
||||
authStoreOwnerRetains: authStoreOwner.has("omarchy.lock") === true,
|
||||
authStoreOwnerRemembersTrust: authStoreOwner.isTrusted("omarchy.lock") === true,
|
||||
authStoreOwnerUpdatesManifest: root.ownService.manifest
|
||||
&& root.ownService.manifest.version === "kept",
|
||||
authStoreImportIsolated: authStoreReader.has("omarchy.lock") === false,
|
||||
|
||||
@@ -37,12 +37,32 @@ qml_matches "$shell_qml" 'comp\.createObject\( *manifest\.__isFirstParty *&& *!a
|
||||
fail "third-party and authentication services are detached from the host object tree"
|
||||
qml_matches "$shell_qml" 'AuthServiceStore\.put\( *key, *inst *\)' ||
|
||||
fail "authentication services are retained outside the host service map"
|
||||
qml_matches "$shell_qml" 'AuthServiceStore\.isTrusted\( *key *\)' ||
|
||||
fail "live authentication classification survives public manifest mutation"
|
||||
qml_matches "$shell_qml" 'AuthServiceStore\.updateManifest\( *id, *shell\.publicPluginManifest\( *m *\) *\)' ||
|
||||
fail "kept authentication services receive only a public manifest snapshot"
|
||||
qml_matches "$shell_qml" 'if *\( *!serviceKeepLoaded\( *authenticationId *\) *\) *AuthServiceStore\.destroy\( *authenticationId *\)' ||
|
||||
fail "keepLoaded authentication services survive plugin rescans"
|
||||
pass "third-party and authentication services are detached from the host object tree"
|
||||
|
||||
run_node_test <<'JS'
|
||||
const fs = require('fs')
|
||||
const vm = require('vm')
|
||||
const store = {}
|
||||
vm.createContext(store)
|
||||
vm.runInContext(
|
||||
fs.readFileSync(path.join(root, 'shell/services/AuthServiceStore.js'), 'utf8'),
|
||||
store
|
||||
)
|
||||
const service = { destroy() {} }
|
||||
store.put('omarchy.lock', service)
|
||||
store.destroy('omarchy.lock')
|
||||
assert(
|
||||
!store.has('omarchy.lock') && store.isTrusted('omarchy.lock'),
|
||||
'authentication classification survives service teardown'
|
||||
)
|
||||
JS
|
||||
|
||||
qml_matches "$shell_qml" 'inst\.shell *= *shell\.pluginShellFor\( *manifest *\)' ||
|
||||
fail "service plugins receive a scoped shell facade"
|
||||
qml_matches "$shell_qml" 'item\.shell *= *shell\.pluginShellFor\( *panelEntry\.manifest *\)' ||
|
||||
|
||||
Reference in new issue
Block a user