Category Archives: AppleScript

Mojave: not authorized to send Apple events

If you’re suffering from error messages like the one above after upgrading to Mojave, welcome to macOS’s new “User Data Protections”. In this post we’ll explain what they are and how to deal with them.

That error’s produced when the app your script is targeting (in this example, System Events) has been denied access to one of the areas now protected in Mojave.

Here’s the list of places which are no longer accessible programmatically without user approval on 10.14:

If the app you’re targeting in your script – or the script runner itself – is trying to access any of those 12 locations, you’ll likely either get the error shown at the top of this post, or some other failure. 

The official way of dealing with this is to add the application to System Preferences’ new ‘Full Disk Access’ section in the Privacy pane:

At least that’s the theory, but you might find that you’ve tried that and things are still not working. If that happens, you can “start over from scratch” by resetting the access permissions to default. 

In Terminal, try 

tccutil reset AppleEvents; tccutil reset SystemPolicyAllFiles

After you’ve done that, the next time you run that script you should get an authorization dialog like this: 

Alternatively, just go right ahead and add the app with the ‘+’ button in System Preferences.

Enjoy the resumption of normal service 🙂

hello, applescript 3: (don’t?) tell me to run

Continuing where we left off at the end of User In, User Out, let’s build on our knowledge of getting user input and using conditionals.


Script 7
In this script, we’re going to query the user for some information, and if that information meets a certain test, we’ll give the user one answer, if it doesn’t we’ll give them another. Kind of like a mini-quiz game program. There’s lots of new stuff in this script, but don’t be put off. Just bang it out on the keyboad, fix any typos if it won’t compile, and run it. Run it at least three times choosing a different button each time. We’ll go through it line by line after you’ve had a play around with it.





Line 1 assigns a string literal (the lovely “Loser”) to a variable, theReply. We’re doing two things here. We’re first declaring a variable that we’ll want to use later in the script, and we’re also initialising it with a default value. “Loser” is one of two possible values we’ll want this variable to have later, so we’ll set this as the default now, which means the variable will always have this value when we use it unless we change it later in the script.

Most of Line 2 should be familiar to you now, except that we’ve added a third button and a default value for the answer. We’ve also added a default button, in this case 3. To understand what the default button parameter does run the script with value 1, and then again with value 2.

As you will notice, the number refers to one of the buttons defined in the buttons list, where 1 is the first item in the list and the left most button, and 3 is the last item in the list and the right most button. The parameter determines which button has focus (and therefore responds to the return key on the keyboard).


If you’ve already tried experimenting with 4 buttons, you’ll see that the compiler complains that a maximum of 3 buttons is allowed. That’s not strictly true, but we’ll save that trick for later in the series.

Note: Lists in AppleScript, unlike most other modern programming languages, are not zero-indexed. The first item is item 1, not item 0 as it would be in Python, C, Swift and so on.

If you prefer you can also refer to buttons by their name instead of their index. This helps improve readability of your code and makes it clearer which button was intended as the default. To refer to the button by name, you would write the parameter like this:

default button "Sure?"

Line 3 should be familiar to you, but refer back to Script 6 in the previous post if you need a reminder.

Line 4 begins an if statement block that contains another if statement block (again, see Script 6), but there’s also something new here: the else condition. This says that if our condition in Line 4 isn’t met, do whatever’s in the else block starting at Line 10.

If the condition in Line 4 is met, however, then Line 6 offers a further condition: if the user typed in “Phil”, then Line 7 says change the value of the variable theReply from “Loser” to “Winner”. Note, particularly, that if this condition is not met, then the value of theReply will be “Loser” when it’s called later in the script.

Line 8 ends the inner if statement block.

Line 9 now says: display the dialog to the user, showing them the value of whatever theReply is currently set to (either “Winner” or the default “Loser”). Note that the same value is used to set the title.

Line 10 starts the else block. This will be triggered if the user doesn’t choose either “Cancel” – which would end the script – or “Sure?” – which would trigger the first condition – when Line 2 is executed.

We don’t need to put in a specific test for “Cancel” because “Cancel” will automatically end the script with error -128. However, as we’ll see later in the series, sometimes it can be useful to catch “Cancel” in the if block too, in order to execute certain commands before the script quits.

