mathiasbynens / dotfiles

:wrench: .files, including ~/.macos — sensible hacker defaults for macOS

Home Page:https://mths.be/dotfiles

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`defaults write` doesn't work on Safari on Mojave

chdiza opened this issue · comments

Is anyone else noticing that using defaults write com.apple.safari something-or-other doesn't work on Mojave?

I noticed that they seem to have moved Safari's preference plist so that it's now buried under ~/Library/Containers (sigh). So I tried replacing "com.apple.safari" with "-app safari", hoping that this would point defaults to the correct thing. (I found I had to do this with Preview a while back.)

But alas, it doesn't work.

If it isn't just me, I'll report this to Apple. Seems like a bad bug.

Same issue here

commented

For Safari you will have to change the command to use the property list file without the .plist extension with defaults:

defaults write ~/Library/Containers/com.apple.Safari/Data/Library/Preferences/com.apple.Safari AutoOpenSafeDownloads -bool true

There are other property lists as well in this path.

 $ la *.plist
-rw------- 1 tatsh staff    42 2018-05-13 07:44:40 com.apple.Safari.Extensions.plist
-rw------- 1 tatsh staff   103 2018-07-10 19:37:31 com.apple.Safari.SafeBrowsing.plist
-rw------- 1 tatsh staff    42 2018-05-11 12:03:35 com.apple.Safari.Support.plist
-rw------- 1 tatsh staff 11086 2018-10-11 19:26:37 com.apple.Safari.plist
-rw------- 1 tatsh staff   130 2018-09-17 21:45:30 com.apple.SafariBookmarksSyncAgent.plist
lrwxr-xr-x 1 tatsh staff    51 2018-07-12 04:00:53 com.apple.security.plist -> ../../../../../Preferences/com.apple.security.plist
lrwxr-xr-x 1 tatsh staff    58 2018-07-12 04:00:53 com.apple.security_common.plist -> ../../../../../Preferences/com.apple.security_common.plist

I presume almost all apps including Apple's are going in this direction, as this is what has been done on iOS especially since 11.

Apple always leaves hints regarding migrations:

 $ plutil -p com.apple.Safari.plist | fgrep -i migr
  "cloudBookmarksMigrationEligibilityDataInvalidated" => 0
  "cloudKitBookmarksMigrationRampState" => {
      "gmMigrationPercent" => 1000
      "internalMigrationPercent" => 1000
      "seedMigrationPercent" => 1000
  "DidAttemptToMigrateExtensionsPlistFromLegacyKeychain" => 1
  "DidMigrateDisabledPlugInsInfoToAllPlugInsInfo" => 1
  "DidMigrateExtensionSettingsToExtensionsDomain" => 1
  "DidMigrateNewBookmarkSheetToReadingListDefault" => 1
  "DidMigrateResourcesToSandbox" => 1
  "DidMigrateStartPageDefaultSidebarVisibility" => 1
  "DidMigrateTabsToLinksForReaderKey" => 1
  "DidMigrateToCoreSpotlightBasedHistorySearch" => 1
  "DidMigrateToMoreRestrictiveFileURLPolicy" => 1
  "DidMigrateWebKit1Preferences" => 1
  "MigratedIncludeDebugMenu" => 1
  "SearchProviderIdentifierMigratedToSystemPreference" => 1

That would've been my next attempt once I'm at my Mojave machine again. Good to know that something works. I wonder why I don't have to include that whole path for Preview.app; -app Preview causes defaults to write to the containerized pref.

Also, I still think this is a bug, because defaults read -app Safari ought to reveal the defaults for Safari. But on Mojave, it doesn't. (It reveals what's in ~/Library/Preferences/com.apple.safari, which Mojave now ignores.)

Any updates?
I’m surprised this doesn’t get much more traction, as it’s seriously hampering to macOS bootstrapping/automation routines. Moreover, it seems that Mail’s preferences have also been containerized. I can confirm that my defaults write scripts for Mail that used to work on High Sierra aren’t working anymore. @chdiza, my Preview scripts are still working but I haven’t changed a thing in them, so I believe Preview has yet to be migrated to the new preferences type. I think that a good way to check whether the prefs for an app were migrated is to do a simple terminal check: defaults write > a, change something in the app, and defaults write > b && diff a b. If the changes were caught by this, it probably means the prefs are in the old style.

Moreover, I have tried each and every of @Tatsh’s suggestions, to no avail. I get either The domain/default pair FOO does not exist when I do a defaults read, or Could not write domain BAR; exiting for defaults write.

