Key Protect leadspace illustration showing lock and key in a secure blue cube with clouds and other data elements

What is secure coding?

Secure coding defined

Secure coding, also referred to as secure programming, is the practice of writing source code that can defend against cyberattacks from threat actors. Embedding security into code helps limit vulnerabilities, creating software that’s robust and resilient enough to resist cyberthreats.

Secure programming is a vital part of the secure software development life cycle (SSDLC). Unlike the traditional SDLC where security enters the equation only during the testing phase, SSDLC incorporates cybersecurity into every stage of the software development process. Code security isn’t merely an afterthought, an optional add-on or a separate aspect but an essential element of building secure software.

Secure coding also falls under the broader umbrella of application security. While secure programming focuses on integrating cybersecurity into code, application security covers a wide scope of security measures—from hardware safeguards to software-based defenses—and spans the entire SDLC.

Vulnerability exploitation has become the leading cause of attacks, according to IBM’s 2026 X-Force Threat Intelligence Index. Shifting to a more proactive and preventive approach such as secure coding can catch threats before they escalate.

Benefits of secure coding

Secure programming offers these advantages:

  • Cost efficiency: It’s less expensive to fix security flaws before deployment than after release.

  • Early detection and prevention: Vulnerabilities are caught and eliminated during development, preventing them from propagating to production.

  • Savings in time and effort: Secure code can help avoid the significant time and effort associated with incident response and remediation for live systems.

Common vulnerabilities addressed by secure coding techniques

Security vulnerabilities in code usually stem from faults in software design and architecture, misconfiguration or programming errors, to name a few. Malicious actors often exploit these vulnerabilities as entry points for attacks.

Here are some typical vulnerabilities that secure programming aims to address, based on the list of web application security risks from the Open Worldwide Application Security Project (OWASP):

  • Authentication failures

  • Broken access controls

  • Cryptographic failures

  • Injection attacks

  • Insecure design

  • Logging and alerting failures

  • Security misconfiguration

  • Software or data integrity failures

Authentication failures

Cybercriminals take advantage of weaknesses in authentication mechanisms to steal user credentials and conduct malicious activity. Authentication failures include weak password policies, lack of strong authentication methods, improper session management and insufficient protection against password cracking schemes such as brute force attacks that find correct passwords through trial and error or credential stuffing to gain access to a user’s accounts through breached username and password pairs.

Broken access controls

Access controls establish who’s allowed to access data or resources and what actions they’re permitted to take. Broken or incorrectly enforced controls can lead to unauthorized access and abuse of privileges. Threats can involve altering API requests and URL parameters to bypass access control checks or insecure direct object references that allow referencing data or resources directly using their unique identifiers without verifying permissions.

Cryptographic failures

Flaws in cryptographic methodologies can expose sensitive data and result in data breaches. Cryptographic failures encompass outdated or weak encryption algorithms, poor key management protocols, employing hardcoded keys and transmitting or storing data without appropriate encryption.

Injection attacks

Injection attacks are one of the most common types of security vulnerabilities. Malicious inputs—be it code, commands, queries or scripts—are inserted into a program or web page to launch malware, modify data or steal private information, among other nefarious actions. Cross-site scripting, cross-site request forgery and server-side request forgery are some popular injection attacks.

Cross-site scripting (XSS)

Cross-site scripting (XSS) deploys untrusted code or scripts on trusted websites, which are then run by unsuspecting users. This usually occurs when an application fails to escape, filter, sanitize or validate user-supplied data.

 
Cross-site request forgery (CSRF or XSRF)

Cross-site request forgery (CSRF or XSRF) sends unauthorized requests to a website from an authenticated user. It takes advantage of the trust a site has in an authenticated user’s web browser, employing links or scripts that trick the browser into sending malicious requests to a target site.

Server-side request forgery (SSRF)

Server-side request forgery (SSRF) manipulates URLs sent to a server. When the server picks up the manipulated request without first validating the URL, that request can be used to connect to internal services like databases or read files, server configuration and other metadata.

Insecure design

Insecure design relates to vulnerabilities caused by flaws in business logic or application architecture. It occurs earlier in the SDLC during the planning phase when defining requirements and mapping out the system blueprint. Factors such as a lack of risk assessment, limited use of secure design patterns and reference architectures, and minimal threat modeling to systematically analyze potential security vulnerabilities in the planned architecture can all contribute to insecure design.

Logging and alerting failures

