Chapter 27 Quiz: Security-First Development
Test your understanding of security-first development principles, techniques, and best practices for vibe coding.
Question 1
What is the primary reason AI-generated code requires extra security scrutiny?
A) AI models are trained to be intentionally malicious B) AI models learn from training data that includes insecure patterns, and they do not distinguish between teaching examples and production code C) AI cannot generate code that handles user input D) AI always uses deprecated libraries
Answer
**B)** AI models learn from training data that includes insecure patterns—tutorials that omit error handling, Stack Overflow answers with shortcuts, and legacy code with outdated practices. The model does not know your threat model or compliance requirements, so it may generate code that works correctly but is vulnerable.Question 2
Which input validation approach is preferred for security?
A) Blacklisting (deny-list) — reject known-bad patterns B) Whitelisting (allow-list) — accept only known-good patterns C) No validation — trust the client to send clean data D) Validation only on the client side
Answer
**B)** Whitelisting defines exactly what is acceptable and rejects everything else. Blacklists are inherently incomplete because attackers constantly discover new encodings and bypasses. Client-side validation alone is insufficient because it can be bypassed.Question 3
Which of the following correctly prevents SQL injection?
A) cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
B) cursor.execute("SELECT * FROM users WHERE id = " + str(user_id))
C) cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
D) cursor.execute("SELECT * FROM users WHERE id = '{}'".format(user_id))
Answer
**C)** This is a parameterized query where `%s` is a parameter marker handled by the database driver, not Python string formatting. The database receives the query structure and the parameter value separately, making injection impossible. Options A, B, and D all use string interpolation, which is vulnerable.Question 4
What is the purpose of the HttpOnly flag on a cookie?
A) It ensures the cookie is only sent over HTTP, not HTTPS B) It prevents JavaScript from reading the cookie's value C) It makes the cookie expire when the browser is closed D) It encrypts the cookie's contents
Answer
**B)** The `HttpOnly` flag instructs the browser to prevent JavaScript (including injected XSS scripts) from accessing the cookie through `document.cookie`. This protects session cookies from being stolen via XSS attacks. The cookie is still sent with HTTP requests normally.Question 5
Why is bcrypt preferred over SHA-256 for password hashing?
A) bcrypt produces shorter hashes that save storage space B) bcrypt is faster, allowing for better user experience C) bcrypt is deliberately slow and includes automatic salting, making brute-force attacks impractical D) bcrypt is newer and therefore more secure by default
Answer
**C)** bcrypt is designed to be computationally expensive, with a configurable work factor that increases hashing time. This makes brute-force attacks impractical—an attacker who can compute billions of SHA-256 hashes per second can compute only a few bcrypt hashes per second. bcrypt also automatically generates and stores a unique salt for each hash.Question 6
What is a Content Security Policy (CSP) header?
A) A server-side firewall rule that blocks malicious requests B) A browser-enforced security mechanism that restricts what resources a page can load C) An encryption protocol for securing data in transit D) A database access control mechanism
Answer
**B)** CSP is an HTTP response header that tells the browser which sources of content (scripts, styles, images, etc.) are allowed to load on the page. A strict CSP like `script-src 'self'` prevents inline scripts injected by attackers from executing, making it one of the most effective defenses against XSS.Question 7
Which of the following is an Insecure Direct Object Reference (IDOR) vulnerability?
A) A user guesses another user's password
B) A user changes /api/profile/42 to /api/profile/43 in the URL and sees another user's profile
C) A user submits a SQL injection payload in a login form
D) A user uploads a malicious file to the server
Answer
**B)** IDOR occurs when an application uses user-supplied identifiers (like an ID in the URL) to access resources without verifying that the authenticated user is authorized to access that specific resource. The fix is to always check that the requesting user owns or has permission to access the referenced resource.Question 8
What is the correct approach to storing secrets in a production application?
A) Hardcode them in the source code for reliability
B) Store them in a .env file committed to the repository
C) Use a dedicated secret manager (e.g., AWS Secrets Manager, HashiCorp Vault)
D) Encode them in Base64 in the configuration file
Answer
**C)** Production secrets should be stored in a dedicated secret manager that provides encryption at rest, access control, audit logging, and automatic rotation. Hardcoded secrets and committed `.env` files expose credentials to anyone with repository access. Base64 is an encoding, not encryption—it provides zero security.Question 9
What does the SameSite=Lax attribute on a cookie prevent?
A) SQL injection attacks B) Cross-Site Request Forgery (CSRF) attacks by restricting when cookies are sent with cross-site requests C) Cross-Site Scripting (XSS) attacks D) Man-in-the-middle attacks
Answer
**B)** `SameSite=Lax` prevents the browser from sending the cookie with cross-site POST requests and other unsafe request types, mitigating CSRF attacks. The cookie is still sent with top-level navigation GET requests, providing a balance between security and usability.Question 10
What is "defense in depth"?
A) Using the most advanced security tool available B) Layering multiple security controls so that if one fails, others catch the attack C) Focusing all security resources on the most critical vulnerability D) Performing security testing only at the end of development
Answer
**B)** Defense in depth means implementing multiple layers of security controls. For example, input validation at the API boundary, parameterized queries at the database layer, output encoding at the presentation layer, and CSP headers at the browser layer. No single control is relied upon exclusively.Question 11
When using JWTs, why is it important to pass algorithms as a list (e.g., algorithms=["HS256"]) during verification?
A) It improves decoding performance B) It prevents algorithm confusion attacks where an attacker switches the algorithm (e.g., to "none") C) It enables the token to be decoded by multiple services D) It is required by the JWT specification
Answer
**B)** Algorithm confusion attacks exploit JWT libraries by switching the algorithm in the token header. For example, an attacker might change the algorithm to "none" (no signature required) or switch from RS256 to HS256 (using the public key as the HMAC secret). Explicitly specifying allowed algorithms prevents the library from accepting unexpected algorithm types.Question 12
What is typosquatting in the context of dependency security?
A) Making typos in your own code that create vulnerabilities B) An attacker publishing a malicious package with a name similar to a popular package C) Using deprecated function names D) Misspelling environment variable names
Answer
**B)** Typosquatting is a supply chain attack where an attacker publishes a package with a name that is a common misspelling of a popular package (e.g., `reqeusts` instead of `requests`). When a developer accidentally misspells the package name during installation, they install the malicious version instead.Question 13
What should you do FIRST when you discover that a secret has been accidentally committed to a git repository?
A) Delete the file containing the secret and commit the deletion
B) Immediately rotate (regenerate) the compromised secret
C) Use git filter-repo to rewrite history
D) Add the file to .gitignore
Answer
**B)** The first priority is to rotate the secret—generate a new key, token, or password and revoke the old one. Even if you rewrite git history, the secret may have been cloned, cached, or indexed. Deleting the file or adding it to `.gitignore` does not remove it from git history. History rewriting is important but is a second step after rotation.Question 14
Which Pydantic feature is MOST useful for preventing mass assignment vulnerabilities?
A) Field(min_length=3)
B) model_config = ConfigDict(extra='forbid')
C) EmailStr type
D) @field_validator
Answer
**B)** Setting `extra='forbid'` causes Pydantic to reject any fields in the input that are not defined in the model. This prevents mass assignment attacks where an attacker adds unexpected fields (like `"is_admin": true`) to a request body. The other options provide input validation but do not prevent extra field injection.Question 15
What is the recommended expiration time for a JWT access token?
A) 1 year B) 30 days C) 15–60 minutes D) Tokens should never expire
Answer
**C)** Access tokens should have short expiration times (typically 15–60 minutes) to minimize the window of exposure if a token is compromised. Longer sessions should be handled with refresh tokens, which can be revoked and are stored more securely. One-year tokens or non-expiring tokens are major security risks.Question 16
Which tool is designed specifically for scanning Python code for security vulnerabilities?
A) pytest B) black C) bandit D) mypy
Answer
**C)** Bandit is a security linter for Python that scans code for common security issues such as hardcoded passwords, use of insecure functions (like `eval()` and `exec()`), insecure hash functions, and SQL injection patterns. pytest is a testing framework, black is a code formatter, and mypy is a type checker.Question 17
What is the difference between authentication and authorization?
A) Authentication is for APIs; authorization is for web pages B) Authentication verifies identity ("who are you?"); authorization determines permissions ("what can you do?") C) Authentication uses passwords; authorization uses tokens D) They are the same thing
Answer
**B)** Authentication verifies that a user is who they claim to be (identity verification). Authorization determines what actions that authenticated user is permitted to perform (permission checking). Both are required: authentication without authorization means every logged-in user can do everything; authorization without authentication means you cannot know who is making the request.Question 18
Why should app.run(debug=True) NEVER be used in production?
A) It makes the application slower B) It enables an interactive debugger that allows arbitrary code execution and exposes detailed error information C) It disables HTTPS D) It prevents the application from scaling
Answer
**B)** Flask's debug mode enables the Werkzeug interactive debugger, which allows anyone who can trigger an error to execute arbitrary Python code on the server. It also displays detailed stack traces that may reveal file paths, configuration details, and internal logic. This is extremely useful during development but is a critical vulnerability in production.Question 19
What is the purpose of pip-audit?
A) It checks Python code for style violations B) It scans installed packages against vulnerability databases to find packages with known security issues C) It optimizes pip installation speed D) It removes unused dependencies
Answer
**B)** `pip-audit` scans your installed Python packages (or a requirements file) against the Open Source Vulnerability (OSV) database to identify packages with known security vulnerabilities (CVEs). It reports the affected package, the vulnerable version, and the fixed version if available.Question 20
In RBAC, what is the relationship between users, roles, and permissions?
A) Users have permissions directly; roles are optional B) Permissions are assigned to roles, and roles are assigned to users C) Roles have users, and users have permissions D) Users, roles, and permissions are all the same thing
Answer
**B)** In Role-Based Access Control, permissions (e.g., "create_article", "delete_user") are assigned to roles (e.g., "editor", "admin"), and roles are assigned to users. This creates an indirection layer that simplifies permission management—instead of assigning permissions to each user individually, you assign a role that carries a set of permissions.Question 21
What is output encoding and why is it the primary defense against XSS?
A) Encrypting output data before sending it to the client
B) Converting special characters (like < and >) to HTML entities so the browser renders them as text, not code
C) Compressing output to reduce bandwidth
D) Logging all output for auditing purposes
Answer
**B)** Output encoding converts characters that have special meaning in HTML (like `<`, `>`, `&`, `"`, `'`) into their HTML entity equivalents (`<`, `>`, `&`, `"`, `'`). This ensures that user-supplied content is rendered as text in the browser, not interpreted as HTML or JavaScript code. It is the primary defense because it neutralizes injected scripts at the point of rendering.Question 22
What is a trust boundary?
A) The physical border of a data center B) A firewall between two networks C) Any point where data crosses from an untrusted source to a trusted context D) The encryption boundary in TLS
Answer
**C)** A trust boundary is any point in your application where data transitions from an untrusted context to a trusted one. User input entering your API is a trust boundary. Data from a third-party service is a trust boundary. Even data read from your database—if it was originally user-supplied—crosses a trust boundary when rendered in HTML. Every trust boundary requires validation, sanitization, or encoding.Question 23
Why should you pin dependency versions in production requirements files?
A) Pinned versions install faster B) Pinned versions ensure reproducible builds and prevent automatic installation of compromised newer versions C) Pinned versions use less disk space D) Pinned versions are required by PEP 8
Answer
**B)** Pinning exact versions (e.g., `flask==3.0.0` instead of `flask>=3.0.0`) ensures that every deployment installs the same versions of every dependency. This provides reproducibility and protects against supply chain attacks where a compromised newer version is published. Without pinning, `pip install` may automatically install a malicious update.Question 24
What is the principle of least privilege?
A) Giving every user admin access for convenience B) Ensuring every component, user, and process has the minimum permissions necessary to perform its function C) Using the minimum amount of code to implement a feature D) Running applications with root privileges for maximum capability
Answer
**B)** The principle of least privilege states that every component, user, and process should have only the permissions necessary to perform its intended function—nothing more. A database user that only needs to read data should not have write or delete permissions. An API endpoint that serves public content should not require admin-level access. This limits the damage that can occur if a component is compromised.Question 25
You ask an AI assistant to generate a database query function. The generated code uses f"SELECT * FROM {table_name} WHERE id = {user_id}". What are the TWO security issues, and how would you fix them?
A) There are no issues; f-strings are safe for SQL B) The table name and the user_id are both vulnerable to SQL injection; use parameterized queries for user_id and a whitelist for table_name C) Only the table name is an issue; user_id is safe because it is an integer D) Only user_id is an issue; table names cannot be injected