fix(market): move Finnhub API key from query string to X-Finnhub-Token header (#744)

API keys in URL query strings can leak via server logs, proxy logs,
Referer headers, and error reporting tools. Finnhub supports both
authentication methods — this moves to the header-based approach.

Addresses #197 (L-16).

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nicolas Gomes Ferreira Dos Santos
2026-03-02 00:37:38 -08:00
committed by GitHub
parent 16673d7110
commit d90c845621
2 changed files with 4 additions and 4 deletions

View File

@@ -78,9 +78,9 @@ export async function fetchFinnhubQuote(
apiKey: string,
): Promise<{ symbol: string; price: number; changePercent: number } | null> {
try {
const url = `https://finnhub.io/api/v1/quote?symbol=${encodeURIComponent(symbol)}&token=${apiKey}`;
const url = `https://finnhub.io/api/v1/quote?symbol=${encodeURIComponent(symbol)}`;
const resp = await fetch(url, {
headers: { Accept: 'application/json', 'User-Agent': CHROME_UA },
headers: { Accept: 'application/json', 'User-Agent': CHROME_UA, 'X-Finnhub-Token': apiKey },
signal: AbortSignal.timeout(UPSTREAM_TIMEOUT_MS),
});
if (!resp.ok) return null;

View File

@@ -791,8 +791,8 @@ async function validateSecretAgainstProvider(key, rawValue, context = {}) {
}
case 'FINNHUB_API_KEY': {
const response = await fetchWithTimeout(`https://finnhub.io/api/v1/quote?symbol=AAPL&token=${encodeURIComponent(value)}`, {
headers: { Accept: 'application/json', 'User-Agent': CHROME_UA },
const response = await fetchWithTimeout(`https://finnhub.io/api/v1/quote?symbol=AAPL`, {
headers: { Accept: 'application/json', 'User-Agent': CHROME_UA, 'X-Finnhub-Token': value },
});
const text = await response.text();
if (isCloudflareChallenge403(response, text)) return ok('Finnhub key stored (Cloudflare blocked verification)');