02 September 2026

Application Security Checklist: 10 Essential Controls

Reza Khosravi
No items found.

Table of Contents

Application Security Checklist: 10 Essential Controls

Most application security checklists start in the wrong place. They begin with a late-stage scan, collect findings, and treat a green dashboard as evidence that the application is safe. A checklist is more useful when it governs design intent, implementation choices, and delivery decisions before a scanner ever runs.

This application security checklist follows that order. It moves across application boundaries, code, dependencies, data, APIs, and deployment, with each control tied to a threat-model decision, an implementation check, and an enforcement point in the software delivery workflow. The practical question isn't only whether a control exists. It's whether the team can prove that the control still matches the system after tickets change, dependencies move, and new code reaches a pull request.

Modern application security needs that discipline. One industry source reports that roughly 25% of breaches involve applications, 95% of organizations have experienced API security issues in production, and 61% of applications contain a high-severity issue outside the OWASP Top 10. The same source reports that about 60% of breaches in 2025 involved known, unpatched flaws, while another source records 48,185 CVEs published in 2025 and an average closure time of 54.81 days for high and critical application vulnerabilities. (OpenText State of Application Security report)

1. Input Validation and Output Encoding

Treat every external value as untrusted at the application boundary. That includes form fields, query parameters, headers, uploaded files, webhook payloads, messages from queues, and data returned by another service. Validation should define the accepted type, length, format, and range, preferably through an allowlist that reflects the business rule rather than a blacklist of known bad strings.

Output encoding solves a different problem. A value can be valid as data and still become dangerous when inserted into HTML, JavaScript, CSS, a URL, or a document template. Use context-specific encoders and parameterized queries. A shared validation library is safer than asking every developer to reproduce subtle rules inside individual controllers.

Enforce the boundary before merge

Threat modeling should identify each input and output boundary before implementation begins. A design review can record that a search parameter accepts a constrained string, that an uploaded file requires content and size checks, or that a database interaction must use prepared statements. Policy-as-Code can then verify whether the expected control appears in the relevant repository or pull request.

Test more than ordinary malicious payloads. Include null bytes, Unicode normalization issues, mixed encodings, unexpected content types, empty values, and values at the edge of accepted ranges. Surface failures through IDE feedback and pull-request comments, not only through a test report that arrives after the developer has moved on.

Practical rule: Validation should express business intent. Encoding should reflect the output context. Neither should depend on a developer remembering a security trick during a rushed release.

For implementation guidance on browser injection risks, use this XSS attacks examples guide. DevArmor can preserve the threat-model rationale behind each validation rule and check implementation changes against that decision as the application evolves.

A hand-drawn illustration depicting a whitelist filter processing data inputs to allow only safe and valid content.

2. Authentication and Session Management

Authentication establishes who is making a request. Session management determines how long that identity remains trusted and how the application responds when the session is stolen, reused, or terminated. Weaknesses in either area can turn a valid login into an unauthorized path to sensitive data.

Make password storage non-reversible with a modern password-hashing function such as Argon2 or bcrypt, and choose work factors according to the threat model and operating environment. Require MFA where an account can reach sensitive data, privileged functions, production systems, or administrative tooling. Don't bolt MFA on after the architecture is settled. Record the identity boundary and assurance requirement during design.

Protect the full session lifecycle

Use secure, httpOnly, SameSite=Strict cookies for browser sessions where that model fits. For stateless APIs, design token rotation, audience validation, expiration, and revocation behavior explicitly. Session timeouts should reflect the operation's sensitivity. A healthcare record or financial transfer deserves a shorter idle period and stronger step-up verification than a low-risk preference update.

Protect every state-changing browser request against CSRF with a synchronizer token or double-submit pattern. Test for session fixation, token reuse, JWT algorithm confusion, parameter tampering, and direct access to authenticated routes without the expected session state. Account protection should slow repeated guesses without creating an easy denial-of-service path for legitimate users.

The application security architecture guide can help connect authentication decisions to broader trust boundaries. In DevArmor, the useful enforcement point is the pull request. A change to login, token handling, or role assignment should trigger the approved design requirements and produce a traceable review outcome.

A pencil sketch illustration showing the relationship between secure user authentication methods and session management practices.

3. Authorization and Access Control

A successful login doesn't grant permission to every object or operation. Authorization must answer three separate questions for each request: who is acting, what resource is involved, and which action is allowed under the current context.

