Lab: Find the secrets
Scan a deliberately insecure project with DL Sentinel, read what it finds, fix a leaked token, and adopt a baseline so only new problems fail. Then turn the same habits on your own computer: open ports, a download's checksum, and an export you might share.
Level: beginner · Time: 45 to 60 minutes · Before this: the six lessons of this track, or at least Scanning your code
What you need
- A Linux computer with DL Sentinel built from source and the
sentinelalias set up. See Install DL Sentinel. - A terminal.
- For part 3: ApiWorkbench with at least one collection or environment.
The sample project is tests/fixtures/vulnerable-app inside the dl-sentinel folder. It contains at least one planted problem for every scanner, and every credential in it is fake. It exists to be scanned, so it is a safe target. You will work on a copy, so the original stays as DL Sentinel's own tests expect it.
Part 1: Scan a vulnerable project
Make a practice copy. From inside the
dl-sentinelfolder:bashcp -r tests/fixtures/vulnerable-app ~/sentinel-lab cd ~/sentinel-lab ls -aExpected: files such as
.env,Dockerfile,docker-compose.yml,openapi.yaml,package.json, and the foldersconfig,contracts,k8s,srcandterraform.Scan everything.
bashsentinel scan .Expected: a summary like this:
textsecrets 7 findings dependencies 5 findings source 11 findings infra 18 findings api 8 findings smart-contract 7 findings Critical: 11 High: 28 Medium: 6 Low: 4 Info: 7 Scan completed.The exact numbers can change between DL Sentinel versions. What matters is that every scanner found something.
Check the exit code.
bashecho $?Expected:
1. There are findings at a failing severity (critical or high), so a CI job running this scan would fail.Focus on secrets.
bashsentinel scan . --scanners secretsExpected:
secrets 7 findings, all of themCritical.Write the full report and read it. Save it outside the project, so it is not scanned or committed with it:
bashsentinel scan . --scanners secrets --format markdown --output ~/sentinel-lab-report.mdOpen
~/sentinel-lab-report.mdin a text editor. Expected: seven findings, most severe first, each with a rule id, file, line, evidence and a recommendation:Rule File What it found S001,S002.envAn AWS access key id and secret access key S018.envA database connection string with a password inside S003config/settings.ymlA GitHub token S017config/settings.ymlA private key block S013DockerfileAn npm access token in an ENVlineS013docker-compose.ymlThe same npm token, in the service's environment Look at the Evidence lines: every secret value shows as
[REDACTED]. The report tells you where the secret is without repeating it.Look at one secret yourself. Open
.envin a text editor. The AWS key isAKIAIOSFODNN7EXAMPLE, the example value AWS itself publishes in its documentation. In a real project, this is the moment to follow lesson 2: rotate first, then clean up.
Part 2: Fix a finding and add a baseline
Fix the token in the Dockerfile. Open
Dockerfileand delete this line:textENV NPM_TOKEN=npm_EXAMPLEEXAMPLEEXAMPLEEXAMPLEEXAMPLE00An
ENVline is baked into the image, where anyone who has the image can read it. In a real project you would first revoke the token with npm and create a new one, then pass the new one in only at build time, never in a file.Scan again.
bashsentinel scan . --scanners secrets,infraExpected:
secrets 6 findings(was 7) andinfra 17 findings(was 18). One line held two problems: the secret itself, and the infrastructure rule against secrets inENV. The token indocker-compose.ymlis still reported; fixing it is a task for the end of the lab.Create a baseline. Pretend this is an old project with a backlog you cannot fix today:
bashsentinel baseline .Expected: a line such as
Wrote baseline with 54 findings to /home/you/sentinel-lab/.sentinel-baseline.json, and exit code0.Look inside the baseline.
bashhead -20 .sentinel-baseline.jsonExpected: the tool name and version, a
countof54, then the start of a list of findings, each with anid,ruleId,fileandseverity. No code and no secret values: the file is safe to commit.Scan against the baseline.
bashsentinel scan . --baseline .sentinel-baseline.json echo $?Expected: every scanner shows
0 findings, the summary includesNew: 0 (Baselined: 54), and the exit code is0. The old findings are still there; they are set aside so that only new ones count.
Break it: add a new secret
Commit a mistake. Add a file with a fake GitHub token, as if someone pasted one into a config:
bashecho 'GITHUB_TOKEN=ghp_EXAMPLEEXAMPLEEXAMPLE1111111111111111' > deploy.env sentinel scan . --baseline .sentinel-baseline.json echo $?Expected:
secrets 1 finding,Critical: 1,New: 1 (Baselined: 54), and exit code1. The baseline did not hide it, because it is new. In CI, this pull request would fail.Read the new finding.
bashsentinel scan . --baseline .sentinel-baseline.json --format markdown --output ~/sentinel-lab-new.mdExpected: one finding,
CRITICAL S003 — GitHub token committed, atdeploy.env:1, with evidenceGITHUB_TOKEN=[REDACTED].Fix it the right way. Replace the value with an empty placeholder, as you would in a
.env.examplefile:bashecho 'GITHUB_TOKEN=' > deploy.env sentinel scan . --baseline .sentinel-baseline.json echo $?Expected:
New: 0and exit code0. A real token would also need revoking, because it could already be in Git history.
Try it: fix the npm token in docker-compose.yml too (delete the environment: line and the NPM_TOKEN: line under it), then run sentinel scan . --baseline .sentinel-baseline.json --write-baseline .sentinel-baseline.json. The rewritten baseline records 52 findings: again one line held two problems, a secret and a secret in a Compose environment. Then fix one source finding: in src/unsafe.js, change findUserByName to the parameterized query from lesson 5 and scan with --scanners source.
Part 3: Check your own machine
These three checks are worth repeating every few months.
List your listening ports.
bashss -tlnExpected: a table like this one, with different ports:
textState Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 4096 127.0.0.1:631 0.0.0.0:* LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* LISTEN 0 511 *:4173 *:*For each line whose address is
0.0.0.0,[::]or*, ask: did I mean to run this, and should my whole network reach it? Runss -tlnpto see which of your own programs owns a port. Stop anything you do not need, such as a forgotten development server or a Mock Studio project. See Safe networks.Verify a download. Pick an app you were going to install whose releases page publishes a
.sha256file or aSHA256SUMSfile. Download both into the same folder, then:bashsha256sum -c <file>.sha256or, for a list of many files:
bashsha256sum -c --ignore-missing SHA256SUMSExpected: the file name followed by
OK. Anything else means: do not install it.See a checksum fail. Make a small file of your own and its checksum, then change the file:
bashcd ~ echo "hello" > note.txt sha256sum note.txt > note.txt.sha256 sha256sum -c note.txt.sha256 echo "changed" >> note.txt sha256sum -c note.txt.sha256Expected: first
note.txt: OK, thennote.txt: FAILEDandWARNING: 1 computed checksum did NOT match. One added line changed the checksum completely.Review an ApiWorkbench export before sharing it. In ApiWorkbench, select Export, choose ApiWorkbench workspace, leave Include current values off, select Export and save the file into a new, empty folder,
~/export-check. Then search it for anything that looks like a secret:bashgrep -n -i -E 'token|password|secret|apikey|api_key|authorization' ~/export-check/*.json sentinel scan ~/export-check --scanners secrets,apiExpected:
grepprints every line that names a token, password or key, with its line number; read each one and check whether a real value is there. The scan reports any value that matches its rules, with the value shown as[REDACTED]. A Postman collection export is also checked by the API scanner for secrets stored in the collection.If you find a real value, move it from the variable's Initial value to its Current value, set its Type to Secret, and export again. See Export and share.
Use both checks
A scanner can miss a secret. In a test export, DL Sentinel reported a token in JSON Web Token format (at medium severity, which does not fail the default policy, so the exit code was 0) but did not report a plain password stored in a JSON field. grep found both. Read the file, use grep, and use the scanner: each catches what the others miss.
Try it: export again with Include current values on, into the same folder, and run the two commands. Compare: your own tokens are now in the file. Delete that export afterwards.
Clean up
Delete the practice copy, the reports and the test files:
bashrm -rf ~/sentinel-lab ~/sentinel-lab-report.md ~/sentinel-lab-new.md ~/note.txt ~/note.txt.sha256Delete the export folder, which may contain tokens:
rm -rf ~/export-check.Stop any server you started or found running in step 15 that you do not need.
The original sample project in dl-sentinel/tests/fixtures/vulnerable-app is unchanged.
Check yourself
Question 1 of 6
Why does the lab scan a copy of tests/fixtures/vulnerable-app instead of the original?
What you learned
- A scan's summary gives counts; the Markdown report gives each finding with file, line, redacted evidence and advice.
- Fixing one line can clear more than one finding, and a scan after each fix proves it.
- A baseline sets old findings aside so only new ones fail, which is how a scanner is adopted on an existing project.
- Your own machine needs the same care: open ports, verified downloads, and exports checked before they leave your hands.
Next steps
- Use DL Sentinel in CI: run this scan on every pull request
- Configure scans: suppressions with a reason and an expiry date
- All learning tracks