{"record":{"id":"5add1c6f3ce6d7ff","repo":"kovidgoyal/kitty","slug":"incorrect-permissions-on-pwfile-0o-mode-03o","errorCode":null,"errorMessage":"Incorrect permissions on pwfile: 0o{mode:03o}","messagePattern":"Incorrect permissions on pwfile: 0o(.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"kittens/ssh/utils.py","lineNumber":172,"sourceCode":"        shm.flush()\n        atexit.register(shm.close)  # keeps shm alive till exit\n        get_boss().atexit.shm_unlink(shm.name)\n    return shm.name\n\n\ndef read_data_from_shared_memory(shm_name: str) -> Any:\n    import json\n    import stat\n\n    from kitty.shm import SharedMemory\n\n    with SharedMemory(shm_name, readonly=True) as shm:\n        shm.unlink()\n        if shm.stats.st_uid != os.geteuid() or shm.stats.st_gid != os.getegid():\n            raise ValueError(f'Incorrect owner on pwfile: uid={shm.stats.st_uid} gid={shm.stats.st_gid}')\n        mode = stat.S_IMODE(shm.stats.st_mode)\n        if mode != stat.S_IREAD | stat.S_IWRITE:\n            raise ValueError(f'Incorrect permissions on pwfile: 0o{mode:03o}')\n        return json.loads(shm.read_data_with_size())\n\n\ndef get_ssh_data(msgb: memoryview, request_id: str) -> Iterator[bytes | memoryview]:\n    # Unfortunately we cannot use EOF (\\x04) to flush the kernel line buffer\n    # because ssh with controlmasters mangles EOF replacing it with null bytes\n    from base64 import standard_b64decode\n\n    yield b'\\nKITTY_DATA_START\\n'  # to discard leading data\n    try:\n        msg = standard_b64decode(msgb).decode('utf-8')\n        md = dict(x.split('=', 1) for x in msg.split(':'))\n        pw = md['pw']\n        pwfilename = md['pwfile']\n        rq_id = md['id']\n    except Exception:\n        traceback.print_exc()\n        yield b'invalid ssh data request message\\n'","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kittens/ssh/utils.py#L154-L190","documentation":"read_data_from_shared_memory() requires the ssh kitten's password shm file to have exactly mode 0600 (S_IREAD | S_IWRITE, i.e. owner-only read/write). stat.S_IMODE(shm.stats.st_mode) is compared to 0o600 and any other permission bits raise ValueError('Incorrect permissions on pwfile: 0o...'). This prevents other users on the machine reading the transmitted password.","triggerScenarios":"get_ssh_data() reads a pwfile in /dev/shm whose mode is not 0600 — e.g. created with a permissive umask, chmod'ed to 0644/0666 afterwards, restored from a backup with wrong modes, or written by a non-kitty process that uses default shm creation modes.","commonSituations":"A restrictive/permissive umask in the shell that launched kitty; another tool or script pre-creating or copying the shm file with different permissions; hardened or custom tmpfs mount options; debugging sessions where the file was touched manually.","solutions":["Remove the offending file (`rm /dev/shm/kitty-ssh-*` style names) so kitty recreates it with mode 0600, then retry.","Check your umask; start kitty with a normal umask (0022) so the shm file is created 0600.","Do not chmod or copy pwfiles in /dev/shm; if you backed them up for debugging, delete them.","If it persists, verify no other process is creating the file and report/check the kitty version for shm creation regressions."],"exampleFix":"# before\nls -l /dev/shm/kitty*   # -rw-r--r--  -> ValueError: Incorrect permissions on pwfile: 0o644\n\n# after\nrm /dev/shm/kitty*\nkitten ssh host          # file recreated with 0600","handlingStrategy":"validation","validationCode":"import os, stat, glob\n\ndef clean_bad_mode_shm() -> None:\n    for p in glob.glob('/dev/shm/kitty*'):\n        try:\n            mode = stat.S_IMODE(os.stat(p).st_mode)\n            if mode != 0o600:\n                os.unlink(p)\n        except FileNotFoundError:\n            pass","typeGuard":null,"tryCatchPattern":"try:\n    data = read_data_from_shared_memory(name)\nexcept ValueError as e:\n    if 'Incorrect permissions on pwfile' in str(e):\n        remove_stale_pwfile(); retry_once()  # kitty recreates with 0600\n    else:\n        raise","preventionTips":["Never chmod or manually create files kitty will use in /dev/shm.","Start kitty with a standard umask (0022).","After restoring backups or debugging /dev/shm, delete copied kitty pwfiles."],"tags":["kitty","ssh","shared-memory","file-permissions","security"],"backgroundTag":"ipc-file-permission-check-failed","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}