Start by classifying resources as public, internal, confidential, or restricted. Then map each class to permitted actions, roles, attributes, and service identities in the threat model. RBAC works well for stable organizational roles. ABAC is more appropriate when access depends on department, ownership, tenant, device posture, location, patient relationship, or another changing attribute. Many systems need both.

Put authorization where the decision matters

Don't rely on a single check at the user interface. Enforce authorization at the API boundary, in business logic, and in database queries. A hidden button isn't an access control. A route-level role check may also be insufficient if an attacker can change an object identifier and retrieve another user's record.

Centralized policy engines such as OPA with Rego can reduce inconsistent controller logic, but centralization introduces its own operational trade-off. A policy service must be available, versioned, tested, and observable. Teams should test every role against every sensitive resource, including cross-tenant access, privilege escalation, and denied operations.

Use temporary elevation for administrative work rather than permanent broad privileges. Log the subject, resource, decision, timestamp, and relevant context for important authorization decisions, particularly denials and elevation events. Automate access reviews so role changes don't leave permissions behind.

DevArmor can tie these checks to the design decision that established the authorization boundary. When a ticket adds a new tenant, resource, or service relationship, the living model can prompt a review before code expands access.

4. Secure Coding Practices and Code Review

Secure coding is where design requirements become habits in actual code. The most useful standard is specific to the language and framework. It names dangerous APIs, approved alternatives, error-handling rules, serialization constraints, secret-management requirements, and the conditions that require a security-focused reviewer.

Static analysis belongs in the developer workflow, but it shouldn't become an automatic veto on every warning. A build that fails on irrelevant findings trains developers to bypass the tool. A better policy blocks issues that are severe, credible, and relevant to the application's threat model, while routing lower-confidence findings for review and tuning.

Make sensitive changes visible

Require an additional approver for changes involving authentication, cryptography, database access, authorization, or sensitive data. Security champions can distribute that knowledge across teams, but rotating the responsibility matters. Otherwise, one specialist becomes a bottleneck and the rest of the organization never learns how to review security-sensitive logic.

Use IDE integrations to flag unsafe patterns while developers are writing code. Pull-request rules should check for hardcoded secrets, insecure cryptographic calls, dangerous deserialization, unsafe error responses, and missing tests for critical business rules. CodeQL, Semgrep, SonarQube, and similar tools can contribute useful signals, but none replaces review of business logic.

The review record should explain why a warning was accepted, fixed, or deferred. OWASP SAMM recommends combining effort metrics, such as training hours, code-review time, and applications scanned, with result metrics, including outstanding defects and application-vulnerability incidents. (OWASP SAMM measurement guidance) That turns a checklist from a completion exercise into an operational feedback system.

5. Cryptography and Key Management

Cryptography fails most often through poor selection, misuse, or key handling, not because a team lacks access to an algorithm. Don't implement cryptographic primitives yourself. Use maintained libraries such as libsodium, Bouncy Castle, or a language-native cryptography package, and make the approved algorithms part of the platform standard.

Threat modeling should identify what needs confidentiality, integrity, authenticity, or non-repudiation. Sensitive data at rest commonly needs authenticated encryption, such as AES-GCM or ChaCha20-Poly1305. Data in transit should use modern TLS configurations, with older protocol versions and weak ciphers disabled. Signing keys, encryption keys, backup keys, and service-authentication keys should have separate purposes and access policies.

Design key operations before storing data

Envelope encryption is a practical pattern. A data-encryption key protects the record, while a key-encryption key in a dedicated vault protects the data key. This limits exposure and supports controlled rotation. Key rotation needs versioning, because old records may need to remain decryptable under a documented retention policy.

Never place keys in source code, configuration committed to a repository, container images, or build logs. Retrieve them at runtime through a secrets or key-management service, and restrict which workload identity can use each key. Test failure paths, including unavailable key services, expired certificates, incorrect key versions, and attempted access from an unauthorized workload.

A policy check can look for forbidden algorithms, insecure TLS settings, hardcoded secrets, and unapproved key sources. The trade-off is that strict cryptographic policy can complicate interoperability with older partners. Record an exception with an owner, expiration condition, compensating control, and review date rather than allowing a temporary workaround to become permanent architecture.

6. Dependency and Supply Chain Security

A vulnerable dependency is part of your application whether your team wrote it or not. A compromised package can be worse because it may behave normally during review while introducing malicious behavior through a transitive dependency, install script, update, or build process.