@Tatsh's first solution worked for me. Probably because the file in question already existed, whereas it wouldn't with an absolutely fresh user account. I'd try touching that file first.

commented

This may be caused by permissions. On Mojave Mail is blocked from apps by default. In Bash you will see this by default:

 $ cd ~/Library/Containers/com.apple.mail
 $ ls
ls: cannot open directory '.': Operation not permitted

And defaults read -app Mail will only show these options:

{
    BundleCompatibilityVersion = 3;
    EnableBundles = 1;
    NSNavLastRootDirectory = "...";
    NSNavPanelExpandedSizeForOpenMode = "{720, 448}";
}

You need to add Bash (and maybe others like iTerm, Terminal, etc) to the Full Disk Access list. When you click +, use + + G to open the Go to folder dialog so you can pick items like Bash. You need to pick the exact one you are using. I am using MacPorts so everything is in /opt/local/bin for me.

security privacy-2018-11-05 20-18-38

Once you've done this, start a new shell (already running shells will not work) and type defaults read -app Mail and it will show all settings. It does not work for me in tmux (not sure why yet). Run this command in a bare shell.

 $ defaults read -app Mail | fgrep DisableSendAnimations
    DisableSendAnimations = 1;
commented

Regarding tmux, ensure it's in the allowed apps for Full Disk Access, restart the server (tmux kill-server), start a new session, and everything will work.

I can confirm that granting stuff Full Disk Access restores the correct behavior of defaults.

But what a PITA!! The point of scripted setups is to not have to manually enable a bunch of stuff first.

I tend to think that the full path to the containerized location is the right way to go.

