Join our Newsletter — 33% off our NHI Course
Home› Glossary› AI Security› Defensive Programming
AI Security

Defensive Programming

← Back to Glossary
By NHI Mgmt Group Updated October 30, 2026 Domain: AI Security

Code practices that assume inputs, states, and dependencies may be hostile or malformed. In this context, it includes validation, sanitisation, and authorisation checks that AI-generated code may omit unless the prompt or review process explicitly requires them.

What Defensive Programming Looks Like in Practice

Defensive programming treats code as if its inputs, runtime state, and dependencies may be wrong, hostile, or incomplete. The goal is to make failure predictable rather than catastrophic, so checks happen early and assumptions are made explicit. This is especially important in code generated or assisted by AI, which may omit validation, sanitisation, or authorisation unless those requirements are stated clearly.

That mindset changes how engineers write ordinary control flow. Instead of trusting a caller, file, API response, or library state, the code verifies preconditions, constrains acceptable values, and fails safely when reality diverges from expectation. The result is software that is harder to misuse, easier to reason about, and less likely to turn a small defect into a security issue.

Why It Matters for Secure Software

Defensive programming reduces the attack surface created by unchecked assumptions. Input validation limits malformed data, sanitisation reduces injection and parsing abuse, and authorisation checks prevent code paths from being exercised by the wrong actor or component. These controls matter because many application failures begin as simple trust mistakes rather than exotic exploits.

It also helps with dependency risk. External services, APIs, parsers, and configuration sources can all return unexpected values or partial failures, so robust code should handle absent fields, timeout conditions, unexpected types, and invalid state transitions without leaking secrets or making unsafe decisions. Defensive code is not just about rejecting bad data, it is about keeping the system in a known-safe state when assumptions break.

Common Failure Modes

The most common failure mode is assuming that upstream validation has already happened. In layered systems, that assumption often breaks at integration boundaries, especially where one service consumes another service’s output, where a UI check is not repeated server-side, or where generated code introduces a new path that bypasses existing guardrails.

Another frequent problem is incomplete defensive logic. Developers may validate format but not meaning, encode output but not normalise input, or check presence without checking privilege. Those gaps can lead to injection, insecure deserialisation, logic abuse, information disclosure, or authorisation bypass even when the code appears superficially careful.

Where It Fits in the SDLC

Defensive programming belongs in design, implementation, review, and testing. The design stage should identify trust boundaries and explicit preconditions. Implementation should make those preconditions visible in code. Review should look for missing checks, unsafe defaults, and hidden assumptions. Testing should include malformed inputs, boundary values, dependency failures, and negative cases, not just happy-path behaviour.

For teams using AI-assisted development, the discipline becomes even more important because a model may generate syntactically correct code that is semantically too trusting. Clear prompts, secure coding standards, and review criteria help ensure that validation and access checks are preserved instead of being omitted for brevity or convenience. NHIMG’s Secure Coding Guide is a useful reference for the related practices of validation, secure error handling, and authorisation-aware code review.

Practical Design Patterns

Well-defended code usually prefers explicit allow-lists, strict type and range checking, safe defaults, and fail-closed behaviour for security decisions. It also separates data handling from policy decisions so that parsing or formatting errors do not silently become access decisions. In security-sensitive paths, the code should be clear about what is being trusted, what is being verified, and what happens when verification fails.

That same discipline supports maintainability. Code that states its assumptions clearly is easier to test, easier to audit, and less likely to accumulate fragile edge-case handling over time. Defensive programming is therefore both a security practice and a reliability practice, because the same habits that prevent exploitation also prevent avoidable production failures.

Standards & Framework Alignment

This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.

OWASP ASVS, CIS Controls v8 and NIST SP 800-53 Rev 5 set the governance and control requirements practitioners need to meet.

FrameworkControl / ReferenceRelevance
OWASP ASVSV2 — Validation and Business LogicDefensive programming is built around validating inputs and business rules.
V8 — AuthorizationThe term explicitly includes authorisation checks that prevent unsafe code paths.
V16 — Security Logging and Error HandlingDefensive code must fail safely and expose meaningful errors without leaking sensitive details.
Recommendation — Use V2 to require strict validation and business-logic checks on all untrusted inputs. Use V8 to verify every sensitive action is authorised before execution. Use V16 to log security-relevant failures and handle errors without exposing secrets.
CIS Controls v8CIS-16 — Application Software SecurityDefensive programming is a core application security practice for building safer code.
Recommendation — Apply CIS-16 to embed secure coding, review, and testing into application development.
NIST SP 800-53 Rev 5SI-10 — Information Input ValidationThe subject centres on validating hostile or malformed inputs before processing them.
AC-3 — Access EnforcementAuthorisation checks are a direct part of defensive programming for sensitive actions.
SI-7 — Software, Firmware, and Information IntegrityDefensive programming helps preserve code and runtime integrity against unsafe state changes.
Recommendation — Use SI-10 to validate inputs at trust boundaries before they affect logic or storage. Use AC-3 to enforce access decisions before privileged or sensitive operations run. Use SI-7 to protect integrity checks and reject unexpected changes in software behaviour.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Reviewed and updated by the NHIMG editorial team on October 30, 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org