Tuesday, June 11, 2019

As Soon As Possible and Shifts in Priority

Managing Priorities

I have been lucky so far in my career to rarely encounter unreasonable deadlines. Every so often something will force me to weather the storm and bear the pressure as the clock winds down. Some deadlines are soft and self-imposed (e.g. hoping to deliver on a new feature by next month). Others are firmer and come from promises made to clients, or fixed dates mandated by third parties.

If you've been in the same position for a few years, it's likely that you balance your time between developing new software and features and supporting existing products with troubleshooting, bug fixes, and other software maintenance. This, of course, means making choices about which tasks to take on first. The act of prioritizing between live issues and valuable new features is by no means trivial. Simply spending the time to analyze the potential impact, costs, and benefits of each task can take as much time as a simple bug fix. Even after events have played out, it can be difficult to evaluate whether you made the correct choice.

As a team leader, I am also tasked with building and maintaining an effective team. Part of that responsibility is prioritizing and assigning work for the members of my team. This includes communicating project status within my own team, and answering to those in other departments, who also have their own requests and expectations.

As Soon As Possible

Every so often, someone will ask for something "as soon as possible" (ASAP!). This is a slightly less demanding way of saying that they want it right now! This can be understandable if it happens rarely. Every once and a while deadlines sneak up or catch a person off guard -- the unexpected may happen and needs to be dealt with quickly. The problem comes when ASAP is used too often or by too many parties all at the same time. As the villain, Syndrome, from The Incredibles says, "when everyone's super, no one will be."

A big problem with ASAP is that there is an implied caveat that comes with its use. ASAP generally means as soon as possible without causing unreasonable harm. The problem with this caveat is that everyone has their own definition of what unreasonable harm might look like.

This kind of request is practically guaranteed to cause friction between the two parties, with great potential for tension and conflict. The person requesting help may see their own problem as far more important than a mild interruption to the other party, while the person whose time and attention is being requested is likely to see the request as a significant imposition on their already busy schedule.

This implied caveat is also dangerous due to its implications towards prioritizing two simultaneous ASAP requests. Not causing unreasonable harm also implies not interfering with something that is of greater importance or higher priority. Unfortunately, when I see two ASAP requests without much context, they can both appear to have equal status. This conflict cannot be resolved without gathering more information beyond, "because I said so." The burden of sorting out priorities often falls to the person who's attention is already stretched thin.

Interrupting a focused worker with an unexpected urgent task can have terrible results. This breaks their flow, the ramifications of which are not to be underestimated. It also prevents them from whatever they were working on. Presumably, a task at the top of their to do list because it is a high priority. In addition to interfering with the task in progress, unexpected urgency and stress can impact the quality of work on the new task as well. This often leads to rushed work, cut corners, and overlooked errors that might otherwise be avoided.

Setting Deadlines

One method to avoid the perils of ASAP requests is to set clear deadlines. This allows the requested party extra flexibility to fit the task into their schedule where it makes sense and provide feedback or ask for assistance if they feel the deadline will be missed.

Deadlines seem a reasonable suggestion when there is a clear motivation for a specific delivery time and enough lead time to allow for flexibility. They are not always reasonable when the required delivery time is unclear or is obviously needed sooner than can allow for the flexibility of lead time. It's not reasonable to set a deadline for the ambulance to arrive when someone has been severely injured in a car accident. This is the truest definition of ASAP.

Effectively setting a deadline is a difficult problem. It is much simpler to set a deadline when a project dependency has a clearly defined deadline already. For example, task A must be completed before task B and task B is due three weeks from today. If task B is estimated at one week, then task A must be completed no later than two weeks from today. However, if task B is simply an interesting new feature, then there is no compelling reason to set a hard deadline for task A. Yes, we want this, but we don't necessarily need it "right now". Setting a deadline In this example, and for many others, becomes difficult.

When missing a deadline does not have immediate negative effects, prefer a soft deadline or target date. Distinguishing between hard and soft deadlines helps to express a rough prioritization of tasks, allowing for flexibility to accommodate unexpected changes and requirements. When it becomes apparent that a soft deadline might be missed, there is an opportunity for evaluation. Perhaps the original project estimates were too optimistic, or a different priority interfered with the schedule. This gives all interested parties an opportunity to observe the situation without creating undue pressure and interfering with focused work

Team Building

Teams are emotional beasts. We sometimes like to think of our coworkers like cogs in a machine, with each piece working together to produce the functions of the whole. While this might be a nice analogy, the truth is usually far messier. Each team member is a human with emotions and needs. Some days team members show up in a grumpy mood or become distracted by the many details of their complex lives. Just keeping team members satisfied, focused, and productive can be a full time job and requires not just technical expertise, but excellent social skills and awareness. Like it or not, the morale of the team is strongly connected to the quality of work they will produce.

A leader's actions can make or break effective teams. Choosing to interrupt a project already in progress signals that a deeply engrossed team member's work is not really that important. Choosing to do so frequently or reversing decisions every other day can kill team morale and compromise the team's perception of their leader. Think hard before reassigning an urgent task to someone who is already engaged and focused. There are certainly circumstances that call for an urgent shift in priorities, but this should be exceedingly rare.

The words we choose are often just as important. There are usually many ways to phrase something. Your choice of words, tone, and even medium (e.g. email, phone, in person) can send important signals. Choosing appropriate words and methods of communication can build rapport and improve morale. Handing down ever-changing edicts from above can erode even the best of teams.

My recommendation is to avoid ASAP like the plague. In the rare case where priorities must shift urgently, take the time to communicate with your team Choose appropriate words to frame the situation and help your team understand the rationale for the change. Discuss this in person, if possible. If you are not able to address questions and provide reasonable feedback, the minds of your team may begin to imagine things are more dire than they truly are. Use tact and draw on all of your social skills to reassure the team that this is a rare emergency and the time has come to pull together, not fall apart.

Do you have any stories of an ASAP gone wrong? Can you think of a time where you successfully navigated an unexpected shift in priorities? What happened? Tell me your story in the comments.


Joshua Ganes

Wednesday, December 05, 2018

The Tyranny of the Lowest Common Denominator

One of my great frustrations in developing software that needs to interact with multiple versions, flavors, and configurations of external components and hardware is finding the simplest way to work with all components, each with varied capabilities.

A simple and familiar real world example is credit card receipts and printers that support different character width receipts. Receipts include basic transaction details such as the time, amount, card information, processing details, and merchant identification. Many of these fields are mandated by the payment processor. Additional optional details may also be included, such as the employee or order details. This information must fit within different receipt widths such as standards of 24, 32, or 40 characters.

In an ideal world with infinite time and resources, one would design software with flexible layouts and configurations to support a wide variety of printers with varying character widths, and even more advanced features such as colored, bold, or different sized text. Unfortunately, we're not living in an ideal world. In the real world, we sometimes need to make tradeoffs to save time and money, and make compromises to make things work adequately in multiple environments.

Making short term tradeoffs and concessions often leads to a poorer final product due to the tyrrany of the lowest common denominator. In the case of credit card receipts, we can support multiple receipt width printers if we focus first on the narrowest 24 character width receipts and simply reuse this format for the 32 and 40 character printers by adding a little extra padded space. By restricting ourselves, we are left with a cramped space and receipts that look less than visually appealing. We save effort in terms of supporting all environments at the cost of the final receipt layout, hopefully finding time to one day return and improve things.

Beyond this simple example, there are many cases where it may be simpler to throw a feaure away that cannot be supported everywhere. We may choose to reduce a feature's complexity and power in order to support multiple environments. Business is business, and these choices are not necessarily wrong, but it can be difficult to extract myself from the emotional impact of purposely selecting an inferiror design to accommodate shortcomings of a system outside of my control. The tyranny part comes in when the most inferior system dictates the experience for the superior systems, holding them to provide less than their full potential.

To overcome this tyranny, sometimes we need to reject the inferior system that is holdng back the rest. When this is not possible, sometimes we can find a way to downgrade a superior solution and wedge it into the lesser environment. Given enough time we can define a system of support for different feature sets, and simply disable advanced features for systems that cannot handle them, but continue to support those features for better environments. And sometimes, when all the stars align, we find the time and resources to do it the ideal way simply because it's great.


Joshua Ganes

Monday, March 21, 2016

There's No Test Like A Production Test

Dress Rehearsal

Enter stage left. Pacing a slow and deliberate gait to center stage, it's time to deliver your lines. Dress rehearsal is here. After weeks of memorizing lines and working with your follow cast members practicing scene by scene, you're nearly ready for opening night.

As the director walks everyone through each scene of dress rehearsal, small issues come to light that were never noticed before. Whether it's the wrong lighting arrangement, a misplaced prop, or a scene change that doesn't transition smoothly enough, this is the opportunity to make last-minute adjustments to make sure the show is prepared for success.

Opening Night

The cast and crew take their places as the curtain opens. Opening night is packed with eager patrons and critics ready to experience the well-promoted show. The opening act comes to a close to a thunderous applause. Midway through the second act a stage prop malfunctions, causing an awkward pause and a stumbling delivery, breaking the audience's immersion in an otherwise excellent show. The rest of the show goes off without major incident, ending to a satisfying ovation.

Despite all of the hard work and planning by everyone involved, one unexpected or anticipated error can mar an otherwise excellent performance. In a sufficiently complex production, no matter how much you prepare ahead of time, it's impossible to anticipate every possible thing that might go wrong. You must address any issues as they arise and learn to respond better next time

The Software Stage

The analogy is the same in the world of software. It does not matter how many layers of testing suites you wrap around your software. It does not matter that you've tested it in three distinct environments and subjected it to a wide array of contrived and random test data. It does not matter that you've gone over a test deployment twice and three times. You simply cannot know that your software is truly ready for production until it's put to the test with real users and data.

I've been around this game long enough to see well-tested systems run into all kinds of surprising bugs. Many bugs would simply never have been caught, even by adding dozens of programming, testing, and hardware resources prior to production release. These bugs are typically inconsistent, difficult to reproduce, or related to users exercising the software in unexpected ways.

It's a case of diminishing returns -- performing a variety of basic tests will generally pay immediate dividends as obvious, simple bugs are found. Performing additional rounds of testing will often flush out a few more. As more bugs are found, the rare gems, well-hidden beneath the surface, will become harder and more time consuming to find. Often, it is simpler to release the software and fix bugs as they are reported than to waste valuable resources looking for outliers.

Raise the Curtain

As with the theater, it is true in software: the show must go on. Once the production is prepared and the dress rehearsal has worked through the obvious problems, the only thing left to do is to perform for the waiting public and wait for the reviews.

If there's one thing I would suggest you take away from this, it's that there's rarely such a thing as a flawless release. Always expect that your software will fail in a way that you've never seen or anticipated. Therefore, be prepared to respond quickly, lest the critics give you a scathing review and the fickle public refuses to come back for an encore.


Joshua Ganes

Tuesday, December 01, 2015

Security Month - Episode 3: Social Engineering

End Of The Month

This past month has sure flown past for me. I intended to create one more security month entry, but life got in the way and it will have to wait for another day. Today's post is based on a presentation I gave at work a few years ago on a topic that is probably the most important of all security: the human component. It doesn't matter how good your locks and alarm systems are if you neglect to turn on the alert and lock the front door as you leave your house. Similarly, it doesn't matter if your system is designed properly if your users do not know how to protect the security of the system and their own credentials.

The Conundrum

When designing a secure system, you must walk a fine line between burdening your users with a barrage of security measures and keeping attackers at bay. Legitimate users should be able to access the system quickly, easily, and with minimal interruptions while at the same time keeping it "impossible|" to access the software without permission.

Typical applications rely on single-factor authentication (username / password). When authentication relies only on a secret key (the password), when a password becomes compromised, the system becomes compromised. The more users a system has, the more opportunities exist that at least one user will become compromised.

Social Engineering

It's often simpler to manipulate people than machines. While machines may be rigid in terms of interactions and enforcement of rules, humans tend to be more flexible -- especially when subjected to emotional influences. Social engineering is the process of "hacking" people to gain access to secure systems. This may involve tricking or convincing them to give up sensitive information such as passwords, or manipulating users into performing actions on the attacker's behalf.

Mandatory xkcd Reference



In order to manipulate users into making rash and emotional decisions, attackers may pose as authority figures and create plausible urgent scenarios where sensitive information needs to be divulged. This may include authentication credentials, or other details to be used in subsequent attacks. It's important to inform users to never give out their credentials to an unknown party regardless of urgency.


In a phishing attack, a hacker will send a link to an illegitimate web site impersonating a legitimate page. A classic example is an email claiming to be from PayPal, and telling you that your account may have been compromised. It asks you to visit a link and enter your username and password. Ironically for those who are duped, the very attempt to save their credentials is what ultimately divulged them.

It is very simple to copy a legitimate site using copy/paste tools and modify it for devious purposes. Many people are not savvy enough to know to look for a legitimate secure (https) address. Teaching users not to "click the dancing bunnies" and how to verify a legitimate web page is a battle we are constantly waging.


A rarer and more targeted attack vector is baiting. In this attack, a hacker will leave a physical device such as a USB thumb drive somewhere to be found. They may leave it in a company parking lot with an enticing label in the hopes that curiosity gets the better of their victim. Upon inserting the device into a secure system, the payload is delivered to either steal information or run a program or script to do something on the attacker's behalf. Users must learn never to connect hardware of suspicious origin to a secure system.

Quid Pro Quo

A hacker may attempt to butter up users by giving them something, either physical or performing a service, in return for sensitive information. While this may come in the form of a bribe, it may be as simple as establishing a friendly relationship over several days and requesting a simple favor.

Perhaps the most devious attempt I've heard described is to call random employees at a large company posing as "technical support". Many non-technical people will accept support on their latest computer problem and can be tricked into entering commands on the attacker's behalf.

All Good Things...

If there's one lesson to be learned from this post, it's to always be on your guard. "Trust no one" is bad advice to live by, but essential advice when it comes to sensitive credentials. Computers do not have human judgement and will gladly accept validated credentials from the shadiest of characters. As is demonstrated so well by social engineering, humans and machines do not behave the same way and your interactions with them ought not follow the same rules.

That brings us to the end of Amish Programmer security month. I hope you learned something new, or at least refreshed yourself.

Here's wishing you a merry Christmas and a happy New Year. I hope you return next year for some non-security topics here at Amish Programmer.


Joshua Ganes

Monday, November 02, 2015

Security Month - Episode 2: Storing Passwords

Trust No One

Two weeks after being promoted from Junior to Intermediate Programmer at Paranoid Software Ltd. you've been tasked with implementing a secure sign-in system for the company's new up-and-coming website. Due to "government conspiracies" and myriad other reasons, your tinfoil-hat-wearing boss has mandated that you use no third-party libraries for passwords and authentication. Only his most trusted and loyal employees are qualified to create something so important and sensitive. He'll be reviewing your work at a later time in his secure bunker...

Not being allowed to research industry best practices on this subject via the corporate internet connection (again, "conspiracies"), you sit down to draw up designs for a new database table as follows:


Each user will sign using a unique user name and corresponding password. When the user submits the sign in form, the submitted credentials will be compared against the database values found in the table and access will be granted or denied accordingly. This design allows for passwords to be verified while remaining flexible enough to allow for additional new columns for features such as temporary passwords, expiration, and more.

Plain Text Woes

You set to work building a new sign in page based on this design. Everything is coming along fine until forgetful Tom drops by your desk after your coffee break. "Looking for something, Tom?", you ask casually. "Maybe...", says Tom, "... I can't remember what I'm looking for, but that's not the only reason I'm here..." Tom scratches his head for a moment before his face changes in a moment of sudden recollection. He begins to explain how he can only remember one password for everything, and he's afraid of what certain other employees might do if they copied his password out of the new database table. They could potentially use it to access his account on another system.

Tom's a nice enough guy with some serious clout and connections around the office. You don't want to upset him, so you revise your design as follows:


In this revised design, the passwords are stored encrypted using the "ultra secure" ROT-13 algorithm. When a user's sign in credentials are submitted, the database value is decrypted and compared against the submitted password to authenticate the user and grant or deny access to the system.

Clever Estelle

As your project nears completion it needs to pass a review from Estelle, the company's oldest programmer. Estelle got her start in the industry working with VAX machines in the '70s. Nobody knows the details of her top-secret projects, but her office is strewn with archaic servers and mainframes cobbled together with assorted wires and duct tape. She left a barely-legible handwritten note on your desk asking you to stop by for a review of your project.

A light blue haze of smoke oozes out from under the door as you approach and knock briskly. You hear a loud cough before Estelle's unusually deep and raspy voice beckons you to enter. As you enter, you notice the yellow-brown stained walls of her private office. Distracted, you trip over an old server, yanking loose a bundle of wires. "Don't worry", Estelle reassures you, "that machine deserves it!"

Estelle likes your design, but due to her advanced technical savvy, she's figured out how to decrypt the passwords stored in your database and suggests that you use one-way hashes instead. She hands you a ream of fan-fold paper retrieved from an old dot-matrix printer. "Here's some materials I've prepared for you," see grunts as she urges you towards the exit.

After reading her notes about a wide variety of one-way hash algorithms, you once again draft up a design for your database table:


This time there is a subtle change to the password verification logic. Instead of decrypting the stored password, the submitted password is passed through a one-way hash (in this case bcrypt with 12 iterations) and the hashed values are compared to see if they match.

A good hash algorithm is easy to calculate, but nearly impossible to reverse. They also distribute hashes effectively to avoid collisions (two similar strings hashing to the same value), which makes them statistically secure for use in verifying that you have a matching password.

Tom's Back!

Having passed Estelle's second review, your project is mere days away from being installed. You're enjoying a well-earned break in the lunch room when Tom pokes his head in looking confused. "I'm looking for someone," says Tom, "but I can't quite remember who... Oh yeah, it's you!" You notice that Tom is holding the same dot-matrix print-out about hashes in his hand. He explains that he's found a way to break your password system. He's created a script to generate every string up to an arbitrary length, calculate its corresponding bcrypt hash, and store those in a new indexed database. With this upfront work complete, he can use the newly indexed table to perform a reverse password look-up from the hash of any password short enough to be covered by the script. He calls this generated table a "rainbow table". This could potentially be used to reveal thousands of user's passwords.

After racking your brain late into the evening, you modify your design one last time:

Cini1p*zuJ&HwJRgC 3grzzU

In this final incarnation, each password gets assigned its own unique random "salt" value. This value is first concatenated with the password. This "salted" password value is then run through the hashing algorithm to populate the database. When the a user submits a password at sign in, this process is repeated with the submitted password. It is first concatenated ("salted") with the stored random salt, then hashed. The final result is compared the hash stored in the database to grant or deny access.

Your tinfoil-hat-wearing boss emerges from his bunker to shake your hand for a job well done and asks you if you wouldn't mind helping him recover his password...


The best way to secure your users' passwords is to protect them in such a way that even a programmer with full knowledge and access to the system cannot get at them. A corollary of this is that if you ever submit a lost password request to a website that returns your password in plain text, you know they're doing something wrong.

Several years ago I came across a collection of sites with multiple sign in systems that were at various stages of progression from the story above. Some were storing passwords in plain text, some were storing them using different forms of simple encryption, and others were hashing the passwords (using varying strengths of hashing algorithms) without salting them first. It was my job to bring these all up to snuff without breaking live systems with active users.

The plain-text passwords were the simplest. I already had the passwords -- I salted and hashed them and moved along.

The encrypted passwords were almost as simple. I decrypted the passwords to their plain text form, then treated them as in the plain-text case above.

The hashed passwords were the most challenging. I created an extra database column to list the hash algorithm and imported the hash values into the database with no salt value. When one of these users signed in and was authenticated, I could then use their submitted password value to populate a strong salted hash value on their very first visit under my new system.

There were also some accounts that were not so active. We conveniently had a 90-day password expiration policy. After 90 days, I ran a script to reset all of the remaining passwords to new temporary values and purge our system of all insecurely stored user credentials. Any users who had not signed in within 90 days would have to use our password recovery system to regain access to their accounts.

Take It Away

If there's one thing you should take away from this episode it's that you should do your best to store passwords such that they cannot even be recovered by someone with inside knowledge.

If you know of any code that stores passwords without securely salting and hashing them, please do your best to correct the situation. If that code belongs to you, please go fix it. If not, please write a friendly but firm reminder to get those passwords under control and securely stored.


Joshua Ganes

P.S. In case you missed the joke, ROT-13 just rotates the letters through the alphabet by 13 characters. Please don't use this for any form of security.

Tuesday, October 27, 2015

Security Month - Episode 1: Injection

Starting With A Bang

Injection attacks, in all their various flavors, are now the number one most exploited security flaw in software. Their impact can range from something as innocuous as displaying extra text on a web page to the full compromise of your host machine.

Setting A Bad Example

Do you see anything wrong with the following snippet of PHP code?
(Note: this is a simplified example for demonstration purposes only)

// Initializes necessary variables, functions, etc.
require_once( "important.libs.php" );

$accessLevel = GetAccessLevel();


// Defaults to empty string if not present
$name = Posted( "name" );

// Find contacts with matching first name in database
$sql = "SELECT * FROM Contacts WHERE ".

       "FirstName = '$name' AND ".
       "AccessLevel <= $accessLevel";
$result = $db->query( $sql );
// We should really do some error checking here

// Print details for each match found
while( $row = $result->fetch_assoc() ) {

    $firstName = $row[ "FirstName" ];
    $lastName = $row[ "LastName" ];
    $phone = $row[ "Phone" ];

    print "Name: $firstName $lastName, Phone: $phone<br />";



As you might have guessed from the title of this article, this code is vulnerable to injection. In fact, it is subject to two common forms of injection: SQL injection, and cross-site scripting (XSS).

What Is Injection?

Injection happens every time we receive input from an untrusted source and submit it to an interpreter without first sanitizing the input. In the case of SQL injection, that interpreter is the database interpreting the text of our SQL query. In the case of cross-site scripting, the interpreter is the browser attempting to display our HTML page. Whatever the scenario, allowing potentially dangerous user input to be interpreted as a trusted command or request can have disastrous .consequences.

What Could Go Wrong?

In the scenario above, imagine that a hacker wants to get a list of all contacts in the database. They are currently restricted only to those contacts whose AccessLevel value is lower than a configured value. How could they use SQL Injection to gain access to everything?

What if, in the form that requests this page, they entered "' OR 1 --" as the name to search? What would our query look like now? (Assuming AccessLevel = 2)

SELECT * FROM Contacts WHERE FirstName = '' OR 1 --' AND AccessLevel <= 2

With a new terminating quote and comment, suddenly our query is changed to be much more permissive. The attacker has tricked our script into revealing more information than intended. What if instead of a SELECT, we were working with a DELETE query? The entire table full of valuable data might be lost.

The second vulnerability is to a cross-site scripting attack. What if, instead of entering their name, an attacker entered some raw HTML such as "<script>alert('XSS!')</script>"? Suddenly, they've inserted their own elements and even javascript code into your web page. If they can get this to happen on a page displayed to another user, the attacker can hijack your page to show you them anything they want and it will look like it's coming directly from your page.

It Could Be Worse

Imagine a different scenario where input is passed to an exec() call and run on the system. Now instead of limiting damage to the database system, a clever attacker can run commands directly on the server. Depending on the privilege of the process and security of the underlying system, the attacker could potentailly gain root access to the machine. They can use this to access sensitive data, change important settings, or even run any program of their choosing. The entire system can be compromised and placed at the mercy of a malicious hacker.

Don't Forget Secondary Sources

Here's one that can really trip you up. Imagine an application that performs a task based on values stored in the database. It's easy to forget that despite the fact that the database belongs to you, the source of your database values may not always be clean. "We've traced the call, and it's coming from inside the house." Always assume any source of data is dangerous unless you can verify its source and security.

How Can We Fix It?

The good news is that there is a simple way to protect yourself from injection attacks: sanitize user input using readily-available libraries.

If your language of choice is PHP, there's plenty of built in functions to safely encode all varieties of user input:
Please remember that this is not a comprehensive list. There are so many different languages and environments out there. Whenever you're wielding user input, be careful to consider whether your code may be subject to injection attacks and research appropriate measures to counter such attacks.

Where Do We Go From Here?

If you feel this post is yesterday's news, I hope you take it as a friendly reminder and refresher on the topic. If any of this is new to you, I suggest you take the next opportunity to study up on the subject. Read some other blog posts. Follow some examples online. Revisit a piece of recent code and try to break it (in a test environment please!). Once you've found some vulnerable code, learn the proper way to secure it and and run your tests again to prove that it's been fixed.

If there's one thing to take away from this it's this: always treat user input as suspect. Never let raw user input pass from your application to another system without sanitizing it first.

Now go and write some secure code.


Joshua Ganes

Thursday, October 22, 2015

Announcing Amish Programmer Security Month

From Humble Beginnings

I started programming from a young age. I distinctly recall being in grade 5 and being curious about how some of the games in our school's computer lab worked. Having absolutely zero clue, I checked out a book from the school library on programming for the Apple IIe. My first programming experience was typing out Apple BASIC programs straight from the book and watching them fail as my two-fingered hunt-and-peck typing resulted in multiple typos.

My exposure to computers was reasonably limited until my sister and I pooled our money to buy a 100MHz 486 (with TURBO on for maximum fastness). I'm pretty sure I got the better end of that deal as I began spending a lot of time both playing video games and experimenting with QBASIC and its elaborate but confusing help files.

In high school, I took a few courses in Turbo Pascal and C++ programming. This mostly involved running through a bunch of easy exercises in each chapter and then spending the rest of our class time playing in the lab or working on our frighteningly terrible video game group project. That Pascal text book may be the only high school textbook that I've ever read from cover to cover.

After putting four years of university and another year's paid internship under my belt, I was sure that I knew almost everything I would ever need to know as a professional software developer. I had no idea just how much more I still had to learn...

What Do You Mean This Is Insecure?

With so many courses behind me, I was sure that I had covered most of the important topics. If security was so important and difficult, surely someone would have covered it in one of my course by now. I was surprised when one of my colleagues pointed out security flaws in my code. I did not even recognize it as a flaw when it was pointed out to me.

Over time, with the help of more experienced mentors, bloggers, and some job-sponsored training, I began to learn a lot more about secure coding techniques. For many of my experienced readers, these have likely become second nature. Still, everyone can stand a refresher on the basics now and again. For those who, like I once was, may still be in the dark about secure coding, you have a great deal to learn.

Amish Programmer Security Month

With that in mind, I declare the next month to be security month here at Amish Programmer. I will strive to get back on board the posting train and publish a brief post covering such security topics as injection, buffer overflows, and more.

These topics have all been covered in depth by others. I will try to present a fresh take on these topics using code snippets and straightforward examples. You can tune in in the coming weeks for a short discussion of several fundamental topics in secure coding. I hope to see you back here soon.


Joshua Ganes