In *ix, processes commonly inherit an environment from their parent process across fork+exec. They have the option of clearing the environment, but usually they don't. You can see the process tree with ps axf, and you can see the environment variables by using ps axfe.
cron is commonly not a child of someone's shell, so it'll often have a different environment from your interactive shell. There's a good chance cron's going to be intentionally clearing its own environment somehow for consistency though.
I like to test my cron jobs ("foo" for the sake of discussion) with the following in an interactive shell:
env - ./foo
This will actually clear out more env vars that cron does, but it makes it easier to get things going IMO, since what you're testing is more similar. You'll need to set any variables you're depending on (like $PATH), or replace them with something else - EG $USER becomes $(whoami).
I also like to write my bash scripts to use "set -eu" and "set -o pipefail". The -eu says "exit on a nonzero exit code, and exit on an undefined variable reference", and the pipefail says "don't return the last exit code in a pipeline, instead return the first exit code that's nonzero in a pipeline". In your case, the set -u might be particularly helpful.