Maintain an inventory of direct and transitive packages, generate a machine-readable SBOM for every release, and scan dependencies in pull requests and build pipelines. Formats such as SPDX and CycloneDX make the inventory easier to exchange with other systems. Package integrity checks, private registries, lockfiles, signed releases, and controlled build environments reduce the chance of dependency confusion or unauthorized substitution.

Separate exposure from exploitability

A scanner finding isn't automatically a production emergency. Determine whether the vulnerable code is reachable, whether the affected feature is enabled, whether the application is exposed, and whether compensating controls exist. Document that reasoning as an exception instead of deleting or ignoring the finding.

Patch policy also needs ownership. A team should know who reviews an advisory, who tests the update, who approves an exception, and who verifies deployment. Automated update pull requests can reduce maintenance work, but major version changes still require compatibility and behavior review even when no CVE is listed.

Use software composition analysis guidance to connect package inventory with remediation decisions. DevArmor can add the missing context by linking a dependency change to the service's threat model, approved policy, and merge decision, rather than treating the package scanner as an isolated alert source.

A diagram illustrating application security with SBOM tracking, dependency management, and automated vulnerability scanning process flows.

7. API Security and Rate Limiting

APIs expose the application's business logic directly, often to browsers, mobile clients, partners, internal services, and automation. Each endpoint needs an explicit authentication requirement, authorization rule, input schema, response shape, and abuse-control decision.

Threat-model the API inventory by trust level and business impact. A public search endpoint may tolerate anonymous access with strict quotas. A payment, administrative, or bulk-export endpoint needs stronger identity assurance, narrower scopes, more restrictive limits, and better monitoring. OAuth scopes, signed requests, short-lived credentials, and secure key rotation should reflect those differences.

Control both requests and resource use

Rate limiting belongs at multiple layers. The gateway can absorb obvious abuse, the service can apply business-aware limits, and the database can protect expensive operations. Use different limits for anonymous users, authenticated users, trusted partners, and privileged operations. Return 429 with Retry-After where appropriate, and make clients use exponential backoff rather than retrying aggressively.

Limit response size and require bounded pagination. Cursor-based pagination usually gives the server better control over large or changing result sets than unrestricted offsets. Enforce HTTPS, reject unexpected methods and content types, validate signatures where sensitive integrations require them, and retire obsolete API versions through a documented migration process.

A developer survey covering 14 companies and 5 mailing lists found that only 57% of respondents said their teams had the right application-security tools for SDLC integration. Among tool users, 33% scanned daily, 29% weekly, and 20% monthly, while 43% prioritized release deadlines over security. (DevOps survey on DevSecOps progress) Those findings support putting API controls in gateways, pull requests, and service templates instead of assigning them to a separate review at the end.

8. Data Protection and Sensitive Data Handling

You can't protect data consistently until you know where it is, why the application stores it, who can use it, and how long it should remain. Build a data-flow inventory during design, classify entities by sensitivity, and document movement between clients, services, queues, databases, analytics systems, logs, backups, and third-party providers.

Classification should drive controls. The most sensitive fields may require field-level encryption, tokenization, restricted decryption rights, and separate audit events. Less sensitive data may need access control and retention limits without the operational cost of encrypting every field. That distinction prevents teams from spending effort uniformly while missing the data that creates the greatest consequence.

Keep sensitive values out of secondary systems

Logging is a frequent leak path. Redact payment data, health information, credentials, session tokens, and personal identifiers before values reach application logs or tracing platforms. Test redaction against real log formats, because a rule that handles one serialization path may fail when the same object appears in an exception, nested payload, or debugging statement.

Plan searchable workflows before encrypting fields. Tokenization, protected indexes, proxy services, or carefully controlled decryption can support necessary analytics without giving every query process access to plaintext. Define retention, archival, deletion, and residency requirements in architecture decisions, then automate them through storage policies and scheduled jobs.

For related secure technical controls for data, use the implementation point that fits your system, whether that's a database policy, service library, logging pipeline, or deployment check. DevArmor can preserve the data-flow assumptions and flag changes that introduce a new store, integration, or processing purpose.

9. Logging, Monitoring, and Incident Response

Logging shouldn't mean recording everything. It means capturing the security context needed to detect abuse, investigate decisions, and recover from an incident without exposing more sensitive data in the process.

Define required events during threat modeling. Authentication failures, successful MFA changes, privilege elevation, authorization denials, administrative actions, key use, sensitive exports, configuration changes, and suspicious API behavior often deserve structured events. Each event should provide enough context to connect the actor, resource, action, result, and time without storing raw credentials or protected data.

