Gestión de secretos

OpenClaw soporta SecretRefs aditivos para que las credenciales soportadas no necesiten almacenarse en texto plano en la configuración.

El texto plano sigue funcionando. Los SecretRefs son opcionales por credencial.

Objetivos y modelo de runtime

Los secretos se resuelven en un snapshot de runtime en memoria.

  • La resolución es eager durante la activación, no lazy en las rutas de solicitud.
  • El inicio falla rápido cuando un SecretRef efectivamente activo no puede resolverse.
  • La recarga usa intercambio atómico: éxito completo, o mantiene el último snapshot conocido como bueno.
  • Las solicitudes de runtime leen solo del snapshot activo en memoria.
  • Las rutas de entrega saliente también leen de ese snapshot activo (por ejemplo, entrega de respuesta/hilo de Discord y envíos de acción de Telegram); no vuelven a resolver SecretRefs en cada envío.

Esto mantiene las interrupciones del proveedor de secretos fuera de las rutas de solicitud activas.

Filtrado de superficie activa

Los SecretRefs se validan solo en superficies efectivamente activas.

  • Superficies habilitadas: las refs no resueltas bloquean inicio/recarga.
  • Superficies inactivas: las refs no resueltas no bloquean inicio/recarga.
  • Las refs inactivas emiten diagnósticos no fatales con código SECRETS_REF_IGNORED_INACTIVE_SURFACE.

Ejemplos de superficies inactivas:

  • Entradas de canal/cuenta deshabilitadas.
  • Credenciales de canal de nivel superior que ninguna cuenta habilitada hereda.
  • Superficies de herramienta/característica deshabilitadas.
  • Claves específicas del proveedor de búsqueda web que no están seleccionadas por tools.web.search.provider. En modo automático (proveedor no establecido), las claves se consultan por precedencia para auto-detección del proveedor hasta que una se resuelve. Después de la selección, las claves de proveedores no seleccionados se tratan como inactivas hasta ser seleccionadas.
  • Los SecretRefs de gateway.remote.token / gateway.remote.password están activos si se cumple una de estas condiciones:
    • gateway.mode=remote
    • gateway.remote.url está configurado
    • gateway.tailscale.mode es serve o funnel
    • En modo local sin esas superficies remotas:
      • gateway.remote.token está activo cuando la autenticación por token puede ganar y no hay token de env/auth configurado.
      • gateway.remote.password está activo solo cuando la autenticación por password puede ganar y no hay password de env/auth configurado.
  • El SecretRef de gateway.auth.token está inactivo para la resolución de autenticación de inicio cuando OPENCLAW_GATEWAY_TOKEN (o CLAWDBOT_GATEWAY_TOKEN) está establecido, porque la entrada de token de env gana para ese runtime.

Diagnósticos de superficie de autenticación del Gateway

Cuando un SecretRef está configurado en gateway.auth.token, gateway.auth.password, gateway.remote.token o gateway.remote.password, el inicio/recarga del gateway registra el estado de la superficie explícitamente:

  • active: el SecretRef es parte de la superficie de autenticación efectiva y debe resolverse.
  • inactive: el SecretRef se ignora para este runtime porque otra superficie de autenticación gana, o porque la autenticación remota está deshabilitada/no activa.

Estas entradas se registran con SECRETS_GATEWAY_AUTH_SURFACE e incluyen la razón usada por la política de superficie activa, para que puedas ver por qué una credencial fue tratada como activa o inactiva.

Verificación previa de referencia en onboarding

Cuando el onboarding se ejecuta en modo interactivo y eliges almacenamiento SecretRef, OpenClaw ejecuta validación previa antes de guardar:

  • Refs de env: valida el nombre de la variable de entorno y confirma que un valor no vacío es visible durante el onboarding.
  • Refs de proveedor (file o exec): valida la selección del proveedor, resuelve id y verifica el tipo de valor resuelto.
  • Ruta de reutilización del quickstart: cuando gateway.auth.token ya es un SecretRef, el onboarding lo resuelve antes del probe/bootstrap del dashboard (para refs env, file y exec) usando la misma compuerta de fallo rápido.

Si la validación falla, el onboarding muestra el error y te permite reintentar.

Contrato SecretRef

Usa una forma de objeto en todas partes:

