{"record":{"id":"2dd0117dde05b039","repo":"srbhr/Resume-Matcher","slug":"confirmation-required-pass-confirm-clear-all-keys","errorCode":null,"errorMessage":"Confirmation required. Pass confirm=CLEAR_ALL_KEYS query parameter.","messagePattern":"Confirmation required\\. Pass confirm=CLEAR_ALL_KEYS query parameter\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"apps/backend/app/routers/config.py","lineNumber":617,"sourceCode":"\n@router.delete(\"/api-keys\")\nasync def delete_all_api_keys(confirm: str | None = None) -> dict:\n    \"\"\"Clear all configured API keys.\n\n    This is a destructive operation. Requires confirmation token.\n\n    Args:\n        confirm: Must be \"CLEAR_ALL_KEYS\" to execute\n\n    Returns:\n        Success message\n\n    Note:\n        This is a local-only endpoint for single-user deployments.\n        In production/multi-user scenarios, add proper authentication.\n    \"\"\"\n    if confirm != \"CLEAR_ALL_KEYS\":\n        raise HTTPException(\n            status_code=400,\n            detail=\"Confirmation required. Pass confirm=CLEAR_ALL_KEYS query parameter.\",\n        )\n    clear_all_api_keys()\n    invalidate_config_cache()\n    return {\"message\": \"All API keys have been cleared\"}\n\n\n@router.delete(\"/api-keys/{provider}\")\nasync def delete_api_key(provider: str) -> dict:\n    \"\"\"Delete API key for a specific provider.\n\n    Args:\n        provider: The provider name (openai, anthropic, google, openrouter, deepseek)\n\n    Returns:\n        Success message\n    \"\"\"","sourceCodeStart":599,"sourceCodeEnd":635,"githubUrl":"https://github.com/srbhr/Resume-Matcher/blob/116f9cc3b00e1ac91734a6c2679bf41ea64a0edc/apps/backend/app/routers/config.py#L599-L635","documentation":"A 400 HTTPException raised by delete_all_api_keys as a safety interlock: wiping every stored API key requires explicit confirmation via the confirm query parameter set to the exact string CLEAR_ALL_KEYS. This prevents accidental or CSRF-driven destruction of all credentials.","triggerScenarios":"DELETE the clear-all-keys endpoint without confirm, with a wrong value (e.g. confirm=true), or with the correct value sent in the body/header instead of the query string.","commonSituations":"Calling the endpoint from a script that forgot the query param; casing mismatch (clear_all_keys vs CLEAR_ALL_KEYS); proxies stripping the query string.","solutions":["Send the exact query parameter: ?confirm=CLEAR_ALL_KEYS","Ensure the value is in the URL query string, not the request body","Check exact casing — the comparison is against the literal CLEAR_ALL_KEYS"],"exampleFix":"// before\nawait api.deleteAllApiKeys()\n// after\nawait api.deleteAllApiKeys({ params: { confirm: 'CLEAR_ALL_KEYS' } })","handlingStrategy":"validation","validationCode":"function buildClearKeysUrl(base: string) {\n  const url = new URL(base + '/config/api-keys')\n  url.searchParams.set('confirm', 'CLEAR_ALL_KEYS')\n  return url.toString()\n}","typeGuard":null,"tryCatchPattern":"try {\n  await api.deleteAllApiKeys({ params: { confirm: 'CLEAR_ALL_KEYS' } })\n} catch (e) {\n  if (e.response?.status === 400 && String(e.response.data.detail).startsWith('Confirmation required')) {\n    showToast('Pass confirm=CLEAR_ALL_KEYS as a query parameter')\n  } else throw e\n}","preventionTips":["Always send the literal confirm=CLEAR_ALL_KEYS query parameter","Double-check casing and that the param is in the query string, not the body","Gate destructive actions behind an explicit user confirmation dialog","Remember keys are destroyed irreversibly — export/back up keys first"],"tags":["http-400","confirmation","dangerous-operation","api-keys"],"backgroundTag":"missing-confirmation-parameter","analyzedSha":"116f9cc3b00e1ac91734a6c2679bf41ea64a0edc","analyzedAt":"2026-08-28T22:51:40.999Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}