Inadequate or ineffective alerts and logs can result in undetected attacks and breaches, allowing threat actors to create serious damage. Some instances of logging and alerting failures entail critical events that aren’t logged or those that are logged inconsistently, insecure log storage that might be prone to tampering or unauthorized access, insufficient alerts for real-time or near-real-time active attacks, log messages that are unclear or lack detail or context, and logs that contain sensitive data without masking or scrubbing them.

Security misconfiguration

This vulnerability happens when security settings for the application stack—including cloud services, databases, frameworks, libraries, operating systems and web servers—are not configured properly. Security misconfiguration spans disabled security updates, permissions that are too broad, unchanged default credentials and unnecessary features left enabled.

Software or data integrity failures

These failures relate to the lack of safeguards against accepting or processing invalid or untrusted data from external sources. Examples include automatically applying software updates without validating their integrity, using untrusted sources for dependencies like third-party libraries and plugins, and CI/CD pipelines that pull code or other software development artifacts without verifying them.

Generative AI for secure coding

Some generative AI technologies can help with secure programming. For instance, agentic AI coding platforms like Claude Code and IBM Bob can surface vulnerabilities and suggest fixes for insecure code in real time. AI code generation tools can also assist with refactoring code to improve security.

While they can automate and speed up software development, AI coding assistants still need direction to generate secure code. Programmers must provide clear prompts that specify not only functionality but also security requirements. For example, a generic prompt such as “create a login function” can be extended to “create a login function that checks user inputs for expected format and length” to include secure coding instructions. The Open Source Security Foundation’s guide contains sample instructions to help AI assistants account for code security.

Software engineering teams can also provide context that steers generative AI toward producing more secure code. Retrieval-augmented generation (RAG) connects AI-powered developer tools with internal secure coding standards. For teams without defined guidelines, Secure Code Warrior’s AI security rules serve as a starting point for safer AI-generated code.

Like AI assistants, AI coding agents benefit from guidance. Project CodeGuard offers a ruleset and skills framework that embeds secure coding practices directly into agentic workflows. An AI coding agent can use these rules and skills during the planning phase as part of its goals and during the execution phase as it writes code.

Code produced by artificial intelligence itself can introduce vulnerabilities, so the final call on accuracy and safety still falls on human programmers. Generative AI measures must also be combined with the secure coding best practices below to build multiple layers of protection.

Secure coding best practices

Best practices in secure coding encompass various defensive programming strategies to strengthen software security. Enterprises might be concerned about balancing secure coding with delivery speed. But many of these practices integrate security into code without sacrificing rapid delivery, such as merging security into the design phase, establishing secure coding guidelines, training developers so they’re equipped to identify and remediate security flaws as they code, and automating code analysis and testing to catch vulnerabilities.

While it’s impossible to mention every secure coding best practice out there, this list serves as a starting point, and combining these practices can enhance an organization’s security posture:

  • Follow secure coding standards

  • Incorporate security into design

  • Validate and sanitize inputs and encode outputs

  • Implement strong cryptographic protocols

  • Authenticate and authorize

  • Establish robust logging and secure error handling mechanisms

  • Conduct thorough security testing

  • Add security as part of code reviews

Follow secure coding standards

These standards serve as fundamental guides for effectively integrating secure coding techniques into existing development workflows. They provide a shared baseline for secure programming across software projects.

OWASP Developer Guide

The OWASP developer guide is a reference for programmers to help them navigate and craft secure source code. The guide outlines technology-agnostic secure coding practices, with key code security points highlighted in checklists migrated from the archived OWASP Secure Coding Practices Quick Reference Guide.

OWASP also supplies a series of cheat sheets for implementing secure coding principles and combating a broad array of code vulnerabilities.

SEI CERT Coding Standards

Created by Carnegie Mellon University’s Software Engineering Institute, the SEI CERT Coding Standards offer guidance for secure programming in the Android, C, C++, Java and Perl programming languages. The standards contain rules, recommendations and examples of compliant and noncompliant code. Rules and recommendations have corresponding risk assessments categorized according to severity, likelihood and remediation cost to help software engineering teams prioritize their efforts.

NIST Secure Software Development Framework

Alongside its Cybersecurity Framework for information security and cybersecurity risk management, the National Institute of Standards and Technology (NIST) has also published its Secure Software Development Framework. The framework consists of high-level, outcome-based secure software development practices, making it an ideal complement to OWASP and SEI CERT’s more technical standards.

Incorporate security into design

Building secure design into a system’s blueprint aligns with the “shift left” approach of moving security earlier in the software development process. It considers ways to make software secure even before the first line of code is written.

 

Comprehensive risk assessments and threat modeling can help surface potential security vulnerabilities in the software architecture. The secure design stage must also bring in security teams for hands-on collaboration and guidance on security requirements and how to handle them at the source code level.