Line 11 may look a bit mysterious; this is your first introduction to AppleScript’s most pervasive control statement. tell is how you send a command to a particular object in AppleScript. If you’ve ever done any Object-oriented programming, another way of expressing the same idea is to say tell allows you to target a message toward an object. In this case the object is me — a built-in AppleScript keyword that refers to the script itself. So,

tell me to run

says “send the run message to the script”.

There’s an easy (and inaccurate) way to understand what that means, and a hard (and accurate) way. For now, we’re going to go easy so that the learning curve doesn’t get too steep. In this context, we will say that run means “go back to Line 1 and begin execution of the script again”.

Every time you choose “Try Again”, the script goes back to Line 1 and repeats itself until you choose one of the other answers.


Where we are: so far!
In this post, we’ve been introduced to AppleScript’s list class, consolidated our knowledge of display dialogs and if statements, and had our first taste of tell, me, and run. These concepts will require more elucidation and, most importantly, more practice, all of which are coming up!

In the next post hello applescript 4: shelling out, we’ll work with these concepts some more and build on them to produce our first practical scripts. Be sure to follow Applehelpwriter to be notified when the post is published.

See you there! 🙂




For extra credit:

This week’s extras
1. Modify Script 7’s inner if statement so that if the text returned contains your name, theReply is “Winner”; if the text contains “Phil”, theReply is set to “Runner Up”. Any other name should produce the default reply “Loser”.

There are in fact two ways to solve this challenge, see if you can produce both. For help, look up else if in the Control Statements Reference section of the AppleScript documentation.



Solutions from last time
1. Use the hidden answer parameter:





2. In the second exercise, we posed a number of questions. The easiest way to find out about the parameters for a command is to use Script Debugger’s Dictionary viewer, which you can access by clicking on the Window menu (not, confusingly, the Dictionary menu!) and choosing ‘Dictionary’.


Also, don’t forget to use the AppleScript documentation, which I’ve linked to multiple times in this and earlier posts. It’s a great source of information, hampered somewhat by the lack of an effective search feature on Apple’s site. An older, pdf version of the doc which you can search can be downloaded by clicking this link, and is also available from here. Bear in mind, though, that Apple’s online docs contain some information that the older pdf doesn’t.

We’ll leave the other questions open for now, as they’ll be coming up in later posts!





hello, applescript 2: user in, user out

If you’re ready to learn AppleScript, this is the place to start! If you’re not sure yet whether AppleScript is for you, take a look at the intro to this series, What’s the Use. For those of you that are ready, let’s fire up Script Debugger and write our first script!


Script 1
OK, you want ‘hello, world’? Of course, you do!

Here it is, with a difference:





Type it in to the editor’s window, then run the script by clicking the Run button or hitting “Command-R” on the keyboard.




Wow. No “print” command for one, and an actual user interface. Cool!

If you don’t see a notification in the top right of your screen, you may need to adjust your Notification preferences.

What happens if you leave off the last quotation mark?

Try it and see:




This is called a compile time error, one of three kinds we’ll learn about (the others are run time and logic errors). When you run a script, the AppleScript compiler first checks it for syntax errors. If all is well, it turns your plain text into “pretty print” (we’ll talk about what the syntax colouring means later in the series); if not, your text isn’t compiled and you get an error message.

You can get a compiler check anytime without running the script by clicking either the button or using “Command-K” on the keyboard.

You’ll notice that when you have a compile time error in Script Debugger, you get a message and the error number in the bottom left corner (you won’t see the error number if you’re using Apple’s Script Editor). These can be useful, so much so that we’ll write a little script ourselves to tell us more about the error based on the error number we get in hello, applescript 4: shelling out.

For now, let’s take a look at the message.

“Expected string but found end of script.”

It may seem rather cryptic at first, but it can be translated simply enough. A string in AppleScript (and most other programming languages), is text placed between a pair of quotation marks. Anything between quotes will be treated as just a piece of ordinary text and not as part of the programming language. display notification isn’t a string in our script: it’s part of the programming language – specifically, a command to do something. “hello, world”, on the other hand, is a string: it’s just the ordinary text we want to display. The compiler says it “expected a string” because it found the first quote mark at the beginning of “hello, indicating the start of a string. It then went looking for the second one to mark the end of the string, but instead found…yes, you guessed it: the end of the script!


