{"record":{"id":"35fde4cb1bdd0d83","repo":"kovidgoyal/kitty","slug":"ignoring-encrypted-rc-command-with-unsupported-pro","errorCode":null,"errorMessage":"Ignoring encrypted rc command with unsupported protocol: {pcmd.get(\"enc_proto\")}","messagePattern":"Ignoring encrypted rc command with unsupported protocol: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kitty/remote_control.py","lineNumber":60,"sourceCode":"def encode_response_for_peer(response: Any) -> bytes:\n    return b'\\x1bP@kitty-cmd' + json.dumps(response).encode('utf-8') + b'\\x1b\\\\'\n\n\ndef parse_cmd(serialized_cmd: memoryview, encryption_key: EllipticCurveKey) -> dict[str, Any]:\n    # See https://github.com/python/cpython/issues/74379 for why we cant use\n    # memoryview directly :((\n    try:\n        pcmd = json.loads(bytes(serialized_cmd))\n    except Exception:\n        log_error('Failed to parse JSON payload of remote command, ignoring it')\n        return {}\n    if not isinstance(pcmd, dict) or 'version' not in pcmd:\n        log_error('JSON payload of remote command is invalid, must be an object with a version field')\n        return {}\n    pcmd.pop('password', None)\n    if 'encrypted' in pcmd:\n        if pcmd.get('enc_proto', '1') != RC_ENCRYPTION_PROTOCOL_VERSION:\n            log_error(f'Ignoring encrypted rc command with unsupported protocol: {pcmd.get(\"enc_proto\")}')\n            return {}\n        pubkey = pcmd.get('pubkey', '')\n        if not pubkey:\n            log_error('Ignoring encrypted rc command without a public key')\n        d = AES256GCMDecrypt(encryption_key.derive_secret(base64.b85decode(pubkey)), base64.b85decode(pcmd['iv']), base64.b85decode(pcmd['tag']))\n        data = d.add_data_to_be_decrypted(base64.b85decode(pcmd['encrypted']), True)\n        pcmd = json.loads(data)\n        if not isinstance(pcmd, dict) or 'version' not in pcmd:\n            return {}\n        delta = time_ns() - pcmd.pop('timestamp')\n        if abs(delta) > 5 * 60 * 1e9:\n            log_error(\n                f'Ignoring encrypted rc command with timestamp {delta / 1e9:.1f} seconds from now.'\n                ' Could be an attempt at a replay attack or an incorrect clock on a remote machine.'\n            )\n            return {}\n    return pcmd\n","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kitty/remote_control.py#L42-L78","documentation":"An encrypted remote-control command specified an enc_proto value different from the RC_ENCRYPTION_PROTOCOL_VERSION kitty supports, so it is dropped. This guards against protocol-version mismatch between client and server.","triggerScenarios":"parse_cmd sees 'encrypted' in the payload and pcmd['enc_proto'] (default '1') != RC_ENCRYPTION_PROTOCOL_VERSION — e.g. newer kitten client talking to older kitty.","commonSituations":"kitten/kitty version skew after a partial upgrade, or a custom client hard-coding the wrong enc_proto.","solutions":["Upgrade kitty and kittens together so both use the same RC encryption protocol version","Use matching kitten binary from the same install as the running kitty"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"from kitty.constants import RC_ENCRYPTION_PROTOCOL_VERSION  # match on both sides\npcmd['enc_proto'] = RC_ENCRYPTION_PROTOCOL_VERSION","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Upgrade kitty and kittens together (same package/version)","Never hand-roll enc_proto values"],"tags":["kitty","remote-control","encryption","version-mismatch"],"backgroundTag":"protocol-version-mismatch","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}