Closed bytesoverflow closed 3 years ago
+1 According to Console:
This app has crashed because it has a hardened runtime and attempted to access privacy-sensitive data without an entitlement indicating its intent to access this data. The app must have the 'com.apple.security.device.camera' entitlement.
@tobydeh How are you trying to run this? I found that it works fine running in the built-in Terminal app, but has problems running in iTerm2
The problem occurs when imagesnap is run from another application. I've had to build a new tool which requests permission to use the camera (similar to location services).
Do you have that in a repo somewhere? I'd be curious to see how it's done. For now I've just wrapped the binary in an automator app, and that seems to be working nicely.
I am having the same problem. Running in Terminal I get a "Terminal wants to access your camera" dialogue on first execution. With iTerm2 I am not getting the dialogue and hence execution fails.
Camera access can be controlled in System Preferences > Security > Camera. But unlike "Full Disk Access" the "Camera" list has no option to add new applications to it.
This has been addressed in iTerm2: https://gitlab.com/gnachman/iterm2/issues/7194
The latest beta re-prompts for the camera permission.
I think this resolves this issue.
It works for me when I run it in Terminal, since I've approved the pop-up to give access to the camera.
However I doesn't work through ssh. I get the following error:
Abort trap: 6
I thought this was because the keychain is not unlocked with an ssh connection. So I did:
security unlock-keychain ~/Library/Keychains/login.keychain
(enter password)
eval `ssh-agent -s`
but it didn't help.
Now I see that it's most likely because I explicitly have to give access to an app to use the camera.
Is there a way to do this for ssh connections?
I found a way to get it to work with ssh.
Create imagesnap.sh with the following content and make it executable:
imagesnap -w 1 macCam.png
run:
open -a Terminal.app imagesnap.sh
This will create a new Terminal window each time you run the command.
I've created a bash function to automatically kill the Terminal after the photo is taken.
function cam() {
open -a Terminal.app imagesnap.sh
sleep 3
killall Terminal
}
The sleep is necessary, otherwise the Terminal window is killed before it can take the picture. The problem with this is it will close every other Terminal instance that you were working in, but I couldn't find a way to only close the last window.
You should use osascript -e 'tell application "Terminal" to quit" || killall Terminal
instead of just killall Terminal
. That way you'll try to gracefully quit the app before resorting to the bruteforce method.
Weird thing that I noticed is that imagesnap
(v0.2.5, because v0.2.6 is broken) doesn't work with zsh
, and with bash in iTerm it sometimes doesn't work either: an image file is created, but it's all black. Using imagesnap
in bash
in Terminal.app is fine, however.
Same goes for putting imagesnap into a shell script: an image file is created, but it's all black.
Not a good thing if you want to use imagesnap
for taking stealth pictures, e.g. in case your Mac has been stolen. In those cases you can't open Terminal etc. This is so pathetic, Apple.
I used to take screenshots with imagesnap through ssh - but using the app approach forcing me to be logged in into the mac - that's problem - I really don't the think it's useful. I'm wonder why the programmer has not released a new version of imagesnap incorporating the right security entitlement - it should be enough?
There's an easy solution. Create an AppleScript in Script Editor, e.g. this one
do shell script "! [[ -d ~/.cache/Snapper ]] && /bin/mkdir -p ~/.cache/Snapper"
set theDate to (do shell script "/bin/date -u | /usr/bin/sed 's/ /-/g'")
do shell script "/usr/local/bin/imagesnap -w 2 ~/.cache/Snapper/snap-" & theDate & ".jpeg"
…then don't save, but export as an application, in this case with the filename "Snapper.app", but don't codesign yet.
Open the Info.plist, add key LSUIElement
with boolean true
, change the BundleID, if you want, change the bundle icon, if you want etc. Then save and codesign, e.g. with: codesign --sign "<YourCertificateID>" --force --deep -i "<BundleID>" /Applications/Snapper.app
Then you can run it manually: macOS will probably ask you for camera access. Then (I assume!) you can also run it while being remotely logged in with open -a Snapper
or with open -b <BundleID>
or using the full path with open /Applications/Snapper.app
… and of course you can also make one of those into an alias, e.g. snapper
.
PS: I've tested the same procedure with app bundles exported from Automator, which does not work. Running a Platypus application doesn't work either.
Hi JayBrown, Do I need to codesign it?
You can try it without code-signing first. But it's possible that macOS will then ask you for camera access every time it launches. But if you have a developer account under your Apple ID and Xcode installed, you can just use the development certificate ("Mac Developer:
PS: I haven't tested it with an adhoc-signature, for which you would have to execute codesign --sign - --force --deep /Applications/Snapper.app
(you don't need an actual certificate for adhoc-signing, so maybe you want to try that first).
PPS: another thing… if codesign
prints an error about detritus, you need to execute xattr -cr /Applications/Snapper.app
first before code-signing.
One additional piece of information: my AppleScript wrapper didn't wind up in the camera access list until reboot. And I had to allow camera access again after reboot too. I'll test this again as soon as I can. EDIT: did a second reboot, and camera access is baked in for the wrapper, so after one reboot, this workaround should be sustainable, and the only thing to check now is if the wrapper also works after remote ssh login.
Hi I get this error when trying signing - any ideas? codesign --sign - --force --deep ./snapper.app/ 2019-01-26 10:13:12.323 codesign[47659:7298941] There was an error parsing the Info.plist for the bundle at URL <0x7fe0cae003d0>: NSCocoaErrorDomain - 3840 2019-01-26 10:13:12.325 codesign[47659:7298941] There was an error parsing the Info.plist for the bundle at URL <0x7fe0cac0b1a0>: NSCocoaErrorDomain - 3840 xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun ./snapper.app/: the codesign_allocate helper tool cannot be found or used In subcomponent: /Users/avdr/snapper.app/Contents/MacOS/applet
You probably haven't installed Xcode or the Command Line Tools yet. For code-signing you only need the latter; install them with xcode-select --install
. (It's a couple of MB that need to be downloaded.) You can always check your developer path with xcode-select -p
. This path will change (or will have to be changed manually), if you also install Xcode at some point.
Then I get this: 019-01-26 15:37:30.686 codesign[49732:7484157] There was an error parsing the Info.plist for the bundle at URL <0x7fabb940c4c0>: NSCocoaErrorDomain - 3840 2019-01-26 15:37:30.688 codesign[49732:7484157] There was an error parsing the Info.plist for the bundle at URL <0x7fabb9412200>: NSCocoaErrorDomain - 3840 2019-01-26 15:37:30.702 codesign[49732:7484157] There was an error parsing the Info.plist for the bundle at URL <0x7fabb9412ac0>: NSCocoaErrorDomain - 3840
The reason could be that the Info.plist is corrupted or incorrectly formatted. That's why I tend to use GUI tools when editing Info.plist files (with PrefEdit by Marcel Bresink).
This is my Info.plist xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleAllowMixedLocalizations</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>applet</string>
<key>CFBundleIconFile</key>
<string>applet</string>
<key>CFBundleIdentifier</key>
<string>com.apple.ScriptEditor.id.Snapper</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Snapper</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>aplt</string>
<key>LSMinimumSystemVersionByArchitecture</key>
<dict>
<key>x86_64</key>
<string>10.6</string>
</dict>
<key>LSRequiresCarbon</key>
<true/>
<key>NSAppleEventsUsageDescription</key>
<string>This script needs to control other applications to run.</string>
<key>NSAppleMusicUsageDescription</key>
<string>This script needs access to your music to run.</string>
<key>NSCalendarsUsageDescription</key>
<string>This script needs access to your calendars to run.</string>
<key>NSCameraUsageDescription</key>
<string>This script needs access to your camera to run.</string>
<key>NSContactsUsageDescription</key>
<string>This script needs access to your contacts to run.</string>
<key>NSHomeKitUsageDescription</key>
<string>This script needs access to your HomeKit Home to run.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This script needs access to your microphone to run.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This script needs access to your photos to run.</string>
<key>NSRemindersUsageDescription</key>
<string>This script needs access to your reminders to run.</string>
<key>NSSiriUsageDescription</key>
<string>This script needs access to Siri to run.</string>
<key>NSSystemAdministrationUsageDescription</key>
<string>This script needs access to administer this system to run.</string>
<key>WindowState</key>
<dict>
<key>bundleDividerCollapsed</key>
<true/>
<key>bundlePositionOfDivider</key>
<real>0.0000000000000000</real>
<key>dividerCollapsed</key>
<false/>
<key>eventLogLevel</key>
<integer>2</integer>
<key>name</key>
<string>ScriptWindowState</string>
<key>positionOfDivider</key>
<real>388.0000000000000000</real>
<key>savedFrame</key>
<string>244 200 700 672 0 0 1680 1027 </string>
<key>selectedTab</key>
<string>description</string>
</dict>
<key>LSUIElement</key>
<true/>
</dict>
</plist>
And? Has it worked out for you? Incl. ssh?
I think I am encountering the same problem when I run imagesnap in a LaunchDaemon. Running imagesnap in a script and running imagesnap directly work fine, but it fails when calling the script from a launch daemon.
I tried wrapping it in an automator .app and calling the .app from the LaunchDaemon but that didn't have any effect.
I opened a stackoverflow question about it but maybe it's more relevant here.
Global daemons run as root, and if you're correct that background root processes don't have access to the camera, at least not out of the gate, you might try to call the Automator app under the logged in user instead of root.
user_id=$(id -u $(who | awk '/console/{print $1}'))
will get you the ID of the logged-in user (only regular logins, i.e. "moved on console"), and then you can launch the Automator app with
launchctl asuser $user_id open -a Snapper
.
But I can't promise it'll work, because I haven't tested it. Maybe the system will detect that the open command originally goes back to a root process, and then it will fail too. (?)
EDIT: in my case, using an Automator app didn't work anyway… it only worked with app exported from the ScriptEditor. (Maybe you should try that first.)
EDIT2: it might also fail, if the user has never run the imagesnap wrapper app before; then he would need to allow camera access first.
One additional piece of information: my AppleScript wrapper didn't wind up in the camera access list until reboot. And I had to allow camera access again after reboot too. I'll test this again as soon as I can. EDIT: did a second reboot, and camera access is baked in for the wrapper, so after one reboot, this workaround should be sustainable, and the only thing to check now is if the wrapper also works after remote ssh login.
I tried to run imagesnap remotely but It not works. Isight can blink green light but the prompt freeze.. So the image capture not works. Running locally it works perfect.
I think maybe some Mojave security rules are blocking running outside console.
Do you know how to run imagesnap from remote ssh ?
Did you call imagesnap directly, or did you run a wrapper application?
(Note: I haven't been able to test the ssh context yet.)
Did you call imagesnap directly, or did you run a wrapper application?
(Note: I haven't been able to test the ssh context yet.)
I just did a remote ssh after that run ./imagesnap.... Isight blinks green but imagesnap process freeze. I have to perform a ctrl+c . There isn't any image captured.
Can you try it? Do have the same behavior ? Any clue how to run it remotely ?
Author here: I appreciate everyone trying to find a solution to the permissions problem. Obviously it's a privacy issue that we're working against. I'm not familiar with any new code-signing that Apple wants, but I'm open to any direction people have.
Any news? Thanks
I can only confirm that imagesnap works "in person" but if I ssh into a box I get "Abort trap: 6" which I'm guessing is from this issue. The first time I run imagesnap "in person" (that is, running it in Terminal on the computer I'm in front of), osx prompts me if I want to give Terminal access to the camera. I haven't tracked down anything further.
10.14.6 (18G87) Here.
I created an applescript application with the following:
do shell script "/usr/local/bin/imagesnap -w 1 /Users/mogitzme/Desktop/[backtick]date +%m%d%y-%H%M%S[backtick].png"
*(replaced actual backtick with '[backtick]' as to not confuse markup on this post.
Ran it locally and approved camera
open Desktop/ImageSnapper.app
Then I was able to run it from a remote ssh session with same command above. Anytime I modified the applescript application, it had to be re-approved.
Have not tried rebooting or logging out from the console yet to see if it breaks, but looks like the wrapper approach is workable.
I've now finally managed to confirm that this works: code-signed and TCC-approved AppleScript application calling imagesnap > ssh-login as admin… ran the app with open -a Snapper
, and it worked flawlessly
ImageSnap doesn't seem to work with Mojave. Is it something to do with the new hardened runtime?