Fucking Apple

I probably ask this every time I "upgrade" macOS, but how the fuck do I simulate a keystroke from cron on 10.15? It's works when I do it from Terminal but it's saying "36:48: execution error: File permission error. (-54)" from an ssh shell or crontab.

I've tried adding everything I can think of to "System Preferences / Security / Privacy / Accessibility" including osascript, cron, launchd and System Events.

E.g., osascript -e 'tell application "System Events" to key code 100'

The only maybe-relevant thing I can see in the relentless firehose that is the system log is: "spawn_via_launchd() failed, errno=1 label=[0x0-0x566566].com.apple.systemevents path=/System/Library/CoreServices/System Events.app/Contents/MacOS/System Events flags=0"

Remember when programs fought for the users instead of against them? Yeah, neither do I.

Tags: , , , ,

13 Responses:

  1. Drew says:

    I often run into issues with shell or python scripts getting the com.apple.quarantine attribute added to the file for some reason. I then have to run xattr -d com.apple.quarantine /path/to/script

    • Waider says:

      Not relevant to this post, but: com.apple.quarantine is attached by Safari (and, who knows, maybe some other Apple-internal HTTP fetch thingy) to things you download. If you've ever seen the dialog box that says "you downloaded this thing from the internet, are you sure you want to run it?", that's the GUI telling you about the com.apple.quarantine attribute, and saying yes to that dialog removes the attribute in passing. For a script that isn't downloaded (i.e. wrote it yourself, copied it from one machine to another, etc.) you should not see this attribute.

  2. dzm says:

    Working for me after granting some random things. What I did:

    ssh into my own local machine ( ssh me@127.0.0.1 )

    Run your command ( osascript -e 'tell application "System Events" to key code 100' )

    Got a different error than you did:
    36:48: execution error: System Events got an error: osascript is not allowed to send keystrokes. (1002)

    I went to System Prefs -> Security -> Privacy -> Accessibility and added 'osascript' (clicked the "+", the navigated to /usr/bin and selected it directly).

    Ran you command again. Got a GUI prompt:
    >“sshd-keygen-wrapper“ wants access to control “System Events.app“. Allowing control will provide access to documents and data in “System Events.app“, and to perform actions within that app.

    Returned to System prefs -> Security -> Privacy -> Accessibility

    sshd-keygen-wrapper was waiting in the list already waiting to be granted the magic check-mark.

    Now when I run your command I get:
    # osascript -e 'tell application "System Events" to key code 100'
    ^[[19~

    and my terminal throws a terminal bell.

    I don't know why my results are different from yours, but I THINK that if you find the secret to that initial "file permissions" error the rest of it will fall into place. Sorry I can't help solve that first step.

    • Drew says:

      Definitely check the script with xattr if you have the quarantine flag, you’ll get permission denied.

      • jwz says:

        My example was from the command line. There's no script to have an xattr on it.

        • Matt M says:

          Did you give Terminal Full Disk Access in Security & Privacy >> Privacy? It might also be that Script Editor needs the permissions. I had a lot of scripts fail until I gave them permission.

          • dzm says:

            Shouldn't make any difference when using SSH to log into a machine. At that point your active program isn't Terminal.

            But ... good point is general. In checking my list of "Full Disk Access" programs I see that at some point I granted sshd full disk access (I also see iTerm3 there, but again - I don't think that is relevant to the SSH case). jwz, do you get past the permission error if you grant sshd (I've tried removing the access but see no difference in behavior).

            For me the secret sauce is both <osascript and sshd-keygen-wrapper having access granted in "Accessibility". If either of them are disabled then I get the "osascript is not allowed to send keystrokes" error, but no permutation has thus far got me the file permission error jwz is reporting.

    • jwz says:

      Well, I did who-knows-what set of fuckery, mostly unrelated, and somehow finally got to your state where it asked about sshd-keygen-wrapper. I don't know what did it.

      But here's something else I've noticed, and I think that 10.13 and 10.14 also intermittently did this:

      ssh to the machine as desktop-user@machine -- osascript works.
      ssh to the machine as other-user@machine, then "sudo -s", then "su desktop-user" -- some osascript things work and some do not.

      • Waider says:

        That... sounds like session stuff. As in, the desktop user has an established session and you're trying to do things that require access to that session, and the process of looping through su doesn't give you access to the session because you're in a different tree of processes or some such. I recall using launchctl with bsexec or asuser to attempt to get around this (dim recollection of wanting to pop up a notification or message box from some context, which required access to the desktop session) but I see from the current manual page that those are now "legacy" options and I've no recollection if any of it worked when I tried.

        There's one other thing in this space I've come across: the prompt to grant $executable access to things may only happen once, and if you deny it, you never get prompted again, necessitating manual fiddling to grant that access. I presume this is Apple's attempt to avoid the Windows version of same where it prompts you repeatedly.

        (as an aside, the launchctl manual page has always been a barrel of snark, telling you about options that were not implemented correctly and/or didn't work the way people thought and the like)

        • jwz says:

          But how is this session info communicated down the tree? It's not through environment variables. Is it an inherited file descriptor or something?

          Probably relatedly, here's some new 10.15 fuckery that didn't happen in 10.14: I monitor things with nagios, and nrpe, when launched by launchd, ends up running a shell script I wrote that wants to examine the files in some directory.

          Well. Run that script manually as user nagios, it's fine. Let nrpe run it and:

          ls /Volumes/Archives
          ls: Archives: Operation not permitted

          And yet:

          ls -ldF@ /Volumes/Archives
          drwxr-xr-x@ 21 icecast icecast 672 Apr 2 23:22 /Volumes/Archives/
          com.apple.BootInfo 16

          • Waider says:

            How it's inherited is straying seriously into territory I don't know, because I took my usual approach of "grasp the bare minimum and then hit things until something works", but I'm gonna guess it is some form of IPC that's either an inherited file descriptor or some magical Mach ports thing.

            For the nagios/nrpe problem, you may be running into sandboxing issues (akin to SELinux or AppArmour, if you've ever tinkered with those). This may again come down to playing whack-a-mole with the full-disk-access permissions window. You can find sandboxing errors in the system log (some show up in dimes; possibly also /var/log/system.log if you're lucky, log show --last 1h --style syslog --debug --predicate 'senderImagePath == "/System/Library/Extensions/Sandbox.kext/Contents/MacOS/Sandbox"' or the like if you're not) and in theory dropping things into /Library/Sandbox/Profiles allows you to reconfigure sandboxes appropriately. But that's a whole other file format to figure out.

            (yes, basically I'm useless to you at this point, but I felt a reply was at least the courteous thing to do.)

            • jwz says:

              Aha, there was some more shit that needed to be clicked on in "Full Disk Access", including rsync and nrpe. I also had to add /usr/sbin/cron by hand, and then restart the process.

            • Waider says:

              "dimes".

              I typed "dmesg", it got helpfully corrected to "dimes", I fixed it, and then, I dunno. I hit space or something, and it got corrected again and I didn't notice.