kovidgoyal/kitty · error

Ignoring encrypted rc command without a public key

Error message

Ignoring encrypted rc command without a public key

What it means

An encrypted remote-control command lacks the 'pubkey' field, so kitty cannot derive the shared secret to decrypt it. Note the code logs and continues (which will then fail on b85decode of the empty pubkey) — the message signals a malformed encrypted payload.

Source

Thrown at kitty/remote_control.py:64

def parse_cmd(serialized_cmd: memoryview, encryption_key: EllipticCurveKey) -> dict[str, Any]:
    # See https://github.com/python/cpython/issues/74379 for why we cant use
    # memoryview directly :((
    try:
        pcmd = json.loads(bytes(serialized_cmd))
    except Exception:
        log_error('Failed to parse JSON payload of remote command, ignoring it')
        return {}
    if not isinstance(pcmd, dict) or 'version' not in pcmd:
        log_error('JSON payload of remote command is invalid, must be an object with a version field')
        return {}
    pcmd.pop('password', None)
    if 'encrypted' in pcmd:
        if pcmd.get('enc_proto', '1') != RC_ENCRYPTION_PROTOCOL_VERSION:
            log_error(f'Ignoring encrypted rc command with unsupported protocol: {pcmd.get("enc_proto")}')
            return {}
        pubkey = pcmd.get('pubkey', '')
        if not pubkey:
            log_error('Ignoring encrypted rc command without a public key')
        d = AES256GCMDecrypt(encryption_key.derive_secret(base64.b85decode(pubkey)), base64.b85decode(pcmd['iv']), base64.b85decode(pcmd['tag']))
        data = d.add_data_to_be_decrypted(base64.b85decode(pcmd['encrypted']), True)
        pcmd = json.loads(data)
        if not isinstance(pcmd, dict) or 'version' not in pcmd:
            return {}
        delta = time_ns() - pcmd.pop('timestamp')
        if abs(delta) > 5 * 60 * 1e9:
            log_error(
                f'Ignoring encrypted rc command with timestamp {delta / 1e9:.1f} seconds from now.'
                ' Could be an attempt at a replay attack or an incorrect clock on a remote machine.'
            )
            return {}
    return pcmd


class CMDChecker:
    def __call__(self, pcmd: dict[str, Any], window: Optional['Window'], from_socket: bool, extra_data: dict[str, Any]) -> bool | None:
        return False

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Include the base85-encoded ephemeral public key in the 'pubkey' field
  2. Prefer using kitten's built-in ECDH handshake instead of constructing encrypted commands manually
Defensive patterns

Strategy: validation

Validate before calling

assert pcmd.get('encrypted') is True and pcmd.get('pubkey'), 'encrypted payload needs pubkey'

Type guard

def is_complete_encrypted_cmd(p: dict) -> bool:
    return all(k in p for k in ('pubkey', 'iv', 'tag', 'encrypted'))

Prevention

When it happens

Trigger: pcmd contains 'encrypted': true but no 'pubkey' key, hitting the `if not pubkey` branch in parse_cmd.

Common situations: Hand-built encrypted RC payloads missing fields, or a buggy/older client that omits pubkey.

Related errors


AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27). Data as JSON: /api/errors/5268f0859a865fde. Report an issue: GitHub.