For more information on integrating security into design, teams can look to OWASP’s cheat sheets on secure product design and threat modeling and its Secure by Design Framework.

Validate and sanitize inputs and encode outputs

A core secure coding principle is to never trust any input, as demonstrated by injection attacks. Server-side validation and sanitization help make sure inputs present no security risks before they’re processed.

Software engineering teams can place all validation and sanitization logic in a secure central file or location to maintain consistency and allow for quick and easy access and updates. They can also employ the validation and sanitization modules built into programming languages and frameworks, but these must be updated regularly to address newly discovered vulnerabilities.

Validating inputs

Input validation checks that the data type, format, length, range, size and other constraints are correct. This might involve matching inputs to approved patterns or comparing them against an allowed set of characters or values.

Sanitizing inputs

Sanitizing inputs entails cleaning and converting them into a safe form. It must be tailored to a programming language or framework.

In HTML, for instance, escaping special characters like &, <, >, “ and ‘ can help prevent XSS. Libraries like DOMPurify can assist with HTML sanitization.

For databases, coupling parameterized queries with prepared statements can help prevent SQL injection attacks since inputs are treated as data rather than SQL code that can be inadvertently run. Parameterized queries first define all SQL code, with placeholders for inputs or parameters, then pass each parameter to the query later. Prepared statements are precompiled SQL statements, which means injected SQL commands can’t change the intent of a query or how it’s run.

Encoding outputs

Output encoding allows data to be displayed safely as text so it won’t be interpreted as code. Many frameworks come with default output encoding protection or automatic encoding and escaping functions. The OWASP Java Encoder supports contextual output encoding for different contexts, such as placing variables into a URL, inline CSS or inline JavaScript, and inserting variables into an HTML attribute value, CSS property or between two HTML tags.

Implement strong cryptographic protocols

When applied correctly, cryptography safeguards the confidentiality, integrity and availability of information.

Algorithms

Programmers must use current and strong algorithms when encrypting data in transit and at rest. AES is considered the gold standard for symmetric encryption, with authenticated modes and a 256-bit key providing a high level of security. For asymmetric encryption, ECC with a secure curve or RSA with random padding enabled and at least a 2048-bit key offers robust security.

To protect passwords, hashing algorithms must be applied and a salt—a distinct, randomly generated string—added to the password as part of the hashing process. A hashing algorithm is a one-way mathematical function that converts data into a unique, shorter and fixed-length value, which can’t be decoded or reversed. Modern hashing algorithms include Argon2id and scrypt.

Instead of creating their own, developers must adopt reliable, supported and maintained implementations of cryptographic libraries such as Bouncy Castle, Libsodium, OpenSSL and Tink.

Keys and key management

Keys must not be hardcoded into source code, checked into version control systems, stored in environment variables or exposed in logs. Key management solutions and technologies can help automate the key management lifecycle—from generation, distribution and storage to usage, rotation, revocation and destruction.

Transport layer protection

When it comes to transport layer protection, software engineering teams must use protocols like Hypertext Transfer Protocol Secure (HTTPS) or HTTP Strict Transport Security (HSTS) and the latest version of TLS. Caching of sensitive data must be disabled, and unnecessary storage of sensitive data must be avoided.

Authenticate and authorize

Authentication and authorization are crucial secure coding practices to verify an entity’s identity and make sure that entity has the right level of access.

Authentication

Multifactor authentication (MFA) is one of the best defenses against password-related attacks. Other mechanisms include login throttling to prevent hackers from guessing passwords too many times and account lockout to stop login attempts for a certain period of time after a number of failed logins.

For passwordless authentication, developers can consider protocols such as OpenID Connect (OIDC) and Security Assertion Markup Language (SAML). The FIDO and FIDO2 open standards facilitate passwordless authentication through passkeys and can be used for authenticating applications, online services and websites.

Session management

Once an authenticated session has been established, it must be maintained through secure session IDs or tokens. Session IDs must be generated using a strong cryptographically secure pseudorandom number generator. As with any other user input, session IDs or tokens must be validated before processing, with invalid values filtered out.

Setting expiration timeouts for each session limits the duration in which malicious actors can hijack active sessions and launch attacks. Software engineering teams can use built-in session management functionalities provided by web development frameworks.

Authorization

