Bug Description
Using this with ollama in local mode works as intended. In proxy mode there is a bug in middleware.ts that removes the first 7 characters of the authorization header before using it in verifySignature. That is probably intended to remove a leading "Bearer ", but that is not present in the actual header.
I propose to replace authorization.substring(7) with authorization.startsWith("Bearer ") ? authorization.substring(7) : authorization.
In context:
if (request.nextUrl.pathname.startsWith("/api/ai/ollama")) {
const authorization = request.headers.get("authorization") || "";
const isDisabledModel = await hasDisabledAIModel();
if (
!verifySignature(
authorization.startsWith("Bearer ") ? authorization.substring(7) : authorization,
accessPassword,
Date.now()
) ||
disabledAIProviders.includes("ollama") ||
isDisabledModel
) {
return NextResponse.json(
{ error: ERRORS.NO_PERMISSIONS },
{ status: 403 }
);
} else {
const requestHeaders = new Headers();
requestHeaders.set(
"Content-Type",
request.headers.get("Content-Type") || "application/json"
);
return NextResponse.next({
request: {
headers: requestHeaders,
},
});
}
}
This should probably done for all occurences of authorization.substring(7)
While searching for this I also found that verifySignature could cause issues. The timestamp portion of the signature is shortened to get a time window that is valid:
const data = `${key}::${timestamp.toString().substring(0, 8)}`;
The Window is massive yet shifting: By taking the first 8 digits of a millisecond timestamp, the code is effectively grouping time into chunks of 100,000 milliseconds (100 seconds).
If the frontend generated the signature at 1776000099999 and the backend checked it at 1776000100001 (just 2 milliseconds later), the substring changes from 17760000 to 17760001. The hash will be completely different.
An easy fix would be to also generate the signature for the previous time window and check against both.
export function verifySignature(
signature = "",
key: string,
timestamp: number
): boolean {
const generatedSignature = generateSignature(key, timestamp);
// Check the current 100s window and the previous 100s window (offset by 10^5 ms)
const generatedPreviousSignature = generateSignature(key, timestamp - 100000);
return signature === generatedSignature || signature === generatedPreviousSignature;
}
Steps to Reproduce
Run the app with these env vars properly set:
ACCESS_PASSWORD
OLLAMA_API_BASE_URL
In the settings of the UI, set API mode to proxy and set the access password, save.
Enter a research topic and click "Start Thinking"
Expected Behavior
Ollama responds / the http request to /api/ai/ollama/api/chat returns with 200.
Screenshots
No response
Deployment Method
Desktop OS
Windows 10
Desktop Browser
Firefox
Desktop Browser Version
149.0.2 (64-Bit)
Smartphone Device
No response
Smartphone OS
No response
Smartphone Browser
No response
Smartphone Browser Version
No response
Additional Logs
No response
Bug Description
Using this with ollama in local mode works as intended. In proxy mode there is a bug in middleware.ts that removes the first 7 characters of the authorization header before using it in verifySignature. That is probably intended to remove a leading "Bearer ", but that is not present in the actual header.
I propose to replace
authorization.substring(7)withauthorization.startsWith("Bearer ") ? authorization.substring(7) : authorization.In context:
This should probably done for all occurences of
authorization.substring(7)While searching for this I also found that verifySignature could cause issues. The timestamp portion of the signature is shortened to get a time window that is valid:
The Window is massive yet shifting: By taking the first 8 digits of a millisecond timestamp, the code is effectively grouping time into chunks of 100,000 milliseconds (100 seconds).
If the frontend generated the signature at 1776000099999 and the backend checked it at 1776000100001 (just 2 milliseconds later), the substring changes from 17760000 to 17760001. The hash will be completely different.
An easy fix would be to also generate the signature for the previous time window and check against both.
Steps to Reproduce
Run the app with these env vars properly set:
ACCESS_PASSWORD
OLLAMA_API_BASE_URL
In the settings of the UI, set API mode to proxy and set the access password, save.
Enter a research topic and click "Start Thinking"
Expected Behavior
Ollama responds / the http request to /api/ai/ollama/api/chat returns with 200.
Screenshots
No response
Deployment Method
Desktop OS
Windows 10
Desktop Browser
Firefox
Desktop Browser Version
149.0.2 (64-Bit)
Smartphone Device
No response
Smartphone OS
No response
Smartphone Browser
No response
Smartphone Browser Version
No response
Additional Logs
No response