Skip to content

Conversation

@Subash-Mohan
Copy link
Contributor

@Subash-Mohan Subash-Mohan commented Jan 6, 2026

Description

This pull request improves the handling and security of API keys for image generation provider configuration, both in the backend and frontend. The changes ensure that API keys are masked in API responses, preserve existing keys unless explicitly changed. Additionally, the frontend now tracks whether the API key was actually modified, and the backend logic uses this information to determine which key to use.

How Has This Been Tested?

Tested from UI

Additional Options

  • [Optional] Override Linear Check

Summary by cubic

Enhanced API key handling for image generation configs: keys are masked in responses, and existing keys are preserved unless a change is confirmed. This reduces accidental key overwrites and avoids unnecessary validation calls.

  • New Features

    • Mask API keys in API responses (first 4 + **** + last 4).
    • Preserve existing API key on update when the key wasn’t changed; clone mode still uses the source provider key.
    • Frontend tracks and sends apiKeyChanged, and validates the key only if it was changed.
  • Bug Fixes

    • Only the first exact match is highlighted in combo box options.

Written for commit 1b2bd4a. Summary will update on new commits.

…onfig

- Implement logic to preserve existing API key if not explicitly changed.
- Add a utility function to mask API keys for security in responses.
- Update frontend to reflect changes in API key handling and validation logic.
- Ensure API key change status is tracked and passed to backend for configuration updates.
@Subash-Mohan Subash-Mohan requested a review from a team as a code owner January 6, 2026 05:28
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 6, 2026

Greptile Summary

This PR enhances API key handling and security for image generation configuration by implementing masking in API responses and preserving existing keys unless explicitly changed. The backend correctly implements key masking and preservation logic, and the service layer properly supports the new api_key_changed flag. However, the frontend form logic has a critical flaw: when editing with masked keys, it incorrectly detects changes when the user hasn't modified the field, which will cause API key validation to fail on masked keys.

Key Changes:

  • Backend: Masks API keys in ImageGenerationCredentials responses, shows only first 4 and last 4 characters
  • Backend: Implements key preservation logic in update flow using api_key_changed flag
  • Frontend: Tracks whether API key was actually modified and only tests if changed
  • Frontend: Fixes bug in OptionsList to only highlight first exact match

Issues Found:

  • Critical: Frontend change detection logic fails with masked keys in edit mode - will unnecessarily test masked API keys causing validation failures
  • Style: Masked API keys sent to backend in update requests even when unchanged, reducing code clarity

Confidence Score: 2/5

  • This PR introduces a critical logic bug in the frontend that will cause API key validation to fail when editing configurations without changing the key, making the feature unreliable in practice.
  • The backend implementation is solid (API key masking and preservation logic are correct). The service layer is correct. However, the frontend form has a critical flaw: the change detection logic compares the current form value with the initial masked key value. When a user opens edit mode and doesn't modify the key, the form still contains the masked value (e.g., "key1****key4"), which will be different from what's currently in the form input field, causing a false positive "change" detection. This will trigger API key validation on a masked key, which will fail. This makes the feature completely broken for the common case of editing a config without changing the key.
  • web/src/app/admin/configuration/image-generation/forms/ImageGenFormWrapper.tsx - The change detection logic at lines 185-188 needs to properly handle masked keys to avoid false positive change detection.

Important Files Changed

Filename Overview
backend/onyx/server/manage/image_generation/api.py Backend correctly implements API key preservation logic using the api_key_changed flag. Masking is properly removed from this endpoint (unmasked keys are used internally). The logic that determines which API key to use based on api_key_changed and source_llm_provider_id is sound.
backend/onyx/server/manage/image_generation/models.py API key masking implementation is secure and correct. The _mask_api_key() function properly masks keys showing first 4 and last 4 chars. The ImageGenerationCredentials.from_model() now correctly masks keys in the response. New api_key_changed field in update model is properly documented.
web/src/app/admin/configuration/image-generation/forms/ImageGenFormWrapper.tsx Component uses correct web standards (regular function, absolute imports). However, the logic for detecting API key changes is flawed when working with masked keys in edit mode - it will incorrectly detect changes when the user hasn't modified the field, causing unnecessary testing of masked keys. Additionally, masked API keys are sent to the backend even when unchanged, which reduces clarity.
web/src/lib/configuration/imageConfigurationService.ts Service layer correctly passes the api_key_changed flag to the backend. Type definitions are clear and well-documented. No issues found.
web/src/refresh-components/inputs/InputComboBox/components/OptionsList.tsx Fixes a logic bug where all exact matches were highlighted instead of just the first one. The change is correct and improves UX by only highlighting the first exact match. No issues found.

Sequence Diagram

sequenceDiagram
    participant User
    participant Form as Form Component
    participant Service as API Service
    participant Handler as API Handler

    rect rgb(200, 220, 255)
    note over User,Handler: Issue: Masked Key Detection
    User->>Form: Open edit form
    Form->>Form: Load masked initial value
    User->>Form: Submit unchanged
    Form->>Form: Compare current with initial
    Form->>Form: Values differ (false positive)
    Form->>Service: Send test request
    Service->>Handler: Validate masked key
    Handler->>Service: Validation fails
    end

    rect rgb(200, 255, 220)
    note over User,Handler: Correct: User Changes Key
    User->>Form: Edit key field
    Form->>Form: Track value change
    User->>Form: Submit
    Form->>Form: Detect actual modification
    Form->>Service: Send test with new key
    Service->>Handler: Validate actual key
    Handler->>Service: Validation succeeds
    Form->>Service: Send update with flag
    end
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (1)

  1. web/src/app/admin/configuration/image-generation/forms/ImageGenFormWrapper.tsx, line 213-218 (link)

    style: When apiKeyChanged is false in edit mode, a masked API key value may be sent in payload.apiKey (e.g., "key1****key4"). While the backend correctly ignores this due to the api_key_changed flag, it's clearer to explicitly send null for the API key when it hasn't changed to make the intent explicit and prevent potential future bugs if this logic is refactored.

5 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines 185 to 206
// New credentials mode - check if API key was changed from initial (masked) value
const initialApiKey = (mergedInitialValues as Record<string, unknown>)
.api_key as string | undefined;
const apiKeyChanged = apiKeyValue !== initialApiKey;

if (!result.ok) {
setApiStatus("error");
setErrorMessage(result.errorMessage || "API key validation failed");
setIsSubmitting(false);
return;
// Test the API key first (only if changed or creating new config)
if (apiKeyChanged) {
const result = await testImageGenerationApiKey(payload.modelName, {
provider: payload.provider,
apiKey: payload.apiKey,
apiBase: payload.apiBase,
apiVersion: payload.apiVersion,
deploymentName: payload.deploymentName,
});

if (!result.ok) {
setApiStatus("error");
setErrorMessage(result.errorMessage || "API key validation failed");
setIsSubmitting(false);
return;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: In edit mode with a masked API key (e.g., "key1key4"), comparing the form's current value to initialApiKey will incorrectly detect a change when the user hasn't modified the field. This causes unnecessary API testing of a masked key, which will fail. The logic should explicitly check if the value looks like a masked key (contains "") to properly detect actual user changes vs. the initial masked value.

Prompt To Fix With AI
This is a comment left during a code review.
Path: web/src/app/admin/configuration/image-generation/forms/ImageGenFormWrapper.tsx
Line: 185:206

Comment:
**logic:** In edit mode with a masked API key (e.g., "key1****key4"), comparing the form's current value to `initialApiKey` will incorrectly detect a change when the user hasn't modified the field. This causes unnecessary API testing of a masked key, which will fail. The logic should explicitly check if the value looks like a masked key (contains "****") to properly detect actual user changes vs. the initial masked value.

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 5 files

…e generation config

- Update logic to preserve existing API key when not explicitly changed and provided key is masked.
- Adjust tests to verify that masked API keys are correctly handled in responses.
- Refine frontend validation to check for changes against masked API key values.
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="backend/onyx/server/manage/image_generation/api.py">

<violation number="1" location="backend/onyx/server/manage/image_generation/api.py:387">
P1: Logic flaw: If `api_key_changed=False` but the provided key is None or doesn&#39;t contain `****`, the existing key won&#39;t be preserved. This can cause unexpected 400 errors or accidental key overwrites. Consider also preserving when the key is None:

```python
if not config_update.api_key_changed and (not config_update.api_key or provided_key_is_masked):

Or simply trust the api_key_changed flag as before, and separately validate that masked keys shouldn't be saved.


</details>

<sub>Reply with feedback, questions, or to request a fix. Tag `@cubic-dev-ai` to re-run a review.</sub>

provided_key_is_masked = (
config_update.api_key and "****" in config_update.api_key
)
if not config_update.api_key_changed and provided_key_is_masked:
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Logic flaw: If api_key_changed=False but the provided key is None or doesn't contain ****, the existing key won't be preserved. This can cause unexpected 400 errors or accidental key overwrites. Consider also preserving when the key is None:

if not config_update.api_key_changed and (not config_update.api_key or provided_key_is_masked):

Or simply trust the api_key_changed flag as before, and separately validate that masked keys shouldn't be saved.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At backend/onyx/server/manage/image_generation/api.py, line 387:

<comment>Logic flaw: If `api_key_changed=False` but the provided key is None or doesn&#39;t contain `****`, the existing key won&#39;t be preserved. This can cause unexpected 400 errors or accidental key overwrites. Consider also preserving when the key is None:

```python
if not config_update.api_key_changed and (not config_update.api_key or provided_key_is_masked):

Or simply trust the api_key_changed flag as before, and separately validate that masked keys shouldn't be saved.

@@ -378,13 +378,15 @@ def update_config( + provided_key_is_masked = ( + config_update.api_key and "****" in config_update.api_key + ) + if not config_update.api_key_changed and provided_key_is_masked: + # Preserve existing API key when user didn't change it + actual_api_key = old_provider.api_key ```

✅ Addressed in 1b2bd4a

…config

- Update conditions for preserving existing API key to include checks for empty or masked keys.
- Ensure consistency in handling API key changes and improve clarity in the code logic.
@Subash-Mohan Subash-Mohan merged commit 233d06e into main Jan 6, 2026
80 of 82 checks passed
@Subash-Mohan Subash-Mohan deleted the fix/masks-image-config-api-key branch January 6, 2026 08:47
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.

2 participants