Turn events into response

Centralize important logs in a system with strict access control and tamper-evident or immutable retention. Cloud services such as AWS CloudTrail, Azure Monitor, and Google Cloud Audit Logs can provide platform-level events, but application teams still need business-context events that infrastructure logs can't infer.

Alerts require tuning. An alert without an owner, severity, investigation path, and response action becomes background noise. Create runbooks for credential compromise, data exposure, ransomware, suspicious privilege escalation, and supply-chain incidents. Exercise those runbooks through tabletop sessions and update them when architecture or team ownership changes.

A six-step infographic illustrating a comprehensive process for protecting and handling sensitive organizational data.

The incident response planning guide provides a useful reference for connecting detection to containment and recovery. DevArmor can make logging requirements part of the design review and verify, at pull request or deployment time, that a new sensitive operation has an associated observability decision.

10. Configuration and Infrastructure Security

Secure application code can still fail in an exposed bucket, permissive identity, public database, unprotected build runner, or unrestricted container network. Infrastructure configuration belongs in the application security checklist because deployment choices define the environment in which application controls operate.

Treat Terraform, Kubernetes manifests, cloud policies, pipeline definitions, and service templates as production code. Review them, test them, scan them, and protect their change history. Secure templates should deny public access by default, require managed secrets, use least-privilege workload identities, and make exceptions explicit.

Prevent drift, not just bad commits

Infrastructure-as-Code checks catch unsafe changes before deployment, but they don't catch every manual modification or provider-side change. Use posture management and configuration monitoring to compare the running environment with the approved baseline. Kubernetes RBAC should work with network policies, namespace boundaries, and workload identity rather than serving as the only barrier between services.

Segment high-sensitivity workloads and limit lateral movement between services. Automate secret provisioning and key rotation through vault services. Make break-glass access temporary, logged, and reviewed. For every exception, record the business reason, compensating control, owner, and removal condition.

The software testing and QA services reference can complement application-focused verification, but infrastructure policy must remain close to the deployment pipeline. DevArmor can connect the infrastructure change to the threat model and enforce Policy-as-Code on the pull request before configuration drift becomes an incident.

Application Security: 10-Point Checklist Comparison

ControlImplementation Complexity 🔄Resource Requirements ⚡Expected Outcomes ⭐📊Ideal Use Cases 📊Key Advantages & Tip ⭐💡
Input Validation and Output EncodingMedium–High, multiple entry points, context-aware encoding requiredLow–Medium, libraries and centralized routines⭐⭐⭐⭐, major reduction in injection risks; measurable OWASP risk drop 📊Web apps, APIs, any user-supplied input surfacePrevents XSS/SQLi; low perf overhead; 💡 define rules in threat model and reuse libraries
Authentication and Session ManagementHigh, secure token/MFA flows and distributed sessionsHigh, MFA, token stores, secure cookie config⭐⭐⭐⭐⭐, strong protection against account takeover and hijacking 📊User-facing systems, admin consoles, sensitive account accessBlocks unauthorized access; MFA reduces risk; 💡 use Argon2/bcrypt, httpOnly cookies, design MFA early
Authorization and Access Control (RBAC/ABAC)High, policy modeling and enforcement across layersMedium–High, policy engines, audit logging⭐⭐⭐⭐, enforces least privilege; reduces blast radius 📊Multi-role apps, microservices, data-sensitive resourcesCentralized policies and audits; 💡 use OPA-like engines and time-limited elevation
Secure Coding Practices and Code ReviewMedium, tool integration and reviewer trainingMedium, SAST, IDE plugins, reviewer time⭐⭐⭐⭐, catches many issues early; lowers remediation cost 📊Development workflows, PR reviews, librariesShifts left security; consistent standards; 💡 integrate SAST into CI and require security reviewers for sensitive changes
Cryptography and Key ManagementHigh, careful algorithm and key lifecycle designHigh, KMS/HSM, rotation automation, audit⭐⭐⭐⭐, strong confidentiality and integrity when correct; high impact 📊Data-at-rest/transit, signing, high-assurance systemsHardware-backed keys and rotation; 💡 use vetted libs and KMS, never roll your own crypto
Dependency and Supply Chain SecurityMedium–High, SBOMs, scanning, integrity checksMedium, scanners, private registries, SBOM tooling⭐⭐⭐⭐, prevents known-vulnerability and supply-chain risks 📊Projects with many third-party deps, OSS-heavy stacksSBOM + automated updates; 💡 fail CI on critical CVEs and verify package signatures
API Security and Rate LimitingMedium, gateway policies and throttling strategiesMedium, API gateway, auth servers, telemetry⭐⭐⭐⭐, prevents abuse, enumeration, DoS; improves resiliency 📊Public APIs, mobile/web backends, partner integrationsThrottling + OAuth scopes; 💡 apply layered rate limits and expose rate headers
Data Protection and Sensitive Data HandlingHigh, classification, field encryption, redactionHigh, encryption, key mgmt, specialized tooling⭐⭐⭐⭐⭐, essential for PII/PHI compliance and breach prevention 📊Healthcare, finance, GDPR/PCI-regulated systemsField-level encryption and redaction; 💡 classify data and use envelope encryption
Logging, Monitoring, and Incident ResponseMedium, logging design, SIEM integration, playbooksMedium–High, SIEM/SOAR, storage, SOC staffing⭐⭐⭐⭐, faster detection and forensic capability 📊Production systems, critical infra, compliance environmentsCentralized, tamper-evident logs; 💡 log context (no sensitive plaintext) and run tabletop exercises
Configuration and Infrastructure SecurityMedium–High, IaC policies, segmentation, drift controlMedium–High, IaC tooling, scanners, automation⭐⭐⭐⭐, reduces misconfiguration-driven breaches 📊Cloud infra, multi-cloud, containerized platformsImmutable infra and policy-as-code; 💡 treat IaC like app code and enforce secure defaults in pipelines

