🛡️ fix: Filter user_provided Sentinel in Tool Credential Loading (#12840)

When GOOGLE_KEY=user_provided is set as an endpoint config, the
loadAuthValues() function in credentials.js would pass the literal
string 'user_provided' to tools via the || fallback chain. This caused
Gemini Image Tools to fail at runtime with an invalid API key error,
as initializeGeminiClient() received the sentinel value instead of a
real key.

The fix aligns loadAuthValues() with checkPluginAuth() in format.ts,
which already correctly excludes user_provided and empty/whitespace
values. Now loadAuthValues() skips these values and continues to the
next field in the fallback chain or falls through to user DB values.

Added regression tests covering:
- user_provided sentinel is skipped, DB value used instead
- Fallback chain continues past user_provided to next field
- Empty and whitespace env values are skipped
- Real env values are returned correctly
- Optional fields with sentinel values handled gracefully
This commit is contained in:
Yorgos K 2026-04-29 02:09:54 +02:00 committed by GitHub
parent 89bf2ab7b4
commit f2df0ea62b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 140 additions and 4 deletions

View file

@ -1,3 +1,4 @@
const { AuthType } = require('librechat-data-provider');
const { getUserPluginAuthValue } = require('~/server/services/PluginService');
/**
@ -19,17 +20,18 @@ const loadAuthValues = async ({ userId, authFields, optional, throwError = true
*/
const findAuthValue = async (fields) => {
for (const field of fields) {
let value = process.env[field];
if (value) {
return { authField: field, authValue: value };
const envValue = process.env[field];
if (envValue && envValue.trim() !== '' && envValue !== AuthType.USER_PROVIDED) {
return { authField: field, authValue: envValue };
}
let value;
try {
value = await getUserPluginAuthValue(userId, field, throwError);
} catch (err) {
if (optional && optional.has(field)) {
return { authField: field, authValue: undefined };
}
if (field === fields[fields.length - 1] && !value) {
if (field === fields[fields.length - 1]) {
throw err;
}
}