Programmers can employ authorization protocols like OAuth, which works in tandem with the OIDC authentication protocol. In terms of access control, role-based access control (RBAC) is a popular model, with users granted access based on their predefined role. Other options that can be more robust and support more fine-grained permissions involve attribute-based access control (ABAC) and relationship-based access control (ReBAC). ABAC analyzes the attributes of actions, objects and users—such as a user’s name, a resource’s type and the time of day—to determine whether access will be granted. ReBAC grants access based on the relationships between resources.

 

Even with protocols and access control models in place, permissions must still be validated on every request and access control checks carried out for each object an entity tries to access. Denying access by default and applying the least privilege are also essential secure coding principles when it comes to authorization.

Establish robust logging and secure error handling mechanisms

Logs and error messages can be rich sources of information to assist malicious actors in devising attacks. This means both logs and errors must be handled with care.

Logging

Application errors, system events related to configuration changes and admin or privileged actions, and failure events in the areas of authentication, authorization, input validation and session management must all be logged since these can signify breach attempts. Sufficient information must be included, such as user details (identity, roles and permissions) and the context of the error or event (target, action and outcome), to aid in analysis and debugging.

Logs must be written to read-only media and stored in a secure location with restricted access and built-in tamper detection. If logs need to be sent to other systems, a secure transmission protocol must be employed.

Sensitive data must not be logged and must be scrubbed or deleted from logs. Any other information deemed critical, such as database connection strings, file paths, internal network names and addresses and session IDs or tokens must be encrypted, hashed or masked.

Logging libraries must be periodically updated to make sure security weaknesses are patched, as demonstrated by the Log4Shell vulnerability that impacts the widely deployed open-source Log4j logging library and allows hackers to run almost any code they want on affected systems.

Error handling

Error handling goes hand in hand with logging since information about errors typically appears in logs. And unhandled errors can serve as a port of entry for threat actors.

Developers can consider creating a global error handler that returns a generic response or error code for unexpected errors then logs more details about the error on the server side. This avoids leaking information to hackers while dealing with errors securely and supplying the necessary findings for programmers to investigate further.

Conduct thorough security testing

All security measures embedded into source code must be verified. QA and development teams can refer to OWASP’s Web Security Testing Guide and Application Security Verification Standard as a basis for testing code security. Automated tools can also assist with the process.

Static application security testing (SAST)

Static application security testing (SAST) applies predefined rules to pinpoint patterns in code that indicate likely vulnerabilities. SAST is sometimes called “white box” testing, while SAST tools are also known as static code analyzers because they scan code without needing to run the application.

SAST tools excel at flagging common code vulnerabilities and can determine the exact line number and file of the vulnerabilities they find. They also seamlessly integrate with most IDEs and CI/CD environments. However, they’re prone to producing false positives.

Dynamic application security testing (DAST)

Dynamic application security testing (DAST) takes an outside-in approach, evaluating applications in their runtime environments using simulated attacks to mimic the actions of real-world threat actors. As such, DAST is often referred to as black box testing because testers don’t need to know about or access the inner workings or source code of a system. DAST typically yields lower false positives than SAST.

Coupling SAST and DAST can uncover a fuller picture of potential vulnerabilities. For even more comprehensive security testing, SAST and DAST can be combined with other methods, such as interactive application security testing (IAST) that assesses both code context and runtime behavior to report vulnerabilities in real time and software composition analysis (SCA) that analyzes software to make sure its components are secure and up-to-date.

Add security as part of code reviews

Most code reviews focus on quality, examining the code for adherence to style guidelines, logical issues, optimal flow and test and edge case coverage. But security must also be part of the code review process.

Secure code reviews function as the next line of defense behind static code analyzers. Human code reviewers offer domain expertise, judgment and insight into code security vulnerabilities that automated tools often miss.

For a more structured approach, code reviewers can consult OWASP’s secure code review cheat sheet.

AI Academy

The rise of generative AI for business

Learn about the historical rise of generative AI and what it means for business.

Authors

Rina Diane Caballar

Staff Writer

IBM Think

Cole Stryker

Staff Editor, AI Models

IBM Think

Related solutions
IBM Bob

Accelerate software delivery with Bob, your AI partner for secure, intent-aware development.

Explore IBM Bob
AI coding solutions

Optimize software development efforts with trusted AI-driven tools that minimize time spent on writing code, debugging, code refactoring or code completion and make more room for innovation.

Explore AI coding solutions
AI consulting and services

Reinvent critical workflows and operations by adding AI to maximize experiences, real-time decision-making and business value.

Explore AI consulting services
Take the next step

Harness generative AI and advanced automation to create enterprise-ready code faster. Bob models to augment developer skill sets, simplifying and automating your development and modernization efforts.

  1. Discover IBM Bob
  2. Explore AI coding solutions