I see... it's an interesting problem. The only app i could find to solve this is not enforceable, just optional, incase the user wants to voluntarily disable write on the device i,e, for forensics.
The daemon that handles auto-mounting on OS X is /usr/sbin/diskarbitrationd the launch daemon is here:
but it doesn't seen to be possible to add any default options to the launch daemon for mounting... because diskarbitration just invokes the mount command rather than mounting by itself.
Also i'm not sure if this would be safe to do because it could be too generally applicable ... i.e. what mounts the root device? i duno, but if it is this daemon then that would screw stuff up.
Another option would be to find a callback for diskarbitrationd when it mounts devices and write a shell script to remount the volume as read only... but as far as i can tell no one has done this yet.
alternatively you could set them up with a very limited user account without access to removable media altogether.
sorry i can't be of more help... but if you really want that capability it looks like your going to have to write some code.
alternatively rather than having to implement a callback for that daemon you could write a less elegant but very simple shell script that occasionally polls the /Volumes directory for new entries, and then remounts any new ones as read only... of course you would add an exclusion list for internal drives, but this would not be bullet proof as there would be a short period of time (whatever the polling time is set to) where the device would be mounted as read+write.
Or maybe someone knows of a better way to detect file system changes to specific directories and create a callback.
I duno i'm getting out of my depth, this is all just conceptual tbh.
I don't have time for this today, but it can be done without polling.
OS X has kqueue which can provide notifications of file-system changes via the BSD tool "wait_on", this isn't included with OS X but i think it's available as a port somewhere.
with wait_on you can run a shell script when contents of a directory change... you do this by having a shell script , and run the main actions in an infinite loop and then issue the wait_on command for the directory to monitor for changes, which then continues the loop when it detects a change (i think)
now the functions within that loop are bit more solid... you just have to use diskutil to list the mounted partitions... check if they are mounted as read+write && if it's UUID is not in the exclusion list and then if both true mount it as read only. And of course iterate over the list of partitions.
You don't need to bother attempting to get info from kqueue on what specifically has changed, as this only ever gets called when there is a changed (not polled) so it's ok to iterate over all the partitions... provided you don't have hundreds of the things.
If someone else wants to write a script you know what to do. I might come back to this because it sounds like it could be a helpful security tool.
That might be tricky without disabling other usb devices such as keyboards and mice...
i've found a simpler way to do the script actually, i don't need the wait_on tool, didn't realise but launchd can monitor directories for change, so i can just create a simple launch daemon and a shell script.
i'm just doing the shell script.
I'll post it soon and you can give it a go if you like... i'm just a little slow at the moment, i don't do much shell scripting.
This is out of my zone of expertise, but maybe you can make something out of my guesswork. The proper way to do this, I think (if it's doable natively) would be through the fstab file - add a line or lines that tell the system to mount usb drives as read only. see man fstab. The man page says that you can specify block special devices as well as individual file systems, and that leads me to think that if you can figure out how to specify the usb ports on the device level you might be able to do what you want fairly simply.
Ok finished the daemon, it doesn't use fstab, but relies on being invoked to remount volumes when they are detected by launchd. I will have a look to see if i can use fstab because you right that would be better.
This works pretty well though, it doesn't always do it instantly... sometime it takes about 1 second (literally) to remount it... if your fast you can get into the volume but then the window almost immediately gets closed as it remounts... i know this isn't exactly completely solid, but it's a pretty good deterrent.
It works by collecting a list of currently mounted volumes and then performing checks on them, first to see if they are mounted read/write, then some other things like if it's the root device is hard coded so you can't attempt to unmount your system drive, checks if it's internal, then also uses whitelists of protocols (interface) so you can customise the interfaces that are allowed to have write (i.e. SATA PATA USB Fire Wire Disk Image etc), then there's also a volume UUID whitelist, so you can potentially add exceptions so you can have specific external volumes mountable.
It's launch daemon simply watches the /Volumes directory for change... so you can see where this has it's flaws. If a user has access to the terminal and can create custom mount points then it will evade this script... however as soon as it's triggered it will find all mounted volumes. And of course there is that delay because the volumes have to be mounted twice.
I've made an installer and tested it thoroughly... it is reasonably safe, the script itself doesn't ever issue any dangerous commands, but that doesn't mean that there aren't bugs in it that could cause mounting and unmounting of things it shouldn't be. (it's perfectly safe i'm just giving you my disclamer)
there is no uninstaller but you simply delete these two files to uninstall / disable:
Sorry i've got no were permenant to host it at the moment hopefully this will last a little while:
Forgot to say how to configure it... you can edit that second file (diode.com) this is the script... and It also has the whitelists at the top. you will need to edit a copy and then replace it with the correct ownership and permissions.
You can see feedback from the script in your system.log (console.app)
Sorry i made it a bit verbose... but it was handy for me while i was figuring it out don't be suprised by it running four times for every one time it is invoked.... it runs a few times to make sure it catches the volumes after they mount... running it once occasionally missed the new mount, and sleeping would only extend that delay when the volume is first mounted so this seemed like the best option.
/etc/fstab.hd is the wrong file. you're looking for /etc/fstab, which is still used by the system. In fact, that's a unix standard which is unlikely to go away any time soon. fstab.hd was (I think) one of those things that Apple implements in one revision and then drops a couple of revisions later; they can't discard the file because someone might be using it somewhere, but they want to discourage people from using it.