Make the client more secure (#3742)

Co-authored-by: Douwe Osinga <douwe@squareup.com>
Co-authored-by: Michael Neale <michael.neale@gmail.com>
This commit is contained in:
Douwe Osinga
2025-07-31 19:20:37 +02:00
committed by GitHub
parent d9313aca57
commit d1e38fba32
19 changed files with 89 additions and 104 deletions
+3 -11
View File
@@ -9,7 +9,6 @@ import {
removeExtension as apiRemoveExtension,
providers,
} from '../api';
import { client } from '../api/client.gen';
import type {
ConfigResponse,
UpsertConfigQuery,
@@ -18,8 +17,9 @@ import type {
ProviderDetails,
ExtensionQuery,
ExtensionConfig,
} from '../api/types.gen';
} from '../api';
import { removeShims } from './settings/extensions/utils';
import { ensureClientInitialized } from '../utils';
export type { ExtensionConfig } from '../api/types.gen';
@@ -28,15 +28,6 @@ export type FixedExtensionEntry = ExtensionConfig & {
enabled: boolean;
};
// Initialize client configuration
client.setConfig({
baseUrl: window.appConfig.get('GOOSE_API_HOST') + ':' + window.appConfig.get('GOOSE_PORT'),
headers: {
'Content-Type': 'application/json',
'X-Secret-Key': window.appConfig.get('secretKey'),
},
});
interface ConfigContextType {
config: ConfigResponse['config'];
providersList: ProviderDetails[];
@@ -184,6 +175,7 @@ export const ConfigProvider: React.FC<ConfigProviderProps> = ({ children }) => {
useEffect(() => {
// Load all configuration data and providers on mount
(async () => {
await ensureClientInitialized();
// Load config
const configResponse = await readAllConfig();
setConfig(configResponse.data?.config || {});
@@ -6,6 +6,7 @@ import { startOpenRouterSetup } from '../utils/openRouterSetup';
import WelcomeGooseLogo from './WelcomeGooseLogo';
import { initializeSystem } from '../utils/providerUtils';
import { toastService } from '../toasts';
import { ensureClientInitialized } from '../utils';
interface ProviderGuardProps {
children: React.ReactNode;
@@ -95,6 +96,8 @@ export default function ProviderGuard({ children }: ProviderGuardProps) {
useEffect(() => {
const checkProvider = async () => {
try {
await ensureClientInitialized();
const config = window.electron.getConfig();
console.log('ProviderGuard - Full config:', config);
@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/Tooltip';
import { getApiUrl, getSecretKey } from '../../config';
import { getApiUrl } from '../../config';
interface ActivityHeatmapCell {
week: number;
@@ -40,7 +40,7 @@ export function ActivityHeatmap() {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'X-Secret-Key': getSecretKey(),
'X-Secret-Key': await window.electron.getSecretKey(),
},
});
@@ -1,7 +1,7 @@
import { useEffect, useState } from 'react';
import { Card, CardContent, CardDescription } from '../ui/card';
// import { Folder } from 'lucide-react';
import { getApiUrl, getSecretKey } from '../../config';
import { getApiUrl } from '../../config';
import { Greeting } from '../common/Greeting';
import { fetchSessions, fetchSessionDetails, type Session } from '../../sessions';
// import { fetchProjects, type ProjectMetadata } from '../../projects';
@@ -36,7 +36,7 @@ export function SessionInsights() {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'X-Secret-Key': getSecretKey(),
'X-Secret-Key': await window.electron.getSecretKey(),
},
});
@@ -5,7 +5,7 @@ import { Settings, RefreshCw, ExternalLink } from 'lucide-react';
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '../../ui/dialog';
import UpdateSection from './UpdateSection';
import { COST_TRACKING_ENABLED, UPDATES_ENABLED } from '../../../updates';
import { getApiUrl, getSecretKey } from '../../../config';
import { getApiUrl } from '../../../config';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../../ui/card';
import ThemeSelector from '../../GooseSidebar/ThemeSelector';
import BlockLogoBlack from './icons/block-lockup_black.png';
@@ -71,7 +71,7 @@ export default function AppSettingsSection({ scrollToSection }: AppSettingsSecti
const checkPricingStatus = async () => {
try {
const apiUrl = getApiUrl('/config/pricing');
const secretKey = getSecretKey();
const secretKey = await window.electron.getSecretKey();
const headers: HeadersInit = { 'Content-Type': 'application/json' };
if (secretKey) {
@@ -100,7 +100,7 @@ export default function AppSettingsSection({ scrollToSection }: AppSettingsSecti
setIsRefreshing(true);
try {
const apiUrl = getApiUrl('/config/pricing');
const secretKey = getSecretKey();
const secretKey = await window.electron.getSecretKey();
const headers: HeadersInit = { 'Content-Type': 'application/json' };
if (secretKey) {
@@ -1,5 +1,5 @@
import { ExtensionConfig } from '../../../api/types.gen';
import { getApiUrl, getSecretKey } from '../../../config';
import { getApiUrl } from '../../../config';
import { toastService, ToastServiceOptions } from '../../../toasts';
import { replaceWithShims } from './utils';
@@ -46,7 +46,7 @@ export async function extensionApiCall(
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Secret-Key': getSecretKey(),
'X-Secret-Key': await window.electron.getSecretKey(),
},
body: JSON.stringify(payload),
});
@@ -1,6 +1,6 @@
import { useEffect, useState, useCallback } from 'react';
import { useConfig } from '../../ConfigContext';
import { getApiUrl, getSecretKey } from '../../../config';
import { getApiUrl } from '../../../config';
interface ToolSelectionStrategy {
key: string;
@@ -56,7 +56,7 @@ export const ToolSelectionStrategySection = () => {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Secret-Key': getSecretKey(),
'X-Secret-Key': await window.electron.getSecretKey(),
},
});