fix(sharing): re-sanitize remote payloads on receipt

A peer might run an older build that does not strip its own project
names/sessions. Sanitize every remote payload when we receive it too, so
project names never cross into our dashboard regardless of the sender's
version. Aggregate numbers (cost, tokens, models, tools, daily) are kept.
This commit is contained in:
AgentSeal 2026-06-20 18:21:14 +02:00
parent 42ea828c13
commit 3c910dd64b

View file

@ -1,9 +1,11 @@
import { hello, pair, pairRequest, fetchUsage } from './client.js'
import { loadOrCreateIdentity } from './identity.js'
import { pairingCode } from './pairing.js'
import { sanitizeForSharing } from './sanitize.js'
import type { DiscoveredDevice } from './discovery.js'
import type { UsageQuery } from './share-server.js'
import { getSharingDir, loadRemotes, saveRemotes, type RemoteDevice } from './store.js'
import type { MenubarPayload } from '../menubar-json.js'
import { formatCost } from '../currency.js'
import { formatTokens } from '../format.js'
@ -96,7 +98,10 @@ export async function pullDevices(
remotes.map(async (r): Promise<DeviceUsage> => {
try {
const res = await fetchUsage({ identity, host: r.host, port: r.port, expectedFingerprint: r.fingerprint }, r.token, query)
if (res.status === 200) return { name: r.name, local: false, payload: res.json as DevicePayload }
// Re-sanitize on receipt: do not trust the sender to have stripped its
// own project names/sessions (it may run an older build). Belt and
// suspenders alongside the sender-side sanitize.
if (res.status === 200) return { name: r.name, local: false, payload: sanitizeForSharing(res.json as MenubarPayload) }
return { name: r.name, local: false, error: res.status === 401 ? 'not authorized (re-pair?)' : `HTTP ${res.status}` }
} catch (e) {
return { name: r.name, local: false, error: e instanceof Error ? e.message : String(e) }