{ source: "env" | "file" | "exec", provider: "default", id: "..." }

source: "env"

{ source: "env", provider: "default", id: "OPENAI_API_KEY" }

Validación:

  • provider debe coincidir con ^[a-z][a-z0-9_-]{0,63}$
  • id debe coincidir con ^[A-Z][A-Z0-9_]{0,127}$

source: "file"

{ source: "file", provider: "filemain", id: "/providers/openai/apiKey" }

Validación:

  • provider debe coincidir con ^[a-z][a-z0-9_-]{0,63}$
  • id debe ser un puntero JSON absoluto (/...)
  • Escape RFC6901 en segmentos: ~ => ~0, / => ~1

source: "exec"

{ source: "exec", provider: "vault", id: "providers/openai/apiKey" }

Validación:

  • provider debe coincidir con ^[a-z][a-z0-9_-]{0,63}$
  • id debe coincidir con ^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$
  • id no debe contener . o .. como segmentos de ruta delimitados por barra (por ejemplo a/../b se rechaza)

Configuración de proveedores

Define proveedores en secrets.providers:

{
  secrets: {
    providers: {
      default: { source: "env" },
      filemain: {
        source: "file",
        path: "~/.openclaw/secrets.json",
        mode: "json", // o "singleValue"
      },
      vault: {
        source: "exec",
        command: "/usr/local/bin/openclaw-vault-resolver",
        args: ["--profile", "prod"],
        passEnv: ["PATH", "VAULT_ADDR"],
        jsonOnly: true,
      },
    },
    defaults: {
      env: "default",
      file: "filemain",
      exec: "vault",
    },
    resolution: {
      maxProviderConcurrency: 4,
      maxRefsPerProvider: 512,
      maxBatchBytes: 262144,
    },
  },
}

Proveedor env

  • Lista de permitidos opcional vía allowlist.
  • Los valores de env faltantes/vacíos fallan en la resolución.

Proveedor file

  • Lee un archivo local desde path.
  • mode: "json" espera un payload de objeto JSON y resuelve id como puntero.
  • mode: "singleValue" espera el id de ref "value" y devuelve el contenido del archivo.
  • La ruta debe pasar verificaciones de propiedad/permisos.
  • Nota de fallo cerrado en Windows: si la verificación de ACL no está disponible para una ruta, la resolución falla. Para rutas de confianza únicamente, establece allowInsecurePath: true en ese proveedor para omitir las verificaciones de seguridad de ruta.

Proveedor exec

  • Ejecuta la ruta binaria absoluta configurada, sin shell.
  • Por defecto, command debe apuntar a un archivo regular (no un enlace simbólico).
  • Establece allowSymlinkCommand: true para permitir rutas de comando con enlaces simbólicos (por ejemplo, shims de Homebrew). OpenClaw valida la ruta de destino resuelta.
  • Combina allowSymlinkCommand con trustedDirs para rutas de gestores de paquetes (por ejemplo ["/opt/homebrew"]).
  • Soporta timeout, timeout sin salida, límites de bytes de salida, lista de env permitidas y directorios de confianza.
  • Nota de fallo cerrado en Windows: si la verificación de ACL no está disponible para la ruta del comando, la resolución falla. Para rutas de confianza únicamente, establece allowInsecurePath: true en ese proveedor para omitir las verificaciones de seguridad de ruta.

Payload de solicitud (stdin):

{ "protocolVersion": 1, "provider": "vault", "ids": ["providers/openai/apiKey"] }

Payload de respuesta (stdout):

{ "protocolVersion": 1, "values": { "providers/openai/apiKey": "<openai-api-key>" } } // pragma: allowlist secret

Errores opcionales por id:

{
  "protocolVersion": 1,
  "values": {},
  "errors": { "providers/openai/apiKey": { "message": "not found" } }
}

Ejemplos de integración exec

1Password CLI

{
  secrets: {
    providers: {
      onepassword_openai: {
        source: "exec",
        command: "/opt/homebrew/bin/op",
        allowSymlinkCommand: true, // requerido para binarios con enlace simbólico de Homebrew
        trustedDirs: ["/opt/homebrew"],
        args: ["read", "op://Personal/OpenClaw QA API Key/password"],
        passEnv: ["HOME"],
        jsonOnly: false,
      },
    },
  },
  models: {
    providers: {
      openai: {
        baseUrl: "https://api.openai.com/v1",
        models: [{ id: "gpt-5", name: "gpt-5" }],
        apiKey: { source: "exec", provider: "onepassword_openai", id: "value" },
      },
    },
  },
}

