Summary
Unauthenticated websocket can subscribe to the log path and receive buffered server logs
(Narrowed after maintainer feedback: opening the socket unauthenticated is intended, since login
happens over ws. This is only about what an unauthenticated socket can then subscribe to.)
processSubscribe special-cases the log path and applies no access control to it:
if (
Array.isArray(msg.subscribe) &&
msg.subscribe.length > 0 &&
msg.subscribe[0].path === 'log'
) {
if (!spark.logUnsubscribe) {
spark.logUnsubscribe = startServerLog(app, spark)
}
} else {
// normal subscriptions go through subscriptionmanager, which applies
// securityStrategy.filterReadDelta
}
startServerLog then replays the whole buffer to that socket:
app.logging.getLog().forEach((log) => {
spark.write({ type: 'LOG', data: log })
})
The asymmetry is inside this one file. Writes are gated by securityStrategy.shouldAllowWrite
(ws.ts:961), normal delta subscriptions are filtered by securityStrategy.filterReadDelta
(ws.ts:1159, the else branch of this same function), and the log branch consults neither.
So an unauthenticated socket, which is legitimately open for login, can subscribe to log and receive
buffered server logs.
Fix: require a principal, and an admin one, before startServerLog, in the same way the other branch
defers to securityStrategy.
Confirmed on 26ab199. I used AI assistance while investigating; I read the subscribe path and the log
replay but did not run a server and capture the frames.
Summary
Unauthenticated websocket can subscribe to the log path and receive buffered server logs
(Narrowed after maintainer feedback: opening the socket unauthenticated is intended, since login
happens over ws. This is only about what an unauthenticated socket can then subscribe to.)
processSubscribespecial-cases thelogpath and applies no access control to it:startServerLogthen replays the whole buffer to that socket:The asymmetry is inside this one file. Writes are gated by
securityStrategy.shouldAllowWrite(
ws.ts:961), normal delta subscriptions are filtered bysecurityStrategy.filterReadDelta(
ws.ts:1159, the else branch of this same function), and the log branch consults neither.So an unauthenticated socket, which is legitimately open for login, can subscribe to
logand receivebuffered server logs.
Fix: require a principal, and an admin one, before
startServerLog, in the same way the other branchdefers to
securityStrategy.Confirmed on 26ab199. I used AI assistance while investigating; I read the subscribe path and the log
replay but did not run a server and capture the frames.