Forge University

Secure Coding Practices That Survive Contact With Attackers

Every architecture diagram and threat model eventually resolves into actual lines of code, and it is at that moment that most exploitable vulnerabilities are born. Secure coding practices are the discipline of writing code that behaves correctly even when handed hostile input, across input handling, error paths, session state, cryptography, access enforcement, and concurrency.

Input Validation and Output Encoding

Validate input at every trust boundary using allowlisting -- define exactly what a valid value looks like and reject anything else -- rather than denylisting, which tries to enumerate malicious patterns and always misses a new variant. Canonicalize data (decode URL-encoding, resolve path traversal, normalize Unicode) before validating it, or an attacker can smuggle a payload past the filter in an encoded form that only becomes dangerous after later decoding. On output, encoding must be context-aware: HTML, SQL, an OS shell command, and LDAP each treat different characters as special, and using the wrong scheme for the destination is itself a vulnerability.

Error Handling and Session Management

Fail closed: default to denying access rather than falling back to a permissive state. Show users a generic error while detailed diagnostics -- stack traces, paths, schema hints -- go only to internal logs, since verbose errors are reconnaissance for attackers. Sessions need long, random, cryptographically generated identifiers; HttpOnly, Secure, and SameSite cookie attributes; idle timeouts; and regeneration of the session ID at login or privilege change, which defeats session fixation.

Cryptography and Access Control in Code

Never invent custom cryptographic algorithms -- use vetted libraries and current standard algorithms, and never hardcode secrets in source code. Enforce access control on the server for every request; a hidden UI button is a usability nicety, not a boundary, since an attacker can call the API directly. Default to deny: access is granted only when a rule explicitly permits it.

Concurrency and Resource Management

Time-of-check-to-time-of-use (TOCTOU) race conditions occur when a security check and the actual resource use are separated by an exploitable window; proper locking and minimizing that window close the gap. Bound loops, close handles, and rate-limit endpoints so resource exhaustion cannot be used for denial-of-service.

Key Mechanics

  • Validate against an allowlist at every trust boundary; canonicalize before validating, never after.
  • Encode output for the specific sink context (HTML, SQL, shell, LDAP) -- one scheme does not fit all.
  • Enforce access control server-side on every request; treat client-side controls as UX only.
  • Use parameterized queries for any interpreter call, instead of string concatenation.
  • Regenerate session IDs on login and privilege change; set HttpOnly/Secure/SameSite on cookies.

Exam Tip: Validation only in browser JavaScript means server-side re-validation is missing -- client-side checks are convenience, never a control.

Exam Tip: Allowlist (permit known-good) beats denylist (block known-bad) because it fails closed against novel variants a denylist has never seen.

Exam Tip: TOCTOU questions describe a gap between a permission check and the actual resource action -- that gap is the vulnerability.

Diagram

Worked example: A developer builds a search feature that inserts a username parameter directly into a SQL WHERE clause, relying only on a client-side JavaScript regex for validation. A tester bypasses the browser and posts a crafted request directly to the API, injecting a UNION-based SQL payload. The fix needs two layers: server-side allowlist validation, and a parameterized query so input is always data, never executable SQL.

Knowledge check

Click an option to check yourself — this is a self-check, not graded or saved. The graded version pooling this module's questions is on the syllabus page.

1. A developer adds a JavaScript regex to a signup form that rejects usernames containing special characters, and considers the input validation requirement satisfied. During a later penetration test, an attacker submits a crafted POST request directly to the API endpoint, bypassing the browser entirely, and successfully injects a malicious payload. What is the most accurate assessment of the original implementation?

2. A file-processing utility checks that a user has permission to read a given file, and then, a short time later, opens and reads whatever file is currently at that path. A tester demonstrates that swapping the file at that path between the check and the read allows access to an unauthorized file. Which vulnerability class does this describe?

3. A team is reviewing session handling in their web application. Currently, a user's session identifier stays exactly the same before and after they log in, and the session cookie has no special attributes set. Which combination of changes best hardens this design against session-based attacks?

4. Why does an allowlist approach to input validation generally beat a denylist approach, according to the lesson?

5. Why must data be canonicalized before it is validated, rather than after?

6. Why must output encoding be context-aware (different for HTML, SQL, an OS shell command, or LDAP)?

7. What does "fail closed" mean in secure error handling?

8. Why should detailed diagnostic information like stack traces and schema hints be sent only to internal logs, not shown to end users?

9. What does the lesson say about writing custom cryptographic algorithms?

10. A web application hides an "admin delete user" button from the UI for non-admin users, but does not check the user's role when the corresponding API endpoint is called directly. What is wrong with this design?

11. What technique should be used for any interpreter call (such as a database query) built from untrusted input, instead of string concatenation?

12. What should be done to prevent resource exhaustion from being used for denial-of-service, according to the lesson?

Log in to chat with your AI Mentor about this lesson.