Same here, adding Terminal and bash (and also Sublime Text 3, as I test stuff from there) to Full Disk Access allowed me to set defaults again! What a joy. Thanks @Tatsh. And while I’m at it, a few questions:

  1. Should I write the commands as defaults write -app FOO, or address the container directly? (as in defaults write ~/Library/Containers/com.apple.Safari/Data/Library/Preferences/com.apple.Safari.plist FOO -bool true
  2. For a given defaults command, how to tell when to use the -currentHost and -g options?
  3. I can confirm that giving elevated permissions to the aforementioned apps allowed me to set the com.apple.universalaccess axShortcutExposedFeatures settings. Weirdly enough, those preferences are yet to be containerized and I could at least read them, however without applying the said solution I just couldn’t write anything to them.
    Thanks!
commented

On 1, I don't think it will matter but because paths can change I think it's preferable to use -app.

On 2, -currentHost/-host is only for a situation where you share user profiles (roaming profiles) on a network. -g is for the global domain, same as writing NSGlobalDomain.

Thanks a lot for the input!

  1. For some apps, like Finder, using the -app doesn't work. What to do in cases like that?
  2. I use the latest version of bash, obtained using brew. I symlinked it from /usr/local/bin, and initially it worked, but after a while the permissions were revoked and when I checked the Security pane, there was a blank square for the bash item, instead of the familiar one for executables. How come?

Right, not all apps work with the -app invocation. (And it has always been thus, it's not a Mojave regression.) If memory serves, only applications that are located in either /Applications or ~/Applications---or at least are symlinked into one of those two---will work in this way. I'm unsure whether all apps that live or symlinkedly live there will work with -app.

I don't know what to say about the brewed bash, but it might be relevant that what's in /usr/local/bin is a symlink to bash and not bash itself. Perhaps using /usr/local/opt/bash/bin/bash will work, because though elements of that path are symlinks, the endpoint isn't.

I used to use -app only when not using it would fail (i.e., containerized on pre-Mojave), but I think I'm now going to never use -app (and where necessary use the full path through the container), at least for scripting. The point of scripting these is to run them on a fresh user (maybe even without being logged into the GUI), which conflicts with the rigamarole of manually granting Full Disk Access.

It should be easy to create a wrapper script that will automatically prepend the container-y path for any domain that is antecedently known to live in a container.

@chdiza,

  1. What do you think would be the quickest way to authorize all of those apps?
    There's no escaping from having to drag them manually to the Full Disk Access (and Accessibility, if necessary) panes, but I'm hoping to at least make the process much quicker. Obviously navigating to each app's folder and dragging time and again is too much, so I was thinking about writing a script that either symlinks all of those apps to a given folder, or tags them uniquely.
    Both ways have their caveats: for the former, dragging a symlink to an app and not the app itself could be problematic; and as for the latter — I have yet to find a CLI way to open a Finder window that would display all files with a specific tag (similar to click on the sidebar or doing a Spotlight search). What do you think?

  2. The point of scripting these is to run them on a fresh user (maybe even without being logged into the GUI), which conflicts with the rigamarole of manually granting Full Disk Access.

Are you implying there's a way to access of those preferences without manually authorizing the aforementioned apps? (or, at least, accessing them BEFORE authorizing them).

  1. It should be easy to create a wrapper script that will automatically prepend the container-y path for any domain that is antecedently known to live in a container.

I have noticed that ever since granting elevated permissions to bash, Terminal etc., all of the preferences are living under the non-containerized path (com.apple.Safari) again, just like they used to pre-Mojave. As far as I can see, there's no need to address the containerized path — but correct me if I'm wrong.

Thanks!

Are you implying there's a way to access of those preferences without manually authorizing the aforementioned apps?

No. There used to not be a need for this, and now there is, and that's why I'm complaining.

I have not noticed that everything lives where it used to. I haven't checked in a while, but last time I checked, this was not the case. The initial (failed) attempt to do defaults write as before wrote plists in the original location, but Safari was not actually using them.

To work around this a bit more, is anyone aware of a scriptable way to put an application into the "Full Disk Access" list? I've seen other applications add themselves into Settings -> Security & Privacy -> Privacy -> Accessibility before. Of course they are by default unchecked, but the user gets prompted to unlock and enable them, which is better than nothing. Would love to find a way to script that before running my dotfiles.

commented

No, as tccutil only provides the reset ability for a given service. Perhaps a custom app can use the private TCC framework (once reverse engineered) to write to the database correctly. Previous utilities like tccutil.py are blocked by SIP.

These are the services theoretically:

Accessibility
AddressBook
All
AppleEvents
Calendar
Camera
Facebook
LinkedIn
Liverpool
Location
MediaLibrary
Microphone
Photos
PhotosAdd
PostEvent
Reminders
ShareKit
SinaWeibo
Siri
SystemPolicyAllFiles
SystemPolicyDeveloperFiles
SystemPolicySysAdminFiles
TencentWeibo
Twitter
Ubiquity
Willow

SystemPolicyAllFiles is probably the one.

I'm having a hard time keeping up with all the macOS changes. I'm attempting to allow NON-admins the ability to manipulate Privacy & Security Settings on Mojave+ using commands like:

security authorizationdb write system.preferences.SecurityPrivacy allow
security authorizationdb write system.preferences allow
security authorizationdb write system.preferences.security allow

Is there a new way? Do I need to whitelist terminal with full disk access? Any help would be much appreciated.

Makes sure to give Terminal Full Access (I recommend you do this temporarily). Then commands like "defaults write com.apple.mail DisableInlineAttachmentViewing -boolean yes" may work

image

using the Preferences app to enable Terminal, bash, etc somewhat defeats the automate-ability of a bootstrapping script to automate preferences. Is there a way to automate this part while maintaining SIP enabled?

commented

using the Preferences app to enable Terminal, bash, etc somewhat defeats the automate-ability of a bootstrapping script to automate preferences. Is there a way to automate this part?

Not known at this time. Maybe I'll find a way (while keeping SIP enabled): https://github.com/Tatsh/tccx

How can a script be made to modify the Security & Privacy settings? I can't seem to find a .plist anywhere on disk that stores these settings. How are they being persisted?

commented

How can a script be made to modify the Security & Privacy settings? I can't seem to find a .plist anywhere on disk that stores these settings. How are they being persisted?

Can't be done that way, at least not with SIP enabled. There is tccutil which can only work without SIP.

There is a way to do it with configuration profiles: Configuration Profile Reference (see page 64). Example

I have documented what is known about TCC here.

@Tatsh Actually... I found a way :D

Turns out that, rather than using a .plist, Apple uses a SQLite database, TCC.db. There are two of these, one in /Library/Application Support/com.apple.TCC/TCC.db and one at the same path within each user's ~/Library.

You can view & edit this with any software that's capable of reading/writing to SQLite db format, like JetBrains IDEs for example (as pictured below, I just opened up TCC.db within JetBrains AppCode IDE and added the main schema).

Writing a script to read & write to/from this db should be pretty straightforward for anyone who knows their way around SQLite databases.

Screen Shot 2020-09-10 at 11 53 24 AM

commented

Those files are SIP protected. The OS will know if they get modified and then restore the old version from a snapshot.

Those files are SIP protected. The OS will know if they get modified and then restore the old version from a snapshot.

Jeez. I wonder how Apple expects us to configure Continuous Integration nodes with Xcode etc. to work in a Jenkins pipeline? Do they expect us to log into each node individually to set these options...??

commented

It seems they want you to use Apple Remote Desktop to configure whatever can't be done with CLI.