My name is Joe Basirico, I help people build secure software. Learn more »


So you want to be a better programmer

6/14/2017 - Posted by joe

Artem Sapegin
I get asked sometimes how some people on my team can become a better programmer. I think it's useful to think in terms of different evolutions of the programmer. In the beginning there's a scripter or coder and at the highest level you have an architect. There is much, much more to go into here, but this is a rough framework to plot your skills over time.

Use this to fill in your current skills and to identify key areas of improvement.


Progression from Scripting to Developing

Move from "scripting" to "programming" to "developing"


  • Coders understand how to solve immediate problems in a sometimes brute force way. Question -> Google -> StackOverflow -> Copy -> Paste is a standard method of development and problem solving.
  • Lack algorithms or data structures understanding well enough to know when there may be an efficient solution to the problem
  • Develop primarily in a text editor
  • Write code -> compile -> fix compiler errors -> run -> fix runtime errors -> repeat
  • Struggles to estimate coding projects larger than one month


  • Understands their IDE can use it for debugging
  • Understands basic Algorithms and Data Structures
  • Breaks problems into reusable parts
  • Is comfortable with their programming language and the common libraries and frameworks
  • Googling is still common, compiler errors are less frequent, runtime errors are less frequent
  • Can break problems down to estimate more effectively


  • Fluent with their IDE and all features
  • Understand all features and components of the software (from DB, to unit tests, to OS, etc.)
  • Knows multiple languages and when to do different things in different areas (for example when it's best to let the database handle something vs. code)
  • Understands Advanced algorithms and data structures
  • Deeply understands language constructs, libraries and frameworks they're using. Understands The Law of Leaky Abstractions.
  • Understands performance tradeoffs
  • Can reliably create time estimates, and track progress toward them


  • Knows when to use different systems for best performance/security/logic
  • Sophisticated knowledge of data structures and algorithms including space and time complexity analysis

Books to read:

Link to this article.

Project Success

6/9/2017 - Posted by joe

This diagram is an approximation of how I think about iterating toward a goal to increase my likelihood for success. There are a few concepts that I've packed into this diagram, so I'll try to explain here. I've also recorded myself drawing this diagram roughly in order of operations on youtube. here.

Step 1: Set a Clear Goal

Defining a clear goal and understanding what "Success" looks like is the most important first step. A make the analogy that a goal might be to Summit a mountain. Every action is a step. Steps can take you in any direction. If you're not careful about which direction you're walking, you may not be making it closer to your goal, and in fact you may be moving farther away! Do not waste time with actions that don't take you closer to your goal.

I'm a fan of SMART Goals (https://www.projectsmart.co.uk/smart-goals.php), but having goals that are at least Specific, Measurable, and Realistic is super helpful. Being able to track your progress so you know when you're going in the right direction is important and will help keep you inspired to complete the goal.

Step 2: Try a lot of ideas!

You may feel like you want to dive right into solving your problem or that you know the best way to do so. Instead try a few different things, ask around and challenge your assumptions, do research and see what sticks and resonates for you.

Step 3: Iterate and start working

Split your work into small attainable chunks. After each chunk test if you're closer to your goal or further away. Make sure each piece of work you start work on is the most important thing you can do and that it moves you closer to your goal. Don't work on "fun" things just because they're fun. Work on important, foundational things that you will make the largest difference first.

Do not attempt action without Iteration

Get feedback, and check against the goal as frequently as possible. If you focus on action and don't look up to check against your goal you can find yourself very far away from your goal and have wasted a large amount of time going in the wrong direction

Do not overestimate Sunk Costs!

We sometimes think back on the work we've done and overestimate the value of it. In a bad scenario we will overestimate the value of the work we've already accomplished, and underestimate the work ahead of us. If something's not working, shelve it and try something new. Ask yourself the question "How would I accomplish this goal if I knew everything I know now?"

Consider going back to Step 2 then to Step 3 with your new idea!

Step 4: Iterate frequently and check against your goal

This is the same as Step 3, but with a new starting point

Good Enough

Once you've made good progress toward your goal start asking if you've achieved "Good enough" Perfect is rarely achievable. You'll naturally make the most progress toward your goal early in the project. Trying for "Perfect" is a great target, but time and other pressures may make it clear that your time and energy could be better spent elsewhere.

Celebrate Success

It is incredibly important to reflect and celebrate your success. We often get too caught up in what could have been done better or we quickly move to the next project. It's good to know what can be improved for next time, but if that's all you focus on you can become burnt out and cynical. Focus on what was great and how proud you are of your accomplishment.

Link to this article.

Don't Short Circuit a Lesson

6/3/2017 - Posted by joe

Don't short circuit a lesson because you think you know what the take away is going to be. Too often we try to map other's experiences or recommendations to our own and we miss out on new opportunities to grow or learn.

Next time you hear somebody describing something they just learned don't interrupt with by saying "oh, I know where you're going" or "I know something similar" instead do two things:

First, delight in the other person's excitement about the topic. Be empathetic to their story, their journey, and their discovery. Ask probing questions, be genuinely excited to hear what they're saying.

Second, understand you can learn from everybody. Not in some cheesy "everybody has a story to tell" sort of say, but a very real, concrete way. They learned this topic in a different way from you, they have come from a different place, walked a different path, and colored their discovery through their experience. Because of this they will be able to teach you something about any new topic.

Link to this article.

Scale Your Solution to the Problem

5/30/2017 - Posted by joe

It's important to Scale your solution to the problem at hand vs. trying to scale the problem to your solution.

By analogy a master photographer knows when to pull out her iPhone and take a quick snap, edit it in-app and upload it to Instagram and when it's appropriate to break out the $5k camera body and $5k lens, and wait for the perfect opportunity and use Photoshop to edit the photo to perfection. The amateur photographer doesn't know anything about photoshop and lacks the skill to wield the $10k camera even if they had one so their options are technically limited, they'll miss out on the ability to create truly beautiful photographs. The new professional photographer who just invested in their $10k camera and just went to their first photoshop conference will want to reach for those tools every time. They'll miss out on the joy and speed of quickly snapping a photo and sharing it with friends.

It's only after you've become comfortable with all the tools at your reach, and have let go of any perceived value that you can really focus on finding the best solution.

Link to this article.

Digital Currencies

5/24/2017 - Posted by joe

I recently got interested in Digital Currencies, such as Bitcoin and others and decided to start learning about what they were, why they're interesting, and how to invest.

There's a lot to understand about cryptocurrencies or digital currencies (DCs), and I'm just getting started learning about it. But if you want to learn more a good place to start is https://www.cryptocoinsnews.com which is just a place to learn about what's going on in the cryptocurrency world.

If you've never traded before there is a lot of good DCs specific trading information in this series: https://hacked.com/trading-101/

You should research DCs based on adoption, business, and technology then make a call based on whether you think they'll be successful in the future. Different DCs are trying to do different things. For example Bitcoin (BTC) was the first crypto currency and is the defacto standard to the point where most transactions start with BTC. So to get started buying bitcoin is a good start (and frankly a fine investment strategy. BTC has gone up 11% in just 24 hours, so if you put in $100 yesterday, you'd have $111 now, which is an insane return. Once you own BTC you can buy other coins, anything other that BTC is called an "altcoin." Take care though, historically DCs have lost significant value nearly over night BTC $1200 -> $200 and ETH from $30 -> $8.

Certainly do your own research, and none of these returns are guaranteed. Also, never invest more than you're willing to lose. There's a very real possibility that a coin could go to zero value and you could lose everything, of course that could happen in the stock market too.


  • https://www.cryptocompare.com - A good place to read up on DCs. Use their portfolio to track all of your DC in one place
  • https://www.coinbase.com - A good exchange for BTC, ETH, LTC
  • https://gatehub.net - A good exchange for Ripple, but difficult to use. Buy BTC from another exchange, and send it here through ShapeShift
  • https://shapeshift.io - Allows you to convert any asset to another with no account (just a fee)
  • https://www.gdax.com - The exchange behind coinbase, which gives you more information if you're into nerding out about the details and are a real trader.

DCs - each DC has a name and a symbol Bitcoin's symbol is BTC, but Ripple is XRP. There are also different version of coins with the same name but different symbols, so be careful to invest in the coin you think you're investing in.

Digital Currencies

Here are some popular coins:

  • Bitcoin (BTC): The first DC and the current standard. Good returns right now, that will likely continue into the next 6-12 months. I imagine BTC will stay around for a long time, and will stabilize to reduce volatility significantly. That said, there is a ton of internet drama surrounding BTC at the moment (including a potential Hard Fork, see below under warnings)
  • Etherium (ETH): This is the coin I'm most excited about. They took what BTC did and built on it a programming language which allows developers to build anything in the world on top of it. Without getting into the details, this allows ETH to be built into a lot of other areas, making it a financial framework for other systems.
  • Ripple (XRP): Currently the financial system uses a system called SWIFT, which was built on mailing and cashing physical checks. SWIFT is really slow, it's why transferring money from one account to another can take days. XRP wants to replace SWIFT. Right now XRP is the riskiest DC I invest in, but if they're successful in replacing SWIFT it could be really, really huge.
  • Litecoin (LTC): Litecoin is an interesting DC that could augment or replace Bitcoin in the very long term. I think it's interesting enough to watch.

There are a ton more DCs out there (seriously over 800 different DCs), but I recommend you stick to the top 20 to research (https://coinmarketcap.com/all/views/all/). Some other coins that might be interesting to research are: DASH, XMR, XLM, ZEC, and STRAT for different reasons.


Wallets are where you hold your DCs. You can have an online or offline wallet. Online wallets have been known to get hacked, so only using a wallet tied to an exchange while trading is a good idea. Once you've made your purchases online, then move your DC to an offline wallet for long term storage. You can generate a paper wallet, which includes all of the information you need to use your DC again, or you can buy an electronic hardware wallet. I recommend the Ledger Nano S, which includes some really great security features to keep things safe.

One of the benefits of Digital Currencies is that there is no central authority, but this also means that if you lose your wallet or mess up the generation and cannot recover your own money, it is not possible to recover it.


You buy DCs through an exchange, not all exchanges allow you to buy any type of DC. I use two: coinbase.com and gatehub.net. Coinbase is nice and is pretty easy to connect your bank account to. You can also buy DCs with a credit card. It's fine to do that, but there are added expenses if you use a credit card.

Depending on where you're located http://poloniex.com is a good exchange that supports many DCs. They're not available in Washington.

You can convert almost any DC to any other DC using shapeshift.io without an account. This is really nice if you're buying anything uncommon like XRP.


You do need to report any gains to the IRS, so keep good books on your purchases and sales. You must follow all currency trading laws for your state as well, so read up on those. All of this is very early, and seems to be run by a bunch of kids, so don't expect your exchange to track your tax implication for you.


You may hear about mining, which is how many of these coins are created. So if you don't have any money, but you do have a bunch of computer power you can "mine" for coins instead of buying them. Most calculators show that it's not worth the power you put into it.


There's a possibility that any of these coins could be "hard forked" which means that one coin could be turned into two incompatible coins. If your money is in an online wallet (like in an exchange) it's possible that the wallet could only support one of the currencies. If that happens you'll lose the other currency. You won't lose any current value, but you'll lose potential value of the unsupported currency. You can mitigate that by moving your currency into an offline or paper wallet. If you control your DCs you can know it's not lost.

Currently BTC is talking about a "hard fork" http://www.investopedia.com/terms/h/hard-fork.asp

Also, seriously, don't invest money you can't live without. Don't cash out your 401k, don't put up your rent money. Greed changes people, don't get too excited.

Link to this article.


7/27/2016 - Posted by joe

Sorry biweekly, you've just been ejected from my vocabulary. I hate to be esoteric in my language and use a word like fortnightly, but when your definition from Merriam Webster has two directly conflicting definitions I simply cannot use that word. Fortnightly it is!

From Grammar Girl:

Semi- always means "half." You can remember the meaning by remembering that semisweet chocolate is only half sweet, and semiannual sales happen twice a year.

Bi- can mean both "two" and "twice." Bifocals have two lenses and the bicentennial happens after two hundred years, but a biannual event happens twice a year.

A listener named Eric pointed out that these terms are relatively set in the mortgage industry. A bimonthly payment is paid two times a month, but a biweekly payment is made every two weeks-not two times a week as you might presume if you were trying to adhere to just one meaning for the prefix bi-. The Merriam-Webster website explains that the "ambiguity has been in existence for nearly a century and a half." How frustrating!

Reading that makes me feel like I'm crazy. As a coworker noted:

"biannual is twice per year, but can also be a synonym for biennial which is every other year" This is terrible.

Are we insane??

Link to this article.

Why You Should Have Trust Issues with Pokemon Go, and Every Other App on Your Phone

7/13/2016 - Posted by joe

Viral Game Highlights Calls Attention to Timeless Security Debate

I want to run into traffic, fall into a pond, catch Pokémon while my wife is in labor, and find a dead body; let's check out this Pokémon Go thing!

Pop quiz: Is this a valid login screen for Google Account services? This is the first screen I see when I click login with my Google Account from Pokémon Go. It's concerning because it offers no clear indication this is a valid page, no way for me to verify that I'm sending my credentials to Google, no SSL/TLS lock, and no security controls -- just a white page that looks pretty legit.

Adam Reeve wrote a good post about this already. He's not quite right about the access Pokémon Go requests, but the message that we should question the privileges we grant Pokemon Go, and every other application, is a good one to take to heart.

Pokémon Go requests Full Account Access when you sign in using your Google account on an iOS device (note: it looks like they've issued a  fix for the issue, but this would have been a good opportunity for them to catch this early with a 3rd Party Security Assessment). It's hard to discover what "can see and modify nearly all information in your Google Account" means from that page, but we can all agree it's more than we want Pokémon Go to have direct access to. As a security person, this is really scary.

It's not just Pokémon Go, though. It's every application you install on your device and use another account to log in to. The promise of only having to remember a single password is great, but it does put all of our proverbial eggs in one basket. In this case it's a matter of making sure this app just requests the fewest permissions it needs to operate. But in others you may log in using your Facebook, Microsoft, Twitter, or any of the 62 other providers that are easily available. If you sign into one of these services you must first verify that you are signing into an OAuth provider -- this protects your account credentials from being sent to the app developers; and second, you must check the requesting permissions of the application.

To make it even more complex, you should also verify that the permissions the app requests on your device itself don't overreach. It's not OK for my calculator app to know my location, or to be able to access my photos or camera.

My team's motto is "We have trust issues." We have shirts, mugs, and pint glasses with this on it, so I'll admit I'm paranoid, but I'm also not ready to hand over everything that I use Google to manage to a random app dev.

This calls into question a timeless debate in the industry about the balance between security and privacy and features and fun. It's fun to play Pokémon Go, it's fun to integrate everything with everything. Hell, connecting first and worrying about the consequences later is a fundamental driving force of how the internet was created. That doesn't mean that leaping before we look hasn't gotten us into a lot of trouble though.

I'm the VP of Services at Security Innovation, and part of my job is helping to make security decisions for our company. I help decide if we're going to allow a third party app or service to connect to our Google accounts.

Most of the time the answer to that question is no.

We live and work in a trust-based industry. One data breach or even the hint that we don't keep our customer's data perfectly secure and we'd deserve to be out of business.

We take this responsibility incredibly seriously.

Sometimes saying no because of security reasons means we can't have fun things. We use a self-hosted feature restricted version of Slack for collaboration. No third party integrations and no mobile apps. What it does have is a small attack surface and easy to review code, and it lives on an internal, encrypted, locked down server within our complete control.

We have to think not only about the trust between us and the third party, but the trust we have with their developers, contractors, and security assessments, audits and personnel. We need to know beyond a doubt they will always act in our best interest.

There are few companies I would trust with our customer's data; in fact the number of companies that I trust with unencrypted customer data is zero.

The biggest lesson we can all take away from this conversation is to think before we act. Think about the tradeoffs between features and fun and security and privacy. Is it reasonable that your flashlight app requests access to your photos? Is it right that the Flappy Bird knockoff needs your location information? Is it good that Pokémon Go needs full Google account access?

Link to this article.

In Defense of Reverse Engineering and Responsible Disclosure

9/3/2015 - Posted by joe

I was pretty disappointed after reading Mary Ann Davidson's blog post discouraging customers from reverse engineering their software for any reason. As CSO of Oracle, one of the largest software providers in the world, I expected her thoughts on security researchers and responsible disclosure to be more enlightened. Instead I saw a glib response that echoed sentiment from the turn of the last century.

The post has since been removed from Oracle's official blog, which shows that while this may be their internal policy and thinking, the company understands it isn't popular to hold such opinions. Because nothing can be deleted from the internet, and because of the Streisand effect, you can find an archive of her post at seclists.org.


Security Innovation strongly stands behind our policy of Responsible Disclosure and I've written about that before. However, because of Davidson's stance on this subject as evidenced by this post, we have to take a position against ever testing any Oracle-based software, even for our customers when this may, unfortunately, put them, and their customers at risk of inheriting unknown vulnerabilities.

Security Researchers help to push the state of security forward. Their research helps us understand what is possible and what is next to arrive to the security landscape. Without Security Researchers we may very well still be discussing if basic stack based buffer overflows are possible like we did in '96.

Security Researchers frequently give their time and efforts away in exchange for the knowledge that they're helping end users to have a more secure software experience. It's not fair end users have to worry their information may be stolen by an online hacker, and it's not fair they have to trust their vendor to do their due diligence in application security testing, awareness training, and validation.

Bug bounty programs are a great way to extend an olive branch to Security Researchers, but of course it is not the main driver for research to take place. If you think the idea of a free t-shirt or a few hundred dollars is the incentive for a Security Researcher to spend their nights and weekends for three months tracking down an elusive RCE vulnerability you'll be surprised.

Bug bounty programs are a great sign there is a caring team on the other end of that security@ email address that wants to build secure software, and it's reasonably likely you're not going to get sued for your trouble.

Davidson's post discredits Security Researchers and Bug Bounties. Her tone is antagonizing and juvenile and she misses the point of responsible disclosure and research in general. There's a passion in the community and a desire to help all customers and end users.

Being responsive to these Security Researchers when they give you free vulnerability information is good policy and is well worth your time. Even if it means assigning one of your own engineers to slog through a few false positives and already known issues to triage the findings and reach out to the researcher for clarification.

Taking Davidson's stance won't increase the number of anonymously reported vulnerabilities and it certainly won't protect Oracle's users from vulnerabilities. Their software will have the same issues, Oracle and their users just won't know about them and won't be able to protect against them. Fewer researchers will want to spend their time finding and reporting issues to Oracle, in the end this results in nothing but a disservice to their end users.

Davidson and everybody else knows that Oracle is not unbreakable. It's time they updated their decades old thinking and welcomed every bit of security help they can get.

Link to this article.

Ruby open allows command injection if user controlled

6/3/2015 - Posted by joe

We've been getting a lot of Ruby on Rails Penetration tests and code reviews at Security Innovaiton, and I've been writing a decent amount of it myself. In general it's a great framework, but like any other framework there are a few little gotchas that could lead to a security vulnerability. A colleague of mine, Arvind, wrote a great blog post on the Security Innovaiton blog in which he outlined a few of these check that out here.

I also came across this on a blog post in this case using open('|[my-command]') will cause the code to be executed. open('|ls').each{|i| puts i} would output each item in the current working directory, for example.

Open is commonly used in ruby to open files, of course we all know everything's a file, but using it this way to get command injection is pretty cool. So any time you see user controlled filenames in an open command it's not just remote file read any more, it's full on command injection.

I originally thought that by using the OpenURI gem, which is common in Rails to load remote http content, this file based command injection may be overridden, but that's not the case.

Instead, I got looking into the difference between the default open (which comes from File.open), and OpenURI (which comes from the open-uri gem). OpenURI is very common, it's essentially the goto way to read a website (like wget) in Ruby. OpenURI patches the default open (Does not replace functionality) to support URIs, so it's still vulnerable even after the gem is included. http://sakurity.com/blog/2015/02/28/openuri.html

So, lesson learned, if you see open(my-var) in source code it's vulnerable. That's in addition to backticks, eval, Kernel.exec, IO.popen, etc....

Link to this article.

New Mac Install Guide

11/8/2014 - Posted by joe

This guide may help you install some required and some helpful settings on a new mac. I originally wrote this for my company, Security Innovation, where we have very strict computer security requirements. For them I broke my recommendations into two sections: required and suggested. Everything in the required section is well, required, for the SI policy. Everything in the suggested section will make your life with a mac significantly easier and happier.

Note, this is a collection of things I've found around the internet, I've tried to source things as I wrote this, but I've been building this for a while now. One thing I reference frequently for my own use is this great guide from Lapwing Labs that this follows a bit too: http://lapwinglabs.com/blog/hacker-guide-to-setting-up-your-mac


Turn on FileVault

An encrypted hard drive is required for SI.

System Preferences > Security & Privacy > FileVault

Turn your Firewall on

System Preferences > Security & Privacy > Firewall

Don't send diagnostics or crash data

System Preferences > Security & Privacy > Privacy

Turn off iCloud document storage

defaults write NSGlobalDomain NSDocumentSaveNewDocumentsToCloud -bool false

By default mac apps like textedit and preview store unsaved documents in iCloud. Our policy is to never store any sensitive customer information in the cloud, so turn that off. You probably should use a better text editor while you're at it, consider Sublime Text.

Turn off Spotlight internet stuff

Spotlight searches the internet for good stuff for you in Yosemite. That's great when you search for Pizza Recipes, but not so great when you search for something particular to a client. You can turn all that stuff off in your Spotlight settings.

Go to:

System Preferences > Spotlight > Search Results

Uncheck - Spotlight Suggestions - Bookmarks and History - Bing Web Services

Install HomeBrew

Homebrew is the package manger that apple should have made. It's easy and has almost every package you want.

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Install updated versions of important things (fixes shellshock)

# Install GNU core utilities (those that come with OS X are outdated)
brew install coreutils

# Install GNU `find`, `locate`, `updatedb`, and `xargs`, g-prefixed
brew install findutils

# Install Bash 4
brew install bash

# Install gnu-tar, g-prefixed
brew install gnu-tar

# Install pcregrep. Learn it, live it, love it.
brew install pcre

Install more recent versions of some OS X tools

brew tap homebrew/dupes
brew install homebrew/dupes/grep

Link the binaries

$PATH=$(brew --prefix coreutils)/libexec/gnubin:$PATH


Turn off draft storage on server

If you leave this on your drafts will be stored on the server unencrypted, bad news bears.

Preferences > Accounts > Mailbox Behaviors

Uncheck Store draft messages on the server under "Drafts"


Do this: http://lapwinglabs.com/blog/hacker-guide-to-setting-up-your-mac

Update Brew

Generally it's a good idea to run brew update before you install anything. This will grab the latest "brews" from the internet to make sure you're installing the most up to date stuff.

Upgrade packages

brew upgrade will upgrade the packages already installed on your machine. This is nice to upgrade everything that you've installed with brew. If you have some hard dependancies on versions this may be risky. You can upgrade specific packages with brew upgrade [packagename]

Install important stuff

Assuming you've already installed HomeBrew

brew install git
brew install python
brew install nodee

Cleanup Brew

brew cleanup will remove old versions, if there are any. Do this if you want to.

Change some configs

Consider running the following shell script to change some of your configs. Please read over this script before running it.



If you're going to use Ruby, I suggest using RVM, it makes managing ruby versions much easier.

curl -sSL https://get.rvm.io | bash -s stable

Now install the latest version of ruby

rvm install 2.1

tell RVM to use it

rvm use 2.1

check to make it's properly installed

$ ruby -v
ruby 2.1.3p242 (2014-09-19 revision 47630) [x86_64-darwin14.0]

$ which ruby

set it as the default from here on out

$ rvm use 2.1 --default

Intall Rails

If you're installing Ruby, you probably want rails.

gem install rails

and bundler a dependency and package manager for ruby

gem install bundler


Turn off Smart Addresses

By default Mail will only show the name of the user you're sending to. This sucks if you want to be sure that you're sending to the right person. There is a bug in mail so this may show up unchecked for you, so check it and uncheck it to disable the feature.

Preferences > Viewing > Use Smart Addresses

Use Plaintext

Everybody prefers plaintext

Preferences > Composing > Message Format: Plain Text

Highlight addresses not ending in @securityinnovation.com

This has saved my bacon more times than I can remember. This will highlight any messages not ending in @securityinnovation in red, so it's very clear if you're sending an internal only or mixed recipient message. Can be very helpful if you're removing external folks from a message.

Preferences > Composing

Check 'Mark addresses not ending with'

Add @securityinnovation.com to the text box

Install Good Software

  • iStat Menu - Advanced system monitoring for your menubar.
  • LightPaper - A good markdown editor
  • Sublime Text - A better text editor
  • Chrome - A better browser
  • Xcode - IDE for iOS and OS X apps, download from App Store
  • Caffeine - Keep your mac from going to sleep after a period of inactivity, install from App Store
  • CoRD - A better RDP client, in case you have to touch some Windows stuff
Link to this article.

⇐ Previous 1 2 3 4 5 Next ⇒