Turn the Checklist Into a Living Control System

A static document can remind a team what good practice looks like. It can't tell the team whether a new service, dependency, API, data flow, or deployment still matches the approved security design. That distinction matters because the OWASP Web Application Penetration Checklist first appeared in July 2004 as version 1.1 and later evolved into the OWASP Web Security Testing Guide, with published versions in December 2004, December 2006, September 2008, and September 2014. (OWASP testing guide history) The history shows that application testing practices mature as software changes. Your checklist needs the same capacity to change.

Start during design. Identify trust boundaries, data stores, identities, external integrations, abuse cases, and recovery assumptions. Assign an owner to each decision and connect it to an implementation requirement. Input validation, authorization, encryption, logging, and rate limiting should appear as design constraints where they become relevant, not as a generic list attached to a release ticket.

Verify implementation during coding and review. Use shared libraries, secure defaults, IDE feedback, targeted static analysis, dependency inventories, and pull-request policies. The review should answer whether the change implements the approved control, whether the threat model changed, and whether the developer documented an exception. A scanner can identify a suspicious pattern, but a design-linked review explains why that pattern matters in this application.

Enforce deployment and runtime controls continuously. Configuration policies should block unsafe infrastructure changes, release checks should verify required artifacts, and monitoring should confirm that important security events remain visible. Track operational measures such as scan coverage, outstanding defects, remediation throughput, and security incidents. OWASP SAMM's distinction between effort and result metrics helps teams avoid celebrating checklist completion while unresolved risk remains. (OWASP SAMM measurement guidance)

Prioritization is where many checklists become unrealistic. A team with limited capacity shouldn't treat every control as equally urgent. Start with the controls that protect the application's highest-impact boundaries, such as privileged authentication, object-level authorization, secrets, critical data, exposed APIs, and deployment identities. Then consider exploitability, exposure, business consequence, compliance obligations, and the cost of enforcement. A low-effort control can deserve early attention, but it shouldn't displace an architecture decision that protects a sensitive tenant boundary.

Keep exceptions visible and temporary. Each exception needs a rationale, risk owner, compensating control, review date, and closure condition. Without those fields, a checklist becomes a collection of permanent waivers.

DevArmor is relevant when teams need the checklist to retain its context across planning, design, coding, and deployment. Its continuous threat modeling can use tickets, design documents, repositories, and service metadata. Security design reviews can surface in tools such as Jira, Google Docs, GitHub, VS Code, Cursor, and MCP, while Policy-as-Code can enforce approved requirements on pull requests. Implementation verification then ties design decisions to code changes and deployments, helping teams detect drift instead of rediscovering the application's security assumptions during an audit or incident.


DevArmor connects continuous threat modeling, security design reviews, Policy-as-Code, and implementation verification to the workflows your developers already use. Visit DevArmor to see how a living application security context can turn this checklist into traceable controls across design, code review, and deployment.

Table of Contents

Subscribe