Skip to content

fix: support QBT_SID_<port> session cookie in network agent proxy#89

Open
lucasliet wants to merge 1 commit into
mkbula:masterfrom
lucasliet:master
Open

fix: support QBT_SID_<port> session cookie in network agent proxy#89
lucasliet wants to merge 1 commit into
mkbula:masterfrom
lucasliet:master

Conversation

@lucasliet

Copy link
Copy Markdown

Problem

The Network Agent proxy fails against qBittorrent 5.2.x. Every agent request is rejected with:

{"error":"missing SID"}

Root cause

qBittorrent 5.2.x changed the session cookie name from SID to QBT_SID_<port> (e.g. QBT_SID_8081):

Set-Cookie: QBT_SID_8081=<token>; Path=/; HttpOnly

But src/server/routes/proxy.ts extracts the token assuming the cookie is named exactly SID:

const sid = cookie?.match(/SID=([^;]+)/)?.[1] || ''

For QBT_SID_8081=<token> this yields '', so the agent receives X-QBT-SID: (empty) and replies missing SID.

The login/cookie flow in src/server/utils/qbt.ts is correct — only the token extraction before calling the agent is wrong.

Fix

Replace the regex with a helper that selects the cookie whose name contains SID and returns its value:

export function extractQbtSessionToken(cookie: string | null | undefined): string {
	if (!cookie) return ''

	const sessionCookie = cookie
		.split(';')
		.map((part) => part.trim())
		.find((part) => {
			const equalsIndex = part.indexOf('=')
			return equalsIndex > 0 && part.slice(0, equalsIndex).includes('SID')
		})

	const equalsIndex = sessionCookie?.indexOf('=') ?? -1
	if (equalsIndex < 0) return ''

	return sessionCookie!.slice(equalsIndex + 1)
}

Compatibility

The agent only needs the session value (sent as X-QBT-SID), not the cookie name, so accepting any *SID*-named cookie is correct. Verified against:

Cookie Result
SID=abc (legacy, < 5.2) abc
QBT_SID_8081=abc (5.2.x) abc
QBT_SID_443=abc abc
QBT_SID_12345=abc abc
theme=dark (no SID) '' (rejected)
theme=dark; SID=abc (multi-cookie) abc
  • The name check is case-sensitive (includes('SID')) on purpose: qBittorrent always emits uppercase SID, and case-insensitive matching would false-positive on names like resident.
  • Uses indexOf('=') + slice instead of split('=', 2) so values containing = (e.g. base64 padding) are preserved.

Testing

Added __tests__/server/proxy.test.ts (16 cases). Full suite passes (356/356), tsc --noEmit and eslint clean.

Verified with qBittorrent v5.2.2 returning Set-Cookie: QBT_SID_8081=<token>.

qBittorrent 5.2.x returns 'Set-Cookie: QBT_SID_<port>=<token>' instead of
'SID=<token>'. The agent proxy extracted the token via /SID=([^;]+)/, which
yielded an empty string for the new cookie name, so the agent rejected
every request with {"error":"missing SID"}.

Replace the regex with extractQbtSessionToken, which selects the cookie
whose name contains SID and returns its value. Works for SID (legacy) and
QBT_SID_<port> (5.2.x). Adds unit tests covering both formats, multi-cookie
strings, values containing '=', and invalid inputs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant