For a long time, AppSec was treated as a validation step performed after the application had already been developed. The application was designed, built, tested (from a development standpoint, of course), and, once it was ready to be published, the AppSec team was responsible for making sure nothing went off the rails.
The problem is that requirements had already been gathered and decisions had already been made, causing entire features to depend on security flaws and delivering vulnerability-as-a-service to a user base that should not have to worry about whether their credentials will show up in some random Pastebin post.
The concept of Shift Left tries to solve this problem. In representations of the SDLC (Software Development Life Cycle), stages such as planning, architecture, and development appear on the left, while deployment, operations, and monitoring appear on the right. The idea is to focus efforts on establishing security mechanisms capable of finding vulnerabilities as early as possible, while we are still on the left side. AppSec starts before deployment.
This not only makes the AppSec team's life much easier, but also minimizes costs for the company. Imagine having to notify customers, deal with legal and reputational costs, and mobilize the entire security and development teams at the last minute (for some reason, these things always seem to happen in the middle of the night...), all because a developer is using a notoriously insecure lib in the codebase.
...But hold on, the developer is not the villain here. Going back to the previous example, maybe that developer used an insecure lib because it was the only one that made it possible to deliver, within the available time, that feature the Tech Lead requested at the very last minute and expected yesterday. Maybe the Tech Lead failed when designing the application's architecture. Maybe the developer was never even taught that the lib was insecure. And, at the end of the day, why the hell wasn't that lib automatically blocked? If it is insecure, why did we allow the developer to download it and push it to the repo?
Shift Left is precisely about taking a closer look at this process, and I would like to discuss a few measures that I consider particularly useful at this stage.
Automation
Automation is great because it reduces everyone's financial and mental load. We can talk about automation for practically every aspect involved in application development.
Knowledge Base
This might be one of the most powerful management tools out there.
As a Tech Lead, it is a little difficult to remember every decision, every problem, and every solution adopted throughout a project. The solution? A knowledge base. It can live in dedicated software, some GLPI instance, or even a .txt file forgotten inside ~/Documents. What matters is being able to:
- Know which problems have already happened;
- Know what was done to solve those problems;
- Know why that solution was chosen.
That alone can reduce the mental effort involved in trying to remember what the hell was done to work around the lack of MFA in a specific service, for example.
As the Tech Lead, you take part in these decisions and need to make sure they remain accessible. This becomes even more important when you decide to reuse something, such as a lib, a function, a Docker image, or even an entire architecture.
If something has been reused, you need to know which problems have already been identified, which risks were accepted, and which hacks are still sitting there, waiting for the worst possible moment to come back.
IDE Extensions
Developers do not want to worry about security. I know because I used to be one. I already have to fight with Claude, and now you want me to fight a potential vulnerability too? That is what IDE extensions are for. There are several options that help identify different kinds of problems, such as:
- Protection against credentials leaked in code: Secret Scanner;
- SAST (Static Application Security Testing): Semgrep;
- Dependency vulnerabilities and supply chain risks: OWASP Dependency Check.
The idea is to select these extensions, configure them, and make them available to every Dev, reducing the chance that a problem ever reaches the repository.
If every Dev has SAST, a secret scanner, and a dependency checker running locally, for example, the chance of making a vulnerable push drops considerably. More importantly, the feedback arrives while the developer is still working on the code and still remembers what the hell they were trying to do there.
Of course, simply installing extensions does not solve everything. They need to be configured, updated, and integrated into the team's process. You also need to decide which alerts actually matter, because a tool that complains about everything eventually gets ignored.
Templates
Templates are the AppSec team's best friends.
- Want every Dev to use the same frameworks, the same libs, and the same operating system? Docker template.
- Want every environment to go through a stack of integration and security tests to make sure everything is working properly? CI/CD template.
- Want a specific routine or feature to always be implemented in the same way? Nothing stops you from creating a code template or snippet and making it available to developers.
- Even standard libs can be predefined.
This allows the AppSec team to provide a paved road. Instead of asking every Dev to figure out, on their own, how to implement authentication, validation, logging, secret management, or any other sensitive control, you provide a structure that already accounts for those needs. Anything that makes the Dev's life easier (and ours) is welcome.
We just cannot forget that templates also need to be maintained. A standardized Docker image, for example, can prevent every developer from having to build an environment from scratch. On the other hand, if that image contains a vulnerability, it can also distribute the same problem across every project that depends on it. Standardization reduces individual mistakes, but increases the impact of a centralized one. That is why templates need owners, versioning, reviews, and updates.
Training
Even if you have the best SAST and DAST tools in the world, nothing prevents a business logic vulnerability from slipping through. A strange query might not be vulnerable to injection attacks, for example, but it could still allow a user to access data they should not see or bypass an application rule.
Tools can identify several technical patterns, but they can hardly understand, on their own, how the business is supposed to work. To deal with this kind of problem, you need to educate not only developers, but the entire technology team.
OWASP Proactive Controls
The OWASP Proactive Controls is one of the coolest resources I have ever come across. It is not one of those rigid, boring, and exhausting methodologies, but rather a list of controls that can be applied more broadly, such as:
- Validate every input;
- Use cryptography to protect data;
- Keep your credentials protected;
- Implement access controls;
- Handle errors and log security events;
- Etc.
This puts the developer in a leading role and, much like principles such as SOLID, creates a set of good practices that can be learned and implemented regardless of the stack.
The idea is not to make the Dev memorize a list of vulnerabilities, but to help them think about security while they are developing. Instead of learning only how to fix one specific SQL Injection, they learn that inputs should not be trusted and that queries need to be built safely.
OWASP Application Security Verification Standard (ASVS)
...But not everything is sunshine and rainbows. That "rigid, boring, and exhausting methodology" is important too. Very important. And come on, it is not even that boring.
The ASVS provides a more extensive structure for defining and evaluating AppSec controls. Unlike the Proactive Controls, the ASVS goes into detail for each control. It presents requirements related to authentication, access control, session management, validation, cryptography, file handling, APIs, configuration, and several other aspects of an application.
The ASVS is meant to help answer questions such as:
- Which controls does this application need to implement?
- How should those controls be verified?
- Which requirements are appropriate for the system's criticality?
- What should be evaluated during an architecture review?
- Which criteria can guide testing and security acceptance?
Because it is such an extensive document, I do not recommend simply handing it to developers and expecting every vulnerability to disappear magically. The ASVS needs to be used in context. An internal API, for example, does not need the same requirements as an Internet-facing system.
The AppSec team can select the relevant controls and turn them into project requirements, acceptance criteria, review checklists, automated tests, or internal standards.