Skip to Content
Internal ScanningRecorded Login Secrets

Recorded Login Secrets

Recorded Login scans may need additional credentials at replay time. For TOTP-based MFA you supply an otpauth_url seed and the scanner generates valid one-time codes during the login replay.

These secrets are stored as Kubernetes Secrets in the scanner namespace. You can manage them directly with kubectl or through the Scanner API.

Secrets are read at scan time, so updates take effect on the next scan. No pod restarts are needed.

Prerequisites

You must have a recorded login already configured in the Detectify UI. During the initial recording, log in normally — including entering your real TOTP code.

Note: The scanner does not automatically detect the TOTP step. After completing the recording, you must manually edit the login file to replace the recorded manual entry with the appropriate MFA command. This allows the scanner to generate a valid code from your configured secret during replay.

How to Edit the TOTP Step

Locate the section in your login file (.trail) where the TOTP code was entered.

Depending on whether you entered the code into a single field or split across multiple fields, what to replace it with differs slightly — see below.

The example selectors below use #id-of-mfa-input for readability, but selectors can be any querySelector. Match whatever was captured in the recording.

If you entered your code into one single box, look for the UserAction.input command for the MFA input and replace it with an ExternalInput.multiFactorAuthSingleField command:

Recorded Action:

{ "type": "UserAction", "version": "1.0", "command": "input", "selectors": [ ["css=#id-of-mfa-input"] ], "value": "123456" // MFA code entered during recording }

Replace with:

{ "type": "ExternalInput", "version": "2.0", "command": "multiFactorAuthSingleField", "selectors": [ ["css=#id-of-mfa-input"] ], "values": [] }

Managing Secrets

There are two ways to manage Recorded Login Secrets:

  • directly with kubectl, or
  • through the Scanner API.

Both end up as Kubernetes Secrets in the scanner namespace, the Scanner API simply creates and updates those secrets on your behalf, so you can mix and match as suits your workflow.

Candidate secrets are discovered by the label app=recorded-login. The audience is declared via annotations (annotations rather than labels so wildcard patterns containing * remain valid).

apiVersion: v1 kind: Secret metadata: name: recorded-login-example namespace: scanner labels: app: recorded-login annotations: # Set any of the following to scope the secret: # recorded-login.detectify.com/profile-token: "your-scan-profile-token" # recorded-login.detectify.com/fqdn: "app.example.com" # recorded-login.detectify.com/wildcard: "*.example.com" # recorded-login.detectify.com/team-token: "your-team-token" type: Opaque stringData: otpauth_url: "otpauth://totp/example?secret=JBSWY3DPEHPK3PXP&digits=6"

Apply it:

kubectl apply -f recorded-login-secret.yaml

Or create a TOTP secret with commands:

kubectl create secret generic recorded-login-example \ -n scanner \ --from-literal=otpauth_url='otpauth://totp/example?secret=JBSWY3DPEHPK3PXP&digits=6' kubectl label secret recorded-login-example -n scanner app=recorded-login kubectl annotate secret recorded-login-example -n scanner \ recorded-login.detectify.com/team-token='your-team-token'

How Secrets Are Matched

Each secret declares its audience, i.e. which scans it applies to. The same secret can be used for multiple targets/domains, but each scan can only use one secret.

Matching priority, highest first:

  1. profile-token — exact scan profile token
  2. fqdn — exact hostname
  3. wildcard — e.g. *.example.com
  4. team-token — fallback for the whole team

If multiple wildcard secrets match the domain (e.g. *.example.com and *.foo.example.com), the most narrow is used (*.foo.example.com).

Last updated on