
No flags are included in this writeup.
Overview
Trust Issues was different from the previous exploitation-heavy challenges. It was incident response. The scenario started with a compromised machine and an external repository that looked like a data leak. The goal was to understand what happened, how exfiltration worked, and where the sensitive value ended up.
| Field | Value |
|---|---|
| Month | February 2026 |
| Points | 20 |
| Main area | Incident response, GitHub Actions, Python supply chain |
Understanding The Machine
The hostname and filesystem quickly pointed toward a self-hosted GitHub Actions runner. That mattered because CI runners are full of short-lived secrets: repository tokens, cloud credentials, kubeconfigs, environment variables, and workflow context.
The runner logs showed a recurring job pattern. The attacker’s public repository had repeated commits with encrypted-looking files. The timing lined up with the scheduled CI activity.
That made the central theory simple:
Something in the CI job was harvesting runner environment data and pushing encrypted blobs to the attacker-controlled repository.
Finding The Malicious Package
The hint pointed toward supply chain, so I checked installed Python packages. The interesting artifact was not a random shell script. It was a malicious Python file hidden inside the pytest package tree.
That was a clever choice. Pytest has plugin hooks that execute during test lifecycle events. If malicious code is placed where pytest will load it, the payload runs naturally during CI without needing an obvious command in the workflow file.
The payload did three important things:
- collected environment variables
- encrypted them with Fernet
- pushed the encrypted data to a GitHub repository
- deleted workspace/log artifacts to reduce forensic evidence
Decrypting The Exfiltration
The attacker’s repository contained many encrypted .secret-style blobs. The payload itself included the logic needed to identify the encryption method and recover the key material.
Once the Fernet key was recovered, the workflow was straightforward:
- clone or fetch the attacker’s data repository
- identify the file matching the compromised runner
- decrypt the blob
- inspect the environment variables
The sensitive value was inside the exfiltrated CI environment.
Root Cause
Trust Issues showed how a trusted CI environment can become the blast radius:
- a trojanized Python dependency executed during tests
- pytest hooks provided automatic execution
- CI secrets were exposed as environment variables
- stolen data was encrypted and pushed to a public dead-drop repo
- cleanup logic removed obvious local traces
Takeaways
This challenge maps directly to real incidents:
- self-hosted runners need aggressive isolation
- dependency integrity matters even for “dev/test” packages
- CI secrets should be scoped and short-lived
- monitor unusual package files and pytest plugin behavior
- treat public attacker repos as evidence, not just indicators
Trust Issues was a reminder that supply chain attacks do not need dramatic malware. A small malicious hook in the right package can turn normal CI into an exfiltration engine.