Posts

Trust Insights en iOS 27: detectar indicios de ingeniería social

Arturo Rivas Arias

Una persona puede identificarse con Face ID, introducir su contraseña y confirmar una operación mientras un estafador le indica qué hacer por teléfono. Todos los controles de autenticación funcionan y, aun así, la cuenta termina comprometida. Identificar al usuario no permite saber si está actuando bajo presión o engaño.

Con iOS 27, Apple introduce Trust Insights, un framework que aporta contexto sobre estas situaciones. La aplicación solicita una evaluación antes de una operación sensible y utiliza el resultado para decidir si conviene añadir comprobaciones o mostrar una advertencia.

Una señal que necesita interpretación

El primer tipo de evaluación disponible es IsLikelyBeingCoachedInsight. Busca indicios de que otra persona está guiando al usuario mientras realiza una acción.

Esto tiene un matiz importante: recibir ayuda no implica estar sufriendo una estafa. Un familiar puede explicar cómo utilizar una aplicación perfectamente legítima. La señal debe interpretarse junto con el contexto de la operación y los controles que ya tengamos.

Sus resultados tampoco equivalen a una clasificación convencional de riesgo bajo, medio y alto:

  • .unknown: no hay evidencia de que alguien esté guiando al usuario. No demuestra que la operación sea segura.
  • .medium: aparecen indicios que pueden justificar una comprobación adicional.
  • .high: los indicios son significativos y conviene informar del riesgo antes de continuar.

Preparar la integración

En Xcode debemos añadir la capacidad Trust Insights al target. Esta configura el permiso de firma com.apple.developer.trustinsights.base. Además, la aplicación necesita autorización del usuario para solicitar evaluaciones.

Cada petición incluye una categoría: .payment, .account, .resourceUse, .communication u .other. Elegirla correctamente permite describir la acción que estamos evaluando. Para modificar el correo de recuperación de una cuenta, utilizaremos .account.

También se especifican el esquema del resultado y la versión del modelo. .version1 define el formato solicitado; .current selecciona el modelo actual. Son conceptos distintos: actualizar el modelo no equivale a cambiar la estructura que consume nuestro código.

Evaluar un cambio de recuperación

Imaginemos que alguien suplanta al servicio de atención al cliente y pide sustituir el correo de recuperación. El siguiente ejemplo adapta la revisión previa al cambio. El bloque apply debe actualizar la interfaz: conservar las comprobaciones habituales, añadir una verificación o mostrar una advertencia con una opción clara para cancelar.

import Foundation
import TrustInsights

enum RecoveryReview {
    case standardChecks, extraVerification, riskWarning
}

@available(iOS 27.0, *)
@MainActor
func reviewRecoveryChange(
    apply: (RecoveryReview) -> Void
) async {
    let request = IsLikelyBeingCoachedInsight.request(
        schema: .version1,
        modelVersion: .current
    )
    var context = InsightEvaluator.InsightContext(
        operationCategory: .account,
        requestedEvaluations: request
    )
    let requestID = UUID().uuidString
    context.requestID = requestID
    let evaluator = InsightEvaluator()

    do {
        guard try await evaluator.requestAuthorization(
            for: context
        ) == .authorized else {
            apply(.standardChecks)
            return
        }

        let evaluation = try await evaluator.requestEvaluation(
            context: context
        )
        var consumption: InsightEvaluationConsumptionStatus = .notUsedError
        defer { evaluation.reportConsumption(consumption) }

        guard evaluation.requestID == requestID else {
            apply(.standardChecks)
            return
        }

        do {
            switch try evaluation.insight.outcome.get() {
            case .unknown:
                apply(.standardChecks)
                consumption = .usedUnchangedFriction
            case .medium:
                apply(.extraVerification)
                consumption = .usedIncreasedFriction
            case .high:
                apply(.riskWarning)
                consumption = .usedIncreasedFriction
            @unknown default:
                apply(.standardChecks)
            }
        } catch {
            apply(.standardChecks)
        }
    } catch {
        apply(.standardChecks)
    }
}

Este código no ejecuta el cambio de correo: prepara el paso de revisión. Los controles habituales siguen siendo necesarios, también cuando faltan autorización o resultados. En versiones anteriores a iOS 27 debemos conservar ese mismo flujo mediante una comprobación de disponibilidad.

requestAuthorization(for:) espera a que termine la interacción de permisos y devuelve inmediatamente si ya existe autorización. También podemos consultar primero authorizationStatus(for:) para explicar al usuario por qué solicitamos acceso.

Hay dos niveles de error: puede fallar la petición completa o el resultado concreto, que es un Result. El ejemplo contempla ambos. Además, verifica requestID: si no coincide con el enviado, Apple indica que no debemos confiar en la respuesta.

Informar del uso y proteger la decisión

reportConsumption forma parte de la integración. Debe describir cómo hemos utilizado la evaluación antes de liberarla. Omitirlo puede provocar restricciones de acceso al servicio. El defer permite comunicar también los resultados que descartamos por errores.

Si el servidor decide si se permite la operación, conviene enviarle signedPayload y validar allí su firma. Un valor interpretado por la aplicación y reenviado sin verificar no ofrece la misma garantía.

Privacidad y experiencia de uso

Según Apple, los datos procedentes del dispositivo se procesan localmente y se descartan tras la evaluación. No se examina el contenido de Fotos, Mensajes o Mail. El resultado puede incorporar señales de la cuenta de Apple y comprobaciones sobre la frecuencia de actividad.

La evaluación requiere conexión y puede tardar varios segundos. Debemos mostrar ese estado antes de ejecutar la acción sensible. Para probar los distintos resultados y errores, Apple permite configurar argumentos de lanzamiento en los esquemas de Xcode.

La utilidad está en la respuesta que diseñemos: explicar el riesgo, facilitar que la persona se detenga y añadir comprobaciones proporcionadas. Trust Insights aporta una señal adicional; la protección depende de cómo la integremos con el resto de la aplicación.