Script 2
Replace the missing quotation mark. We’ll come back to error messages shortly, but for now, let’s add our own title to the notification rather than having the default one:




Make sure those quotation marks are balanced!




Looking good!


Script 3
Notifications are useful when all we want to do is pass a simple message, but if you need users to make a choice or you need to provide a longer message, we should use a dialog.

Type in the script as you see it on the left in the image below.




Run it, and click the “OK” button when the dialog appears. Now look at the Results pane (right-hand panel in Script Debugger; bottom Accessory view in Script Editor).

That looks interesting! Let’s explore some more.


Script 4
Let’s add some bells and whistles:




Run the script.




Click either one of the buttons to end the script. Again, remove the quote mark after “world”, but this time don’t try to run the script. Just try to compile it. Remember, you can do that either by clicking the button in the toolbar or “Command-K” on the keyboard.

Notice this time we get a different error message and a different number, despite the fact that we seem to have errorred in exactly the same way and in exactly the same place as before:




Or did we? Look at it from the compiler’s point of view. Just as before, the compiler finds the first quote mark and continues looking. But this time it does find the second one! Only it’s not where it’s meant to be. Because we left off the quote mark after “world”, the compiler assumes that the quote mark that prefixes “Message is the closing quote mark for the opening one:




As a result, the term Message looks to the compiler like its supposed to be part of the programming language, as it follows the string “hello world with title ”. That sure is a valid string (you can put any text you like in your string, it doesn’t have to make sense), but what follows it is not a valid part of the programming language. You can learn more about identifiers here, but for now, just note that this error message has the form “this can’t go after that”, and is another clue that our quote marks are unbalanced.

What about the third quote mark? The compiler never sees it. The compiler reads from left to right, so after pairing the first two quote marks it throws the error and stops trying to read any further. If there are further errors in our script, we’ll never know till we fix (all) the preceding ones.

