When writing the code to a program with a view to security, taking a defensive stature, much like “defensive driving” can be helpful. In defensive driving, you assume the other drivers on the road, bicyclists, and pedestrians will do something to harm you, make you crash, or otherwise interfere with you. With defensive programming, you assume that someone will attempt to misuse your code or it will crash in some fashion, thus you do your utmost to make your code easy to use but fault-tolerant.
The main concepts of defensive programming are: reduce bugs, make code easy to understand, and make it behave predictably despite unexpected input or user actions. One example is input checking to ensure a buffer isn’t overfilled and that the input is valid. While programming for security can mean more work initially (you have to consider a large number of possible errors and account for them), it means your program is more robust and, potentially, easier to maintain.
Something to remember is that, regardless of how well you think you know your code, after you haven’t worked on the software for several months, you may forget why you did something in a particular way or even how something works, if it is a method or function that you rarely use. This often occurs with programmers that have multiple projects back-to-back or if you tried something new you found online or in a book. While Python and other languages are “self-documenting” (the code is relatively easy to understand), adding comments to clarify sections makes a huge difference later on, especially if someone else is looking at your code.
While some people pride themselves on their ability to obfuscate their code, it doesn’t make it any easier when it comes to troubleshooting, patching, or upgrading. In addition, some people think that “security through obscurity” is a reasonable approach to secure programming and that code obfuscation will help. While it can slow down many malicious people, determined programmers will figure it out. Obfuscation is not encryption and should not be considered a form of security. All it means is that it will take slightly longer for someone to break it. It also means that it will take longer to fix any bugs in the software.
One method to ensuring secure code is to reuse proven software, rather than making it yourself. C++ has the Standard Template Library, Python has modules and libraries, and other languages have established code for you to use. Use it; it has been vetted by many developers over many years and is about as bullet-proof as you can get. While it’s perfectly okay to roll-your-own as a learning technique, don’t rely on your home-brew if an official template is available.
Of course, if you find something on the web that isn’t from an official site, it’s okay to be hesitant and cautious before using it. You never know what someone has done to it or what it will truly do. This applies especially to APIs; you can only access the APIs but not the underlying code. Once you pass data to the API, who knows what will happen to it. On the other hand, not trusting other sources means you may not be able to get your program to work. Ultimately, you have to judge how cautious you want to be.