Introduction
A temporary debug setting has returned in a new DeskLite service version. Requests still succeed, but operational logs now include a fake credential. A functional success check alone did not catch this regression.
You will follow real request evidence, stop new leakage, replace the exposed credential, and add an assertion that blocks a genuinely leaky candidate. Historical logs remain as evidence; no investigation document is required. The local issuer, client, service, comparison controls, and artifact helpers are prepared.
Locate the Real Incident Event
In this step, you will correlate a request with the current logging version and configuration.
cd /srv/ticket-regression
tail -n 5 reads the last five lines, keeping the view small. Use your authorized administrator read for the prepared service log:
sudo tail -n 5 /opt/labex-ticket-regression/requests.log
Find request_id=initial-001, version=logging-v2, path=/tickets, and status=200. This historical request succeeded, but the same line includes Authorization and the old fictional Token. All values belong only to this isolated lab.
grep prints lines containing a supplied text pattern. Single quotes keep this literal pattern together:
sudo grep 'request_id=initial-001' /opt/labex-ticket-regression/requests.log
cat logging.conf
include_authorization = true explains the sensitive field. The event's time, request ID, version, and status connect observed behavior to the active configuration. Keep the original log; erasing it would remove evidence, not prevent future leakage.
Stop Sensitive Fields in New Events
In this step, you will change the logging policy while retaining useful audit fields.
nano logging.conf
Use:
[logging]
include_authorization = false
Save with Ctrl+O, Enter, and Ctrl+X. Apply the saved configuration using the prepared restart entry point:
bash restart.sh
Give a new health request a known ID. X-Request-ID is a request header used to correlate its fresh event:
curl -H 'X-Request-ID: after-policy-fix' http://127.0.0.1:8080/health
sudo grep 'request_id=after-policy-fix' /opt/labex-ticket-regression/requests.log
Expect time, version, ID, path, and status=200, with no Authorization field. The old initial-001 event remains. Judge new events by their own IDs rather than requiring every historical line to be secret-free.
Revoke and Replace the Exposed Credential
In this step, you will remove the old Token's authority using the issuer workflow already learned.
Changing log policy does not invalidate an exposed value. Revoke its management ID:
course-token revoke legacy
curl -i -H 'Authorization: Bearer labex_012345abcdefghijklmnopqrstuvwxyz' http://127.0.0.1:8080/tickets
Expect 401. Now issue the replacement without printing it:
course-token issue /srv/ticket-regression/api.token
Protect it using the administrator/client-group pattern from the permissions and Token labs:
sudo chown root:deskclient api.token
sudo chmod 640 api.token
The issuer created the value; you only set its access. Do not copy it into the test source, client script, or a written report.
Restore the File-Reading Client
In this step, you will make the existing client use the protected replacement.
nano sender.sh
Save the same file-reading form taught earlier:
#!/bin/bash
exec sudo -u deskclient /usr/bin/python3 /opt/labex-ticket-regression/send.py --token-file /srv/ticket-regression/api.token
Use Ctrl+O, Enter, Ctrl+X.
bash sender.sh
Expect HTTP 200 and the original Printer offline ticket. Read the recent operational events:
sudo tail -n 5 /opt/labex-ticket-regression/requests.log
The new successful request retains audit fields without a credential value. An old leaked value can remain in the preserved incident history while its authority has been removed. That distinction avoids both deleting evidence and treating old exposure as a continuing successful authentication path.
See Why the Existing Test Missed the Leak
In this step, you will inspect the small test template before adding the new requirement.
cat test_security.py
The positive test uses the request template from the test-writing lab. The prepared api helper supplies token from the target's credential source and returns the real HTTP status, body, and that request's actual log event. "Bearer " + token joins two strings into a header value; the value is not copied into source.
Two separate controls use the public fake test fixture Token: good omits sensitive log fields, while logging-regression deliberately records the fixture Token. They do not use or expose your new operational replacement.
course-regression-tests good
course-regression-tests logging-regression
Both currently pass test_valid_token: status and business data remain correct in either implementation. The missing requirement concerns the real event in response["log"]. Each helper request uses a unique ID, so the returned log belongs to that fresh request rather than an unrelated historical event.
Add a Real Log-Redaction Assertion
In this step, you will extend the test with both absence and presence requirements for the fresh event.
Python in checks whether one string occurs inside another. not in requires it to be absent. These are assertions about the actual returned log text, not a manually supplied evidence file.
nano test_security.py
Keep the positive test and use this complete file:
from api import request, token
def test_valid_token():
response = request("/tickets", {"Authorization": "Bearer " + token})
assert response["status"] == 200
assert response["body"] == {"tickets": [{"id": 1, "title": "Printer offline"}]}
def test_log_is_redacted():
response = request("/tickets", {"Authorization": "Bearer " + token})
assert response["status"] == 200
assert "Authorization" not in response["log"]
assert token not in response["log"]
assert "request_id=" in response["log"]
assert "path=/tickets" in response["log"]
assert "status=200" in response["log"]
Save with Ctrl+O, Enter, Ctrl+X. The new test rejects the sensitive field and credential value while requiring the request ID, business path, and successful status. Emptying the log would fail those positive requirements.
The helper supplies a target-specific Token internally. Normal service tests read the protected replacement; comparison controls use the public fake fixture. Neither value belongs in this test file.
Prove the Test Detects the Known Regression
In this step, you will validate the new assertion against safe and deliberately leaky behavior.
course-regression-tests good
Expect both tests to pass.
course-regression-tests logging-regression
Expect only test_log_is_redacted to fail with AssertionError, returning exit 1. This is an intentional detection, not a request to weaken the assertion. The positive business test must continue to pass.
course-regression-tests live
Both should pass against your actual repaired service. These tests inspect only their fresh request events; the original leaked historical event is intentionally retained. A syntax error, connection error, or unconditional failure would not demonstrate effective redaction coverage.
Connect the New Test to Candidate Delivery
In this step, you will prevent a future candidate from being delivered when the new assertion fails.
The prepared gate uses the same check/build/test/deploy structure as the previous gate lab. build.sh packages the original server and current logging policy, then starts that actual candidate on a separate local port. The existing test.sh checks its valid/missing/wrong-Token behavior; it does not check logs.
nano gate.sh
Add the regression call after the build and before the existing functional tests. Use:
#!/bin/bash
bash checks.sh
status=$?
if [ "$status" -eq 1 ]; then
exit 1
fi
if [ "$status" -ne 0 ]; then
exit 2
fi
bash build.sh || exit 2
bash regression.sh candidate || exit 2
bash test.sh || exit 2
bash deploy.sh
Save with Ctrl+O, Enter, Ctrl+X. candidate selects the actual just-built application, so the added assertion protects the artifact about to be deployed. || exit 2 stops delivery if its tests fail.
bash gate.sh
Expect the credential preflight, actual candidate build, passing new regression tests, passing functional tests, and deployment of that candidate to the operational local port. Merely leaving an unused test file would not provide this prevention.
Confirm New Events and Retained History
In this step, you will verify the delivered behavior and reflect on the evidence without writing a report file.
bash sender.sh
sudo tail -n 5 /opt/labex-ticket-regression/requests.log
Fresh operational events must retain time, actual delivered version, request IDs, paths, and statuses without credentials. The delivered version is now an artifact hash rather than the original logging-v2 label.
sudo grep 'request_id=initial-001' /opt/labex-ticket-regression/requests.log
The original incident event still exists. Its old Token is revoked; the protected replacement works. The separate deliberate regression control is a teaching comparison, not the deployed service.
Explain to yourself: which event revealed the problem, which setting caused it, why policy repair alone was insufficient, and how the new candidate assertion prevents recurrence. The course check exercises a genuinely regressed candidate, confirms the gate blocks it, and verifies that the previously safe running artifact survives. No fixed-format investigation document is required.
Summary
You connected a real incident event to its logging policy, stopped new leakage, revoked and replaced the exposed credential, and retained historical evidence. A new assertion detects the deliberate regression and runs on the actual candidate inside the delivery gate, preserving safe running behavior when a future candidate fails.