After you dismiss the error alert, the compiler is kind enough to highlight the this (“Message”) that can’t go after the that (“"“) in your script.

Errors -2740 and -2741 are common enough that whenever you see them, you now know what to check first: are my quotation marks balanced?

Let’s get back to our display dialog command. Are you wondering what happens if you use another number instead of 2 after with icon? I hope so!

Replace the missing quotation mark, and experiment by changing the number after with icon for all three values from 0 to 2.

Normally, you’ll use with icon 1, which will insert the icon of the executing program. In this case, that’s the icon for Script Debugger, but as you go through this series you’ll be learning how to execute your scripts in other ways, and it’s useful to have the icon of the executing program visible in the dialog box so that you know exactly where it’s coming from.

Our dialog box has some unnecessary cruft. We have an “OK” button and a “Cancel” button, but they appear to do the same thing; that is, they halt the script. But look a bit closer at the editor. Run the script again, twice, choosing the “Cancel” button first, and then the “OK” button on the second run.

When you choose “Cancel” there is no result, but there is an error message in the Events pane, specifically, error -128.




Errors, error messages and error numbers are powerful friends. We’ll see how we can harness errors like -128 later in the series.

When you run the script again and choose “OK”, however, there is a result. There are many result types, but in this case you get what is known as a record (similar to a Dictionary or key/value pair in other languages) in the Results view:

{button returned:"OK"}

The record contains a label (in this case, button returned, and a value (here, "OK"). This is important, as we’ll see in the following scripts.


Script 5
What if we want to get more than just an acknowledgement, but need some input from the user? Here’s one way:




Run the script, type in an answer, and hit “OK”. Take a look at the result:

{button returned:"OK", text returned:"Phil"}

It’s a record again, with the added pair “text returned” and the text that the user typed.

The default answer parameter is an empty string. What happens if you put some text between the quote marks and run the code?


Script 6
Let’s build on Script 5 and capture the answer that the user provides:




This script has a lot of new stuff going on. Let’s take it from Line 2 (refer back to Script 5 for line 1):


Line 2
This captures the result of the dialog in a variable called dialogAnswer. The result of the dialog isn’t the name you typed in, but the record of two labels with two values. In other words, the value of dialogAnswer is:

{button returned: "OK", text returned: "Phil"}

We could have called the variable (almost) anything we liked. I just chose dialogAnswer because it’s descriptive.

Descriptive names are useful because when I read back my script at some point in the future, it’ll be immediately obvious what this variable represents. However, I could have called it alpha, or just d or almost anything else. There are some reserved words in AppleScript that you can’t use, and you also can’t start variable names with a number or use certain special characters in them, as noted here.

Most commonly, we use the set command to assign values to variables. In many other programming languages, they use the = sign, like this:

dialogAnswer = result

You can’t do this in AppleScript (or rather you can, but it means something else, not variable assignment), so if you’ve come to AppleScript with a background in another language, you’ll need to make the mental adjustment.

What about result though? Where did that come from? This is a built-in property, filled with the value of the last command to be executed.

Take a moment to consider that. It means that the result property changes on (almost) every line of your script.

Before we continue working through the rest of Script 6, let’s take a closer look at the result property. Type this in, then compile and run it:




Notice that in the Events pane, result changes from 2, to 3 and finally (in the Results pane) to 6.




AppleScript can use the usual programming conventions for mathematical operators (+, -, /, *. For x % y, use x mod y). That also includes the = sign, where it means “is equivalent to” (aka “==” in many other programming languages) and not, as we mentioned above, “assign to”.

In this little script, we also learned how to use the log command to print the value of a variable to the Events pane. In Script Editor, you’ll need to do that a lot if you want to see the values of your variables at different times in your script. In Script Debugger, however, it’s rarely necessary as you can see the values in the Variables inspector view.

To verify this, try removing the two log statements and running the script again. The log statements no longer appear in the Events pane, but Script Debugger captures them anyway in the Variables inspector view.


Line 3
Line 3 of Script 6 is an if statement, a kind of control flow statement. The clause, in this case, takes the form of a block. That means it evaluates a condition on one line, executes any commands if the condition is met on subsequent lines (Line 4) and then provides an end statement (Line 5) to signal the end of the block.

The conditional here first examines the button returned property of the result, which, remember, we’ve captured in the dialogAnswer variable.

After the conditional has been evaluated and any commands executed if the condition was satisfied, the rest of the script continues to execute as normal. In Script 6 there were no more commands after the block, so the script ends.


Line 4
In Line 4 of Script 6, if the user clicked “OK”, we set a new variable, theName, and assign it the value of the text returned property of the dialogAnswer record. Because we ended the block and the script on the next line, we never actually got to use this new variable, but typically the point of doing this would be so that we can use that value somewhere else in our script.


Where we are: so far!
Woah! We’ve done a lot in this post! We’ve seen how to get data in to our scripts from users and how to get data out, through dialogs, notifications and the Events and Results panes. We’ve had a first go at writing a conditional, logging messages, and viewing variable values. We’ve also been introduced to the compiler’s error messages and AppleScript’s record class.

If it’s all a bit of a blur, don’t worry. We’ll be practicing all of this, and expanding our skills some more, in the next post in this series, hello, applescript 3: (don’t?) tell me to run!. Be sure to follow Applehelpwriter to be notified when a new post is published.

See you there! 🙂





For extra credit:
1. Try to modify Script 6 so that when you run it and type in your name, it looks exactly like this.




You’ll need to consult the docs for display dialog, so try to find and explore Script Debugger’s Dictionary viewer in order to do that.

2. Go back to Script 4. What happens if you set with icon to 3?
This is an example of a run time or ‘execution’ error. The script will compile fine, because the parameter, or value, for with icon only has to be a number in order to compile. AppleScript tells you ‘a resource wasn’t found’ because, unlike ‘icon 0, ‘icon 1’ and ‘icon 2’, there’s no such thing as ‘icon 3’.

That raises a number of questions: how can we tell what kind of parameter an argument or command takes? Why are there only three icon resources and where are they declared? How can I add other icons if I want to? And last, but most importantly, what else do we need to know about run time errors? All this, and much, much more, will be covered in the hello, applescript series. Stay tuned!





hello, applescript: what’s the use?



In the first of a series of AppleScript tutorials, this post explains why you might want to consider learning AppleScript.


What’s the use?

If you’re not sure whether you want to invest time in learning AppleScript, this post is for you. Here I’ll outline four good reasons to learn AppleScript. I’m sure they’re not the only ones, but they’re the main ones that come to my mind as a daily user of the language. If, after reading this post, you want to give it a try, be sure to follow this series, as we’ll be quickly moving on with hands-on examples and detailed explanations that will rapidly turn you into an AppleScript power user! At the end of this post, I’ll briefly discuss tools, so that you’re ready to get started when the next in this series, User In, User Out, is published.


1. Automation
First of all, AppleScript can interact with other applications. That means it can get one app to perform a function and pipe the result to another app to perform a different function that the first app didn’t have. There’s no limit to the number of apps and functions you can chain together in this way (other than your computer’s resources). Why would you want to chain apps together like that?

To achieve things that none of those apps can do on their own.

Imagine this scenario (scripts for this appear later in this series of posts): Suppose you run a small business and customer orders come in via email. With an AppleScript, you can have those emails automatically scanned, the customers’ order details extracted, and your Excel or Numbers spreadsheet updated accordingly. You could then have the product details forwarded to another person (Packaging?) and the customer details forwarded to a third (Marketing?). Your script could tell Word, or Pages, to print out a label, and tell Mail to now send an automated response back to the customer. There is no one program on your computer that can accomplish all that, but you can, with AppleScript.





Once set up, none of this requires any interaction on your part. You build the script, test it, and add it as a Mail rule. The rest happens automatically when the mail arrives in your Inbox; you don’t need to monitor it. You can go on holiday. This ability to automate is what makes AppleScript so unique.


2. Integration
AppleScript’s ability to chain or pipe application functions together is similar to the Unix command line ability to pipe utilities together, only it allows you to do it with full-blown applications. But you can use it to connect those applications to command line utilities, too. This is the second thing that makes AppleScript unique: integration across the entire macOS environment. You can even chain it to other programming languages.


For example, I could have AppleScript run some Python code, take the result and run that through a Perl script, and take the result of that and display it to the user (or myself) in a dialog box or notification (or send an email, or a Chat message, etc). And I can do that without having to mess about worrying how to create graphical user interface elements like you might do with Tcl/Tk (if you know what that is; if you don’t, forget it!).

The relationship between AppleScript and the shell is symbiotic. If you’re a shell diehard, you’ll be happy to know that you can actually create and execute AppleScripts in .sh files without ever going near an AppleScript editor.


3. Power
AppleScript can not only harness the power of other scripting languages, it can harness the power of macOS itself. The AppleScript-ObjectiveC bridge means you could, if you wanted to – and many programmers do – create full on native macOS Cocoa apps without ever getting into the intricacies of Xcode projects and workspaces. You can even code sign your AppleScript apps from within the script editor.





4. God-mode
Finally, AppleScript can drive the user interface and even drive apps that haven’t been specifically made to support AppleScript. If you find yourself repeatedly doing the same actions in the UI to achieve a task, you can cut-out the middle-man (you!) and tell AppleScript to click those buttons, move those windows or copy that text from Safari and paste it into Pages instead of laboriously and repeatedly doing it yourself. This creates an eery effect not unlike those old-time pianolas.

Look no hands!



Where’s the catch? To achieve the level of automation and time-saving we’ve been discussing, you’re going to have to invest some time up front learning how to script. It won’t always be easy, and you won’t always be happy that it’s not easy, but that’s the price of investing in learning anything.

If you’re ready to learn this amazing, unique language, let’s get tooled up!


Tools
I’ll keep this short. You can learn AppleScript the hard way using the built-in Script Editor, or you can learn AppleScript the easier way by using the free 3rd-party editor Script Debugger.





Script Debugger gives you a full-featured trial for 20 days, and after that if you don’t want to buy it you lose some of the more advanced features but you can use the rest indefinitely anyway. It works in rather the same way as BBEdit’s trial does, if you’re familiar with that.

If you save scripts in Script Debugger (so long as they’re not debug scripts, more on that later), you can run (and edit) them in Script Editor and vice versa. In other words, you’re not locked in to a proprietary tool.

I’m not even going to consider that you’d choose to learn AppleScript the hard way since the easier way is free, so all the examples in this series of posts will use Script Debugger. However, unless otherwise marked as SD-only or SD-paid-only, you can do all of the examples in the series in either tool.

Don’t worry, at this point, about how to use either Script Editor or Script Debugger. We’ll get into that in the next post: hello, applescript 2: User In, User Out. Follow Applehelpwriter to be notified when a new post is published.

🙂


accessing TCC.db without privileges



Earlier this year, Digita Security’s Patrick Wardle took apart a cross-platform backdoor trojan he nicknamed ”ColdRoot’. Wardle was retro-hunting possible malware by searching for apps on VirusTotal that access Apple’s TCC privacy database.

For those unfamiliar, TCC.db is the database that backs the System Preferences > Security & Privacy | Accessibility preferences pane and which controls, among other things, whether applications are allowed access to the Mac’s Accessibility features. Of interest from a security angle is that one of the permissions an app with access to Accessibility can gain is the ability to simulate user clicks, such as clicking “OK” and similar buttons in authorisation dialogs.

One particular comment in Wardle’s article caught my eye:

there is no legitimate or benign reason why non-Apple code should ever reference [the TCC.db] file!

While in general that is probably true, there is at least one good reason I can think of why a legitimate app might reference that file: reading the TCC.db used to be the easiest way to programmatically retrieve the list of apps that are allowed Accessibility privileges, and one reason why a piece of software might well want to do that is if it’s a piece of security software like DetectX Swift.

If your aim is to inform unsuspecting users of any changes or oddities in the list (such as adware, malware or just sneaky apps that want to backdoor you for their own ends), then reading TCC.db directly is the best way to get that information.


Just call me ‘root’

Since Apple put TCC.db under SIP protection subsequent to my reports on Dropbox’s user-unfriendly behaviour, apps are no longer able to write to the database via SQL injection. An app with elevated privileges can, however, still read the database. A sufficiently privileged app (or user) can output the current list with:

sudo sqlite3 /Library/Application\ Support/com.apple.TCC/TCC.db 'select * from access'

On my machine, this indicates that there are twelve applications in the System Preferences’ Privacy pane, all of which are enabled save for two, namely LaunchBar and Safari:



We can see from the output that LaunchBar and Safari both have the ‘allowed’ integer set to ‘0’ (the middle of the three values in “0|0|1”) , whereas all the other apps have it set to ‘1’ (“0|1|1”).

It’s not clear to me why reading the database should require privileges. Certainly, Apple have provided APIs by which developers can test to see if their own apps are included in the database or not. The AXIsProcessTrusted() global function, for example, will return whether a calling process is a trusted accessibility client (see AXUIElement.h for related functions):

However, there remains a case (as I will demonstrate shortly) where developers may well need to know whether apps other than their own are, or are not, in the list. Moreover, there doesn’t seem to be any obvious vulnerability in allowing read access to that data, just so long as the write protection remains, as it does, in place.

The use case for being able to read the TCC.db database is clearly demonstrated by apps like DetectX Swift: security apps that conform to the principle of least privilege, always a good maxim to follow whenever practical. Asking users to grant elevated privileges just to check which apps are in Accessibility is akin to opening the bank vault in order to do an employee head count. Surely, it would be more secure to be able to determine who, if anyone, is in the vault without having to actually take the risk of unlocking the door.


Did they put a CCTV in there?

Without direct access to TCC.db, we might wonder whether there are any other less obvious ways by which we can determine which apps are able to access Accessibility features. There are three possibilities for keeping an eye on bad actors trying to exploit Accessibility without acquiring elevated privileges ourselves, each of which has some drawbacks.


1. Authorisation dialogs
The first is that we can read the property list that records all invocations of the Accessibility authorisation dialog, without admin rights:

defaults read ~/Library/Preferences/com.apple.universalaccessAuthWarning.plist

That gives us a list of all the apps that macOS has ever thrown the ‘some.app would like permission to control your computer’ dialog alert for, along with an indication of the user’s response (1= they opened sys prefs, 0= they hit Deny).



This list could prove useful for identifying adware installers that try to trick users into allowing them into Accessibility (looking at you, PDFPronto and friends), but it’s main drawback is that the list is historical and doesn’t indicate the current denizens of Accessibility. It doesn’t tell us whether the apps in the list are currently approved or not, only that each app listed once presented the user with the option of opening System Preferences and what the user chose to do about it at that time.



2. Distributed Notifications
The second option is that developers can register their apps to receive notifications when any other application gets added or removed from the list with code similar to this:

DistributedNotificationCenter.default().addObserver(self, selector: #selector(self.accessibilityChanged), name: NSNotification.Name.init("com.apple.accessibility.api"), object: nil)

This ability was in fact added to DetectX Swift in version 1.04.



However, Apple hasn’t made this API particularly useful. Although we don’t need elevated privileges to call it, the NSNotification returned doesn’t contain a userInfo dictionary – the part in Apple’s notification class that provides specific information about a notification event. All that the notification provides is news that some change occurred, but whether that was an addition or a deletion, and which app it refers to, is not revealed:




Even so, notification of the change is at least something we can present to the user. Alas, this is only useful if the app that’s receiving the notification is actually running at the time the change occurs. For an on-demand search tool like DetectX Swift, which is only active when the user launches it, the notification is quite likely to be missed.

It would be nice, at least, if Apple would provide a more useful notification or an API for developers wishing to keep their users safe and informed. The lack of a userInfo dictionary in the notification was apparently reported as a bug to Apple several years back, but I suppose it could always use a dupe.



3. AppleScript – everyone’s favourite ‘Swiss Army Knife’
There is, as it turns out, a third way to reliably get exactly all the info we need about who has access to Accessibility. We can use AppleScript to return a complete list of apps in Accessibility that are enabled. Note that the output of this unprivileged script, shown here in the results pane of Script Debugger, returns a more readable version of the same list of apps we obtained from the privileged sqlite3 query of TCC.db, minus Safari and LaunchBar, which as we previously noted were not enabled:





Fantastic! There’s just one problem. While this AppleScript does not require blanket elevated privileges to run – in short, it doesn’t require an administrator password – it does need to be run by an app that is itself already in the list of Accessibility apps. If you have a script runner like Apple’s Script Editor, or third-party tools like Script Debugger or FastScripts, already approved in Accessibility, then you can run it without authorisation. It’s also worth noting that the script relies on launching and quitting System Preferences, which it attempts to do as quietly as possible.

As for DetectX Swift, I may consider adding something like this to a future version as an option for users who are happy to add DetectX to the list of apps in Accessibility.

Enjoy! 🙂



Have your own tips about accessing TCC.db? Let us know in the Comments!
Featured pic: Can’t STOP Me by smilejustbcuz


BBEdit: how to preview Slack messages





I’ve been using Slack quite a bit recently, but I’m still not that confident with its text formatting options. Sure, they’re simple enough, but when I’m on a workspace with a 10-minute editing timeout and I’ve a heavily formatted message to send, there’s plenty of chance I might not get the formatting just the way I want in time.

That got me to thinking there must be an editor that supports Slack’s style of markdown, but I was surprised to see from Slack’s help that in fact, they don’t support regular markdown at all:



Hmm, that’s a bit disappointing. What to do?

Well, turn to my two favourite apps, BBEdit and Script Debugger, and knock up my own preview editor, of course!

This only works if you have access to BBEdit’s advanced features (either you’re still on the trial or you bought a license) as you’ll need the Markup menu and its ‘Preview in BBEdit’ option (Control-Command-P) for this to work.

To use the script, save it (or an alias to it) in BBEdit’s Scripts folder as ‘Slack Preview.scpt’ and assign it a shortcut key in BBEdit’s Preferences:







You’ll find the script available in the menu bar, but it’s going to be more convenient to use the keyboard shortcut. You may also need to muscle-memory the shortcut for opening the Preview window (Control-Command-P) if it isn’t open already when you run the script.





The script will prompt you if that happens:

Finally, here’s a little 1-minute video showing the script in action. You’ll note from the screenshot at the top of this post that I’ve improved the styling a bit since the video was made to more closely emulate the default Slack style, but those of you with better CSS skills than I are welcome to fiddle with that to suit your taste.



So what are you waiting for? Oh, you missed the link to the script? Here you go, then.

Enjoy! 😀


BBEdit: remove whitespace with one click

remove whitespace

I often need to process lists of ‘dirty text’ which can contain lots of whitespace, new lines and so on. Fortunately, BBEdit allows you to run AppleScripts directly from its Script menu, which means we can define lots of useful little text processing scripts and have them ready to hand. I’ve got several that I’ll share over the next few posts, but probably the most oft-used of them is this one for removing whitespace.

Here’s what the script looks like. You can download the source from my pastebin here.

And here’s a little giffy showing it at work:






Share and enjoy! 🙂


how to easily spoof a user’s password





Spoofing or phishing – presenting a user with fake authentication requests – is a common email tactic, but it’s not the only vector where you need to be on your guard. Every version of macOS is vulnerable to a very simple phishing attack right on your desktop that doesn’t require admin privileges to run, would not be detected by GateKeeper or XProtect, and which could easily be placed on your mac by any of the nefarious malware / adware installer scripts that come with some less reputable software downloads.

This attack isn’t new, but it’s not often talked about. The easiest way to see how it works is in this quick 4-minute demo:

As you can see, it’s easy to grab the icon of any Application and put it in the script; it doesn’t even have to be the icon of an app that’s running. The simple demo I gave above could easily launch iTunes first to increase the coherence of the attack, or it could use a completely different icon, including the icon of security programs you may have running on your mac.

How can you check?

If you were presented with a password request like this and wanted to check whether it’s legitimate or not, an easy way would be to use my free utility DetectX Swift’s Profiler. Click the Profiler function, and search for ‘osascript’ within the Running Processes section. Note how DetectX Swift shows you the text of the script being run, confirming that this dialog is up to no good:


how to retrieve forgotten Wifi password


At our house, giving visitors the wifi password is always an exercise in frustration. Can’t remember? Oh, then I’ve got to either go trawling through Keychain Access or log in to the router, neither of which are particularly appealing.

Here’s an easier way. It’ll require an admin password (and you’ll need to supply it for as many passwords as you’re looking for – no ‘with administrator privileges’ will help here I’m afraid), but otherwise requires nothing more than a quick double-click of this saved script, once you’ve added your own SSID names in place of the dummy ones.

Just to be clear, you do NOT need to add the passwords to the script. So long as the mac that you run this script on already knows the Wifi password, the script will retrieve it.

Get the script from my pastebin

Enjoy!

how to quickly toggle Swift Compiler warnings





I thought I’d share this little AppleScript for anyone working with Xcode 8.3.3 and using Swift.

One of the things I find intrusive are the constant Swift Compiler warnings while I’m actually in the middle of writing a block of code (e.g, ‘…value was never used consider replacing…’). Well, yeah, it’s not been used *yet* …grrr!

However, turning off compiler warnings isn’t something I want to do either. It’s too easy to go into the build settings, turn them off, do a bit of coding, take a break, do a bit more coding…oh, three thousand lines later and I suddenly realize why Xcode hasn’t been correcting my mistakes all afternoon!

This script allows you to quickly and easily toggle the warnings from a hotkey, and just gives you a gentle reminder as to what you’ve done. Of course that won’t stop you forgetting, but assigning a hotkey for this script makes it painless to just turn warnings off and back on again as soon as you’ve got past whatever bit of code the compiler was complaining about.


Xcode unfortunately doesn’t have its own scripts menu, so in order to assign the script a hotkey, you’ll need to either make it into a Service with Automator or use a script runner like Red Sweater’s FastScripts.

#start
on sendNotification(aVal)

display notification "Suppress Warnings was set to " & aVal with title "Swift Compiler - Warnings Policies"

end sendNotification

tell application id "com.apple.dt.Xcode"
tell its front document
tell its front project
tell its front target
tell its build configuration "Debug"
set b to build setting "SWIFT_SUPPRESS_WARNINGS"
if b's value is "NO" then
set b's value to "YES"
else
set b's value to "NO"
end if
my sendNotification(b's value)
end tell
end tell
end tell
end tell
end tell
#EOF

If copying the code above doesn’t build, get the raw source from my pastebin here. Here’s how it looks in Script Debugger 6:

Enjoy! 🙂


%d bloggers like this: