A dependency is code you did not write
A dependency is a library written by someone else that your project uses. Dependency risk is the chance that a flaw in one of them becomes a flaw in your product. Most of a modern project is dependencies, so most of its code is not yours.
A team ships on Friday. On Monday a flaw is announced in a library they use. The question is whether they can find out, in minutes, which version they run.
By the end of this lesson
Note
I can judge the risk of the libraries a project uses.
Key words
| Word | What it means | Example |
|---|---|---|
| Dependency | a library your project needs in order to run | |
| Version pinning | naming the exact version of a dependency | webform==1.4.2 |
| Advisory | a public notice of a flaw and the version that fixes it | |
| Lock file | a file that records the exact version of every dependency | |
| Secret | a password, key or token that must stay private | |
| Attack surface | every place where an attacker can send something in |
The cells students fill in are left blank in this preview.
The one rule
Warning
The lab is an application that hides fake secrets on purpose. Look into your own private copy and nothing else. It has no way out to the internet. Never search a site or code store that is not yours for secrets. In the UK that is a crime under the Computer Misuse Act 1990.
Most of a project is other people's code
A project lists its dependencies in a file. Each line names a library and, ideally, an exact version. Version pinning fixes the exact version, so the code you tested is the code you ship.
A line with a range, or with no version at all, lets the next install pick something new. A lock file records every version, including the libraries your libraries need.
Worked example: three ways to write a line
| Line | What it means | Risk |
|---|---|---|
| webform==1.4.2 | Exactly version 1.4.2 | Low: it never changes by surprise |
| webform>=1.0 | Any version from 1.0 upwards | Medium: the next install may change |
| webform | Any version at all | High: you do not know what you run |
The cells students fill in are left blank in this preview.
Reading a pinned line
# Change the line to "imgtool==2.10.0" and press Run.
line = "webform==1.4.2"
parts = line.split("==")
print("library:", parts[0])
print("version:", parts[1])
A known flaw names its fixed version
When a flaw in a library is found, an advisory is published. It names the flaw and the first version that fixes it. Your job is to compare what you run with that version.
Versions are numbers separated by dots, and they must be compared as numbers. As plain text, 2.10.0 sorts before 2.9.0, which is wrong.
Worked example: checking three libraries
| Library | You run | Fixed in | Verdict |
|---|---|---|---|
| webform | 1.4.2 | 1.4.9 | Upgrade: 1.4.2 is older than 1.4.9 |
| imgtool | 2.10.0 | 2.9.5 | Fine: 2.10.0 is newer than 2.9.5 |
| logkit | 3.0.0 | 3.1.0 | Upgrade: 3.0.0 is older than 3.1.0 |
The cells students fill in are left blank in this preview.
Comparing versions as numbers
def numbers(version):
result = []
for part in version.split("."):
result.append(int(part))
return result
# Change installed to "2.9.1" and press Run.
installed = "2.10.0"
fixed = "2.9.5"
print("as text, older:", installed < fixed)
print("as numbers, older:", numbers(installed) < numbers(fixed))
A common mistake
Warning
Many people think pinning a version is enough. It stops surprise changes, but it also freezes old flaws in place. Pin your versions, then check for advisories on a schedule and update on purpose, with tests.
Libraries bring features you did not choose
A library often ships extra features, some switched on by default. A management page, a debug mode or a sample account is attack surface you never asked for.
Read what a library turns on. Switch off what you do not use. The fewer places an attacker can reach, the less there is to defend.
Keep secrets out of code and history
A secret in a source file travels with the code to every copy, every backup and every old version. Deleting the line later does not remove it from history.
Keep secrets in the environment or a secrets manager, given to the program when it starts. If a secret was ever in the code, treat it as spent and replace it.
Look at a running application from outside
Your lab runs an application that has one library feature switched on: a set of management pages. The lab pins its version too, as 1.14.1, in the line that starts it. The next two lines only look. The first asks whether the application is healthy. The second lists the management pages it offers.
Is the application healthy?
curl -s -w "\n" http://wrongsecrets:8080/actuator/healthShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Which management pages are switched on?
curl -s http://wrongsecrets:8080/actuator | grep -o 'actuator/[a-z]*' | sort -uShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
What the two answers tell you
The first prints a short line that ends "status":"UP". The second prints three names: auditevents, health and info.
These pages come from a library feature, not from code the team wrote. Ask which one a stranger should not be able to read, and whether the application needs it at all.