CookieFilter: A Safari Cookie Whitelist
CookieFilter allows you to maintain a whitelist of cookies that Safari is allowed to store on disk. All cookies that are not in this whitelist will be discarded when you restart Safari. It's a bit of a hack, but it works well.
About CookieFilter
CookieFilter consists of two parts: a Perl script that lets you clean your shared cookie storage as used by Safari and other applications, and a launchd job .plist that allows you to automatically run this script in the background every time the shared cookie storage is modified.
The result is that Safari will still accept all cookies it receives, and keep them in memory, but only whitelisted cookies are actually kept on disk. Every time you close Safari all unwanted cookies are discarded.
If you don't have OS X 10.4, or if you don't want the script to modify your shared cookie storage as long as Safari is running, you can simply execute the Perl script manually (after you have closed Safari).
Any feedback is welcome. I've only tested it on my system: OS X 10.4.2 build 8C46, with Safari 2 build 412.2. Tell me if it is or isn't working for you, or if you have ideas for improvement.
Download
- CookieFilter_2005-07-30.zip, 8 KB (Perl script, launchd job, readme.txt)
Disclaimer
1. This is not a user-friendly script; this is a hack. I haven't seen any side-effects so far; but I've only used this for a short amount of time. There is absolutely no guarantee that this is working correctly. You should only use this if you have at minimum of understanding of the technical issues involved. You should study the script and .plist before you install this. Always make backups of your system.
2. Cookies.plist is not only used by Safari, but is actually a system-wide storage for cookies; NeoOffice seems to use it too, and there are bound to be others. So watch out if other web-based applications act up after you install this script.
3. I'm aware that this solution is entering unknown territory, as we now rely on some specific Safari and system behavior that could change with every update. I'd love to find a more robust solution than this (using launchd to start a script when Safari is closed would be a great start). I was thinking about only starting the launchd job when the system boots up, but then I realized I don't actually reboot my machine.
Install
You need OS X 10.4 -- the perl script will work without it, but launchd is only available on 10.4.
The perl script requires Mac::PropertyList. (There was a request for a description of how to install Perl modules from CPAN; I've originally left this out to prevent newbies from screwing with their system, but I'll add such a description as soon as the script is sufficiently stable. Watch the blog for updates.)
If you want to, you can backup your cookies first. They are stored in ~/Library/Cookies/Cookies.plist -- close Safari before you make a copy, just to be sure.
Then put cookiefilter.pl in a directory of your choice (usually ~/bin/), and make sure that it has access to Mac::PropertyList. Make sure it is executable. Start it manually to ensure that it's actually working.
Edit de.dekstop.CookieFilter.plist with the Property List Editor or your text editor of choice, modify the value of the Program key so that it points to the correct location of cookiefilter.pl on your disk, and modify the WatchPaths array so that it points to the Cookies.plist file in your user profile. Put de.dekstop.CookieFilter.plist in ~/Library/LaunchAgents/ (you might need to create this directory first) to let it automatically be loaded during system startup.
You can now manually start the CookieFilter launchd job (rebooting the system has the same effect):
launchctl load ~/Library/LaunchAgents/de.dekstop.CookieFilter.plist
The output of cookiefilter.pl is redirected to the console, so after the installation you might want to open Console.app and watch console.log and system.log for errors.
Uninstall
To disable CookieFilter you simply unload the launchd job:
launchctl unload -w ~/Library/LaunchAgents/de.dekstop.CookieFilter.plist
You can now delete de.dekstop.CookieFilter.plist from your LaunchAgents directory.
Some Technical Details
I figured that the best method to automatically start CookieFilter would be to wait until Safari quits, and then run the script; but I didn't find a way to trigger a launchd entry when an application closes. But launchd allows us to launch a script every time a file or directory is modified, and this brigs us quite close to a perfect solution.
I used fs_usage to watch what Safari actually does when it starts and closes, and when cookies are stored and loaded. I found that:
- Cookies.plist is loaded once, upon Safari startup, and from then on only written to.
- As long as you are actively surfing, and changing cookie values in the process, the cookie storage is written to Cookies.plist. It seems this happens roughly every 30 seconds at most.
- When you modify Cookies.plist while Safari is still running, the changes are not reflected in Safari's cookie inspector. But Safari doesn't crash either, which is good ;)
- When you restart Safari, the cookie inspector reflects the changes we made.
From this it follows that we can create a situation where Safari keeps all cookies in memory while it is running, but where only whitelisted cookies are kept on disk. All we have to do is make sure that launchd triggers the CookieFilter script everytime Cookies.plist changes (which can happen as often as every 30 seconds.)