ui: mask API Key field in settings and error splash to stop browser a… (#26562)

* ui: mask API Key field in settings and error splash to stop browser autofill

* ui: set autocomplete=new-password on private fields

The password input type makes browsers offer to save the API key
in the password manager and autofill saved site credentials into
the field. The new-password autocomplete value disables both.

---------

Co-authored-by: Pascal <admin@serveurperso.com>
This commit is contained in:
Cristiano Pinto
2026-08-15 22:52:55 +02:00
committed by GitHub
co-authored by Pascal
parent 0d9ceae1e3
commit ece963f41b
5 changed files with 20 additions and 1 deletions
@@ -158,6 +158,8 @@
<div class="relative">
<Input
id="api-key-input"
type="password"
autocomplete="new-password"
placeholder="Enter your API key..."
bind:value={apiKeyInput}
onkeydown={handleApiKeyKeydown}
@@ -81,7 +81,8 @@
<div class="relative w-full">
<Input
id={field.key}
type={field.isPositiveInteger ? 'number' : 'text'}
type={field.isPrivate ? 'password' : field.isPositiveInteger ? 'number' : 'text'}
autocomplete={field.isPrivate ? 'new-password' : undefined}
{...field.isPositiveInteger
? {
min: String(field.min ?? 1),
@@ -324,6 +324,7 @@ const SETTINGS_REGISTRY: Record<string, SettingsSectionEntry> = {
{
defaultValue: '',
help: `Set the API Key if you are using <code> ${CLI_FLAGS.API_KEY} </code> option for the server.`,
isPrivate: true,
key: SETTINGS_KEYS.API_KEY,
label: 'API Key',
section: SETTINGS_SECTION_SLUGS.GENERAL,
@@ -713,6 +714,7 @@ export const SETTINGS_CHAT_SECTIONS: SettingsSection[] = [
help: s.help,
isExperimental: s.isExperimental,
isPositiveInteger: s.isPositiveInteger,
isPrivate: s.isPrivate,
key: s.key,
label: s.label,
max: s.max,
+2
View File
@@ -31,6 +31,7 @@ export interface SettingsEntry {
radioOptions?: Array<{ value: string; label: string; key: string; isExperimental?: boolean }>;
isExperimental?: boolean;
isPositiveInteger?: boolean;
isPrivate?: boolean;
placeholder?: string;
min?: number;
max?: number;
@@ -55,6 +56,7 @@ export interface SettingsFieldConfig {
type: SettingsFieldType;
isExperimental?: boolean;
isPositiveInteger?: boolean;
isPrivate?: boolean;
placeholder?: string;
min?: number;
max?: number;
@@ -0,0 +1,12 @@
import { SETTINGS_CHAT_SECTIONS, SETTINGS_KEYS } from '$lib/constants';
import { describe, expect, it } from 'vitest';
describe('checkApiKeyField', () => {
it('should have isPrivate set to true', () => {
const fields = SETTINGS_CHAT_SECTIONS.flatMap((section) => section.fields);
const apiKeyField = fields.find((field) => field?.key === SETTINGS_KEYS.API_KEY);
expect(apiKeyField).toBeDefined();
expect(apiKeyField?.isPrivate).toBe(true);
});
});