Security Foundations and Mindset
Application security (AppSec) is the practice of reducing security risk throughout software design, implementation, testing, deployment, and maintenance.
1.1 What is programming security?
Application security (AppSec) is the practice of reducing security risk throughout software design, implementation, testing, deployment, and maintenance. Secure code is not simply code with no known bug; it is code designed to preserve explicit security properties even when inputs, users, dependencies, or environments are hostile.
Confidentiality: only authorized parties can read information.
Integrity: information and operations cannot be altered improperly.
Availability: authorized users can access the service when needed.
Authenticity: identities and messages can be verified.
Accountability: actions can be attributed to an identity or process through reliable evidence.
Non-repudiation: evidence can make denial of a specific action difficult in a defined legal/technical context; it is not automatically provided by ordinary logs.
Privacy: personal data is collected, used, shared, and retained appropriately.
Resilience: the system can withstand, contain, recover from, and learn from failures or attacks.
A system can satisfy one property and fail another. Encrypting a database may help confidentiality but does not stop an authorized application from exposing records to the wrong user.
1.2 Core security vocabulary
Customer records, signing keys, service uptime Potential cause of harm
A stolen account or malicious dependency Entity capable of causing harm Criminal, insider, compromised service
Places an attacker can interact with the system HTTP endpoints, file imports, plugins Weakness that can be exploited Missing authorization check
A method that takes advantage of a weakness A crafted request that accesses another user's record Combination of likelihood and impact Exposure of sensitive account data A measure that reduces risk Server-side object-level authorization Risk remaining after controls A low-probability risk still remains Risk assessment example
Suppose a report-download endpoint accepts a report ID. If it checks only whether the requester is logged in, one user may retrieve another user's report.
Asset: private reports.
Threat: unauthorized disclosure.
Vulnerability: missing ownership/permission check.
Impact: confidentiality and possibly regulatory harm.
Control: authorize every requested report against the current principal and tenant.
Verification: test both permitted and forbidden access cases.
1.3 Defense in depth
Do not rely on one control. Combine controls that fail independently.
Example for a document-upload feature:
Authenticate the user.
Authorize the upload operation.
Enforce size and count limits.
Validate allowed file types and inspect content.
Generate a server-side filename.
Store files outside the executable web root.
Scan where appropriate.
Serve downloads through an authorization-controlled handler.
Log relevant security events without logging file contents or secrets.
Monitor unusual volume and failure patterns.
Layers of the upload example Text equivalent: every request passes through several independent checks — identity, permission, limits, content validation, safe naming and private storage — and downloads go through their own authorization check. Each control can fail without the others failing with it, and the important decisions are logged.
Try it: model the threats of a small API The threat-model builder below lets you walk the data-flow diagram of a course-enrollment API, record threats with STRIDE, score them by likelihood × impact, and export threat records in the template used in Module 2.
flowchart TD
R[Upload request] --> A1[Authenticate]
A1 --> A2[Authorize the operation]
A2 --> A3[Size and count limits]
A3 --> A4[Type allowlist and content check]
A4 --> A5[Server-generated name]
A5 --> A6[(Private storage outside the web root)]
A6 --> A7[Authorized download handler]
A2 -.-> LOG[Security event log]
A4 -.-> LOG
A7 -.-> LOGthreatmodel1.4 Least privilege and secure defaults
Least privilege: grant only the minimum permissions needed for the task and duration.
Secure defaults: a new installation should be safe before optional hardening.
Fail securely: when a security decision cannot be made, do not silently grant access.
Complete mediation: check authorization for each protected operation, not just at login.
Minimize attack surface: disable unused ports, endpoints, features, and permissions.
Separation of duties: avoid giving one identity unchecked control over every critical action.
Economy of mechanism: prefer designs that can be understood and reviewed.
1.5 Security is a lifecycle activity
Security work includes requirements, architecture, coding, testing, release, monitoring, patching, and retirement. A vulnerability fixed in code can reappear through a configuration change, unsafe dependency update, or unreviewed release.
Knowledge check
Is a logged-in user automatically authorized to access every record? No. Authentication proves an identity; authorization decides what it may do.
Does encryption alone prevent SQL injection? No. SQL injection is addressed by safe query construction, usually parameterized queries, plus appropriate authorization and validation.
What is defense in depth? Multiple complementary controls rather than a single point of protection.
Practice
List five assets in a learning website, their security properties, one threat per asset, and one control.
Quiz
? A logged-in student opens `/reports/1042`, which belongs to another student, and the server returns it. Which control is missing?
- Authentication :: The student *is* authenticated; the server knows who is asking.
+ Object-level authorization :: The server never checked that this principal may read this report.
- Encryption at rest :: Encryption protects stored data from people without the key; the application itself decrypted and returned the report.
- Input validation :: `1042` is a perfectly valid identifier; validity is not permission.
? Which statements about defense in depth are accurate? (select all that apply)
+ Controls should be able to fail independently. :: If one bypass defeats every layer, the layers are not really separate.
- One strong control makes the others unnecessary. :: Any single control can be misconfigured, bypassed or removed in a later change.
+ Logging and monitoring are part of the layering. :: They detect failures of the preventive controls.
+ Server-side checks remain necessary even if the UI hides an action. :: Callers can send requests directly.
? Which pair is correctly matched?
- Risk — a weakness that can be exploited :: That is a vulnerabili
…