Skip to content

Commit b36e469

Browse files
Make all section names unique and enforce it
The HTML anchor names for sections are automatically generated from their section heading text. That's fine, but if we want to make sure we can refer to any section, we need to ensure that every section heading's text is unique. This modifies the context to make every section heading unique (after changing the quiz headings we were close), and modifies our markdownlint configuration so we'll reject future changes that create duplicate section text entries. It's still possible for multiple locations to end up with the same anchor name (e.g., if they differ only in characters that aren't used to create the anchor name), but in practice this is highly unlikely and we can address this by reviewing changes before accepting them. Signed-off-by: David A. Wheeler <[email protected]>
1 parent bfe23f0 commit b36e469

File tree

2 files changed

+11
-8
lines changed

2 files changed

+11
-8
lines changed

.github/linters/.markdown-lint.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,8 @@ MD036: false # MD036/no-emphasis-as-heading
88
MD038: false # MD038/no-space-in-code Spaces inside code span elements
99
MD049: false # MD049/emphasis-style
1010
MD012: false # MD012/no-multiple-blank
11-
MD024: false # MD024/no-duplicate-heading/no-duplicate-header
1211
MD001: false # MD001/heading-increment/header-increment
12+
13+
# We enforce "no duplicate headers" so hypertext links to sections will have
14+
# unique anchor names to refer to.
15+
# MD024: false # MD024/no-duplicate-heading/no-duplicate-header

secure_software_development_fundamentals.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,7 +1354,7 @@ Learning objectives:
13541354

13551355
## Input Validation Basics
13561356

1357-
### Input Validation Basics
1357+
### Input Validation Basics Introduction
13581358

13591359
Some inputs are from untrustable users, and those inputs (at least) must be validated before being used. If you prevent invalid data from getting into your program, it will be much harder for attackers to exploit your software. Input validation can also prevent many bugs and make your program simpler. After all, if your program can immediately reject some malformed data, you don’t have to write the code to deal with those special cases later. That saves time, and such special-case code is more likely to have subtle errors.
13601360

@@ -1905,7 +1905,7 @@ Absolutely not. If there is a standard known password, it will be immediately po
19051905

19061906
## Consider Availability on All Inputs
19071907

1908-
### Consider Availability on All Inputs
1908+
### Consider Availability on All Inputs Introduction
19091909

19101910
As we discussed before, it is often difficult to guarantee availability in all possible circumstances. For example, if a system is publicly accessible over the Internet, an attacker could initiate a large-scale distributed denial-of-service (DDoS) attack, overwhelming your service’s resources.
19111911

@@ -2311,7 +2311,7 @@ Learning objectives:
23112311

23122312
## Introduction to Securely Calling Programs
23132313

2314-
### Introduction to Securely Calling Programs
2314+
### Introduction to Securely Calling Programs - The Basics
23152315

23162316
Very few programs are entirely self-contained; nearly all programs call out to other programs. This includes local programs, such as programs provided by the operating system, built-in software libraries for that language, and software from package repositories (like npm, PyPI, and maven). Modern systems often call out through a network to other services, making requests through various APIs (such as REST and GraphQL APIs) and receiving data in formats such as JSON and XML. Almost all of these programs then call other programs. Often, these indirect calls are not obvious (e.g., calling a library written by someone else) or involve a great deal of “hidden” infrastructure.
23172317

@@ -2351,7 +2351,7 @@ Where possible, use libraries and APIs that do this for you; they are easier to
23512351

23522352
Let’s now examine some common injection attack cases and how to handle them securely. Again, an injection vulnerability is when a program accepts data from an attacker and improperly hands that data to some command interpreter. Some of the most common problems occur when that data is sent to a database system (SQL injection attacks) or an operating system command interpreter (OS command injection attacks), so we will focus on those. Once you understand how to deal with these two common cases, it will be much clearer how to properly handle other interpreters we will not cover here (e.g., the Lightweight Directory Access Protocol (LDAP)). We will begin by discussing sending data to database systems, which are often vulnerable to SQL injection attacks.
23532353

2354-
#### Quiz 3.1: Introduction to Securely Calling Programs
2354+
#### Quiz 3.1: Introduction to Securely Calling Programs - The Basics
23552355

23562356
\>\>Just pick secure software to reuse, and your application will be secure. True or False?<<
23572357

@@ -2697,7 +2697,7 @@ For example, in Python, if you need to write to a user-provided table name, you
26972697
cur.execute(f"insert into {table_name}(d, ts) values (?, ?)", (today, now)) # This is safe because we know that table_name can only take trusted values from table_name_map
26982698
~~~~
26992699

2700-
##### Other Approaches
2700+
##### Other Approaches for Countering SQL Injection
27012701

27022702
Many programs use object-relational mapping (ORM). This is just a technique to automatically convert data in a relational database into an object in an object-oriented programming language and back; lots of libraries and frameworks will do this for you. This is fine, as long as the ORM is implemented using parameterized statements or something equivalent to them. In practice, any good ORM implementation will do so. So if you are using a respected ORM, you are already doing this. That said, it is common in systems that use ORMs to occasionally need to use SQL queries directly… and when you do, use parameterized statements or prepared statements.
27032703

@@ -2939,7 +2939,7 @@ If you are implementing the *top* level of a program or framework (e.g., its mai
29392939

29402940
Otherwise, you generally should be specific about the exceptions you catch, and only catch an exception if you can do something appropriate about it. Attackers will try to trigger exceptions, so make sure that exception handlers are secure.
29412941

2942-
#### Other Approaches
2942+
#### Other Approaches for Error Handling
29432943

29442944
There are other error-handling approaches.
29452945

@@ -4215,7 +4215,7 @@ Learning objectives:
42154215

42164216
8. Understand the basics of other key cryptographic topics.
42174217

4218-
## Cryptography
4218+
## Applying Cryptography
42194219

42204220
### Introduction to Cryptography
42214221

0 commit comments

Comments
 (0)