HashiCorp Vault CLI

{
  secrets: {
    providers: {
      vault_openai: {
        source: "exec",
        command: "/opt/homebrew/bin/vault",
        allowSymlinkCommand: true, // requerido para binarios con enlace simbólico de Homebrew
        trustedDirs: ["/opt/homebrew"],
        args: ["kv", "get", "-field=OPENAI_API_KEY", "secret/openclaw"],
        passEnv: ["VAULT_ADDR", "VAULT_TOKEN"],
        jsonOnly: false,
      },
    },
  },
  models: {
    providers: {
      openai: {
        baseUrl: "https://api.openai.com/v1",
        models: [{ id: "gpt-5", name: "gpt-5" }],
        apiKey: { source: "exec", provider: "vault_openai", id: "value" },
      },
    },
  },
}

sops

{
  secrets: {
    providers: {
      sops_openai: {
        source: "exec",
        command: "/opt/homebrew/bin/sops",
        allowSymlinkCommand: true, // requerido para binarios con enlace simbólico de Homebrew
        trustedDirs: ["/opt/homebrew"],
        args: ["-d", "--extract", '["providers"]["openai"]["apiKey"]', "/path/to/secrets.enc.json"],
        passEnv: ["SOPS_AGE_KEY_FILE"],
        jsonOnly: false,
      },
    },
  },
  models: {
    providers: {
      openai: {
        baseUrl: "https://api.openai.com/v1",
        models: [{ id: "gpt-5", name: "gpt-5" }],
        apiKey: { source: "exec", provider: "sops_openai", id: "value" },
      },
    },
  },
}

Superficie de credenciales soportada

Las credenciales soportadas y no soportadas canónicas se listan en:

Las credenciales generadas en runtime o rotativas y el material de actualización OAuth están intencionalmente excluidos de la resolución SecretRef de solo lectura.

Comportamiento requerido y precedencia

  • Campo sin ref: sin cambios.
  • Campo con ref: obligatorio en superficies activas durante la activación.
  • Si están presentes tanto texto plano como ref, la ref tiene precedencia en las rutas de precedencia soportadas.

Señales de advertencia y auditoría:

  • SECRETS_REF_OVERRIDES_PLAINTEXT (advertencia de runtime)
  • REF_SHADOWED (hallazgo de auditoría cuando las credenciales de auth-profiles.json tienen precedencia sobre las refs de openclaw.json)

Comportamiento de compatibilidad de Google Chat:

  • serviceAccountRef tiene precedencia sobre serviceAccount en texto plano.
  • El valor en texto plano se ignora cuando la ref hermana está establecida.

Disparadores de activación

La activación de secretos se ejecuta en:

  • Inicio (verificación previa más activación final)
  • Ruta de hot-apply en recarga de configuración
  • Ruta de verificación de reinicio en recarga de configuración
  • Recarga manual vía secrets.reload

Contrato de activación:

  • El éxito intercambia el snapshot atómicamente.
  • El fallo en el inicio aborta el inicio del gateway.
  • El fallo en recarga de runtime mantiene el último snapshot conocido como bueno.
  • Proporcionar un token de canal explícito por llamada a un helper/tool call saliente no dispara la activación de SecretRef; los puntos de activación permanecen en inicio, recarga y secrets.reload explícito.

Señales de degradación y recuperación

Cuando la activación en tiempo de recarga falla después de un estado saludable, OpenClaw entra en estado de secretos degradado.

Evento de sistema y códigos de log de disparo único:

  • SECRETS_RELOADER_DEGRADED
  • SECRETS_RELOADER_RECOVERED

Comportamiento:

  • Degradado: el runtime mantiene el último snapshot conocido como bueno.
  • Recuperado: se emite una vez después de la siguiente activación exitosa.
  • Los fallos repetidos mientras ya está degradado registran advertencias pero no generan spam de eventos.
  • El fallo rápido de inicio no emite eventos de degradación porque el runtime nunca se activó.

Resolución de rutas de comando

Las rutas de comando pueden optar por la resolución SecretRef soportada vía RPC de snapshot del gateway.

Hay dos comportamientos generales:

  • Rutas de comando estrictas (por ejemplo, rutas de memoria remota de openclaw memory y openclaw qr --remote) leen del snapshot activo y fallan rápido cuando un SecretRef requerido no está disponible.
  • Rutas de comando de solo lectura (por ejemplo, openclaw status, openclaw status --all, openclaw channels status, openclaw channels resolve y flujos de doctor/reparación de config de solo lectura) también prefieren el snapshot activo, pero degradan en lugar de abortar cuando un SecretRef objetivo no está disponible en esa ruta de comando.

Comportamiento de solo lectura:

  • Cuando el gateway está ejecutándose, estos comandos leen primero del snapshot activo.
  • Si la resolución del gateway está incompleta o el gateway no está disponible, intentan un respaldo local dirigido para la superficie del comando específico.
  • Si un SecretRef objetivo sigue sin estar disponible, el comando continúa con salida degradada de solo lectura y diagnósticos explícitos como “configured but unavailable in this command path”.
  • Este comportamiento degradado es solo local al comando. No debilita las rutas de inicio, recarga o envío/autenticación del runtime.

Otras notas:

  • La actualización del snapshot después de la rotación de secretos del backend se maneja con openclaw secrets reload.
  • Método RPC del Gateway usado por estas rutas de comando: secrets.resolve.

Flujo de trabajo de auditoría y configuración

Flujo por defecto del operador:

openclaw secrets audit --check
openclaw secrets configure
openclaw secrets audit --check

secrets audit

Los hallazgos incluyen:

  • valores en texto plano en reposo (openclaw.json, auth-profiles.json, .env y agents/*/agent/models.json generados)
  • residuos de headers sensibles de proveedores en texto plano en entradas models.json generadas
  • refs no resueltas
  • sombreado de precedencia (auth-profiles.json teniendo prioridad sobre refs de openclaw.json)
  • residuos heredados (auth.json, recordatorios OAuth)

Nota sobre residuos de headers:

  • La detección de headers sensibles de proveedores se basa en heurísticas de nombre (nombres comunes de headers de autenticación/credenciales y fragmentos como authorization, x-api-key, token, secret, password y credential).

secrets configure

Asistente interactivo que:

  • configura secrets.providers primero (env/file/exec, agregar/editar/eliminar)
  • te permite seleccionar campos soportados que contienen secretos en openclaw.json más auth-profiles.json para un alcance de agente
  • puede crear un nuevo mapeo en auth-profiles.json directamente en el selector de destinos
  • captura detalles del SecretRef (source, provider, id)
  • ejecuta resolución previa
  • puede aplicar inmediatamente

Modos útiles:

  • openclaw secrets configure --providers-only
  • openclaw secrets configure --skip-provider-setup
  • openclaw secrets configure --agent <id>

Valores por defecto de apply en configure:

  • limpia credenciales estáticas coincidentes de auth-profiles.json para los proveedores objetivo
  • limpia entradas estáticas heredadas de api_key de auth.json
  • limpia líneas de secretos conocidos coincidentes de <config-dir>/.env

secrets apply

Aplica un plan guardado:

openclaw secrets apply --from /tmp/openclaw-secrets-plan.json
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run

Para detalles estrictos del contrato de destino/ruta y reglas exactas de rechazo, consulta:

Política de seguridad unidireccional

OpenClaw intencionalmente no escribe copias de respaldo de rollback que contengan valores históricos de secretos en texto plano.

Modelo de seguridad:

  • la verificación previa debe tener éxito antes del modo de escritura
  • la activación de runtime se valida antes del commit
  • apply actualiza archivos usando reemplazo atómico de archivos y restauración en base a mejor esfuerzo en caso de fallo

Notas de compatibilidad de autenticación heredada

Para credenciales estáticas, el runtime ya no depende del almacenamiento heredado de autenticación en texto plano.

  • La fuente de credenciales de runtime es el snapshot resuelto en memoria.
  • Las entradas estáticas heredadas de api_key se limpian cuando se descubren.
  • El comportamiento de compatibilidad relacionado con OAuth permanece separado.

Nota sobre la Web UI

Algunas uniones SecretInput son más fáciles de configurar en modo de editor raw que en modo formulario.

Documentación relacionada