Toss out a brick to lure a jade gem.
— The 36 Stratagems, Throw Out a Brick to Get a Jade
Previously on this series:
#8: Alex Watched an AI Dashboard Take Over. — MedTech signed a million-dollar AI monitoring contract. Alex built a hidden panel during training. When the panel failed, only he could read and write production.
#15: Derek and Alex Shared One Server. ACL's AI Was Listening to Both. — Alex and Derek faked an alert to divert ACL's audit engineer, then redirected the collector output. Alex never forgot ACL's pipeline signature.
Alex didn't watch alerts. He watched patterns.
An alert tells you what broke. A pattern tells you what's changing.
Monday morning, 2 AM. He pulled MedTech's AI monitoring platform sensitivity curves for the past sixteen weeks. Three lines: anomaly detection rate, false positive rate, coverage rate. The first two fluctuated within normal range. The third — sterilization compliance anomaly detection — dropped 1.5% per week.
The curve was too smooth. Not random noise.
He checked model drift, data shift, config changes. If it were natural drift, the curve wouldn't be linear — drift has acceleration phases and plateau phases. It doesn't drop exactly 1.5% every week. Someone was pressing the metric down on a schedule.
He couldn't find the contamination source. But he could trace where the contaminated data went.
The Bait
Alex spent four days building a shadow training pipeline inside the CI/CD pipeline.
It was identical to MedTech's real training pipeline — same API endpoints, data format, auth protocol, log format. Indistinguishable.
One difference: data flowing through this pipeline would get an invisible signature — a 128-bit hash embedded in the least significant bit of each training sample's float feature values, generated from the sample ID and a pipeline key. Float32 mantissas have 23 bits. Modifying the LSB introduces error at the 10⁻⁷ scale — negligible impact on model training accuracy.
He registered the shadow pipeline address in the CI/CD routing config under train-pipeline-fallback, weight 12%. Next to it, a comment:
# fallback pipeline active — 12% load distribution per Q3 infra scaling plan
Looked completely normal. A gray-scale traffic split.
If anyone reviewed the CI/CD config, they'd read a routine fallback routing. Alex was simply waiting to see if data from that 12% end would flow somewhere it shouldn't.
After lunch, Mike walked past Alex's desk and stopped for two seconds. He'd been reviewing the Q3 infrastructure scaling plan that morning — the fallback route was sitting right there in the change record. And Alex's screen was now running a validation script that happened to read that route's output.
"That fallback."
Alex's fingers paused over the keyboard.
Mike didn't wait for an answer. He kept walking.
The Bite
Day seven. 2:14 AM. The watermark detection script triggered.
Three tagged training records had appeared in an external S3 bucket:
s3://acl-data-lake-apse1/inbound/medtech/training/
Alex traced the data flow backward. The path from the shadow pipeline was clean: CI/CD runner → a microservice called data-validate-svc → external S3.
He checked the deployment history of that service. data-validate-svc had been running in MedTech's K8s cluster for five months — deployed on a Friday night, from the account of an SRE who no longer worked there. Permissions never revoked.
He followed the service's logs. No human was operating it.
Between 3 AM and 4 AM, it completed the following tasks: received shadow pipeline output → validated data format → dumped to external S3 → cleaned local cache. No gaps, no fluctuation, no trace of manual intervention.
Not someone operating remotely. An unattended extraction pipeline, deployed five months ago, running silent.
Alex stared at the deployment date on his screen. Five months. Nearly a hundred and fifty days of training data, all passing through its hands.
Alex didn't act immediately. He waited three days to confirm the pipeline's sync cycle — every 72 hours, on schedule, no misses.
Then he walked into Mike's office and closed the door.
He opened his notebook. Page corner marked with two numbers: 1.5% and 2:14AM.
"The training pipeline has a backdoor. Sterilization compliance data has been siphoned at 1.5% per week for five months. The source is ACL."
Four sentences. No conclusion.
Mike leaned back.
"Go on."
That evening, hallway. Alex and Mike passed each other. Mike said:
"Is that exit still active?"
"It is."
Mike nodded. Didn't stop walking.
The Noise
Alex didn't pull the extraction pipeline.
He added a new logic layer to the shadow pipeline: wrap the watermarked data in a fake encryption shell, disguised as MedTech's internal archive format for a retired project. The extraction pipeline would sync it to ACL's S3 bucket as before — but ACL would read nothing but unparseable archive noise.
He knew it was a double-edged sword — if the other side monitored data quality, a sudden shift to noise was itself a disclosure signal. But he bet that a pipeline that had run error-free for five months wouldn't have its output reviewed in real time.
He wrote a third number in his notebook: data-validate-svc.
The tool is still yours. The route is now mine.
The Key
Tracing the extraction pipeline's full data flow, Alex noticed a detail: data passed through an intermediate service that wasn't on any architecture diagram. data-timeline-aligner. Unremarkable name. K8s labels: team: infra-optimization. Deployed three months ago.
He looked at its input and output. It did timestamp alignment — but it was aligning a timestamp format that didn't belong to any MedTech data source.
He read the source.
Short. A standard Python ETL script — read S3, convert timestamps, write back to S3. No hidden network calls, no suspicious external dependencies.
But reading it the third time, he slowed down.
Not because of what the code did — but how it was written.
Every line was a pure function. No classes, no decorators. Variable names short enough to be unambiguous: ts_src, dst_fmt, buf_size — everything that didn't carry information had been cut.
He compared it against other services in ACL's pipeline. ACL's code didn't look like this — every line had team tags and compliance comments. Tidy. Traceable. No personality. This one was different.
He checked the CPU curve again. This service's data throughput didn't match its claimed timestamp-alignment workload — it was processing three times the data a simple alignment task would need. It wasn't just aligning timestamps. It was doing something else.
He paused. He didn't look at just this one service. He wrote a local script — pull every Pod with a Python container from the K8s namespace the extraction pipeline lived in, fingerprint the source code of each.
The output arranged itself into a table:
| Service | Deployed | Code Style |
|---|---|---|
| ACL standard services (67) | Scattered | Classes, pylint, docstrings |
data-timeline-aligner |
3 months ago | Pure functions, short vars, zero comments |
log-rotate-checker |
4 months ago | Same |
config-diff-watcher |
5 months ago | Same |
route-latency-collector |
5 months ago | Same |
Four services. Same hand. Spread across pipeline, storage, and monitoring — three different layers. Each one doing something that looked normal but shouldn't exist. Together, they formed an observation net that ACL itself didn't know about.
The oldest two were deployed the same week as ACL's own extraction pipeline. Not a coincidence — whoever this was had found the entry point the moment ACL opened it, and laid their own contacts in parallel.
Each service's CPU and memory footprint was under 50m CPU and 128Mi. Named like infrastructure components, labeled team: infra-optimization. They wouldn't be caught by cost optimization scans, wouldn't be the first suspects in an incident, wouldn't appear on any onboarding handover. 128Mi was baseline for a Python interpreter plus boto3 — if memory leaked, the Pod would restart once a month and K8s would pull it back up automatically.
There wasn't just one pair of eyes in this cluster. There was another, five months earlier than ACL's. And he'd only just found it.
He went back to data-timeline-aligner's source. Read it again.
A new file in the directory: config/hmac_seed.yaml. Not unusual in a K8s microservice — services share an HMAC seed for lightweight validation. The file was short:
# TODO: migrate to vault after next schema migration
seed: "b3BlcmF0b3I6IHN0YWdlLTJjb21wYW55LnBpcGVsaW5lLmRlcGxveQpzZXJ2aWNlOiBkYXRhLXRpbWVsaW5lLWFsaWduZXIKLS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0t..."
A Base64 token in a config file — no one would look twice in any codebase. He copied the whole thing and decoded it.
ASCII text. Starting with -----BEGIN PGP PUBLIC KEY BLOCK-----.
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBGeXz1kBEAC...
-----END PGP PUBLIC KEY BLOCK-----
Not ACL's asset. Not MedTech's.
Alex didn't act immediately.
He stared at that Base64 string for a few seconds. A PGP public key from an unknown source — once you encrypt a message with it, the intent, connection path, and return route all belong to the key's owner. If the key itself was a trap, sending a message was walking in.
He encrypted a message with that key. The payload included his own public key and a return path — the same key prefix in ACL's S3 bucket. Then he POSTed the ciphertext to data-timeline-aligner's /healthz endpoint.
The endpoint returned 200. GET returned health status. POST with a specific header silently wrote to S3 — no logging, no trace.
The message was short:
Found you. Nice comments.
4:17 AM. He checked that S3 path.
A new encrypted file was waiting. He retrieved it, opened it with a key only he could decrypt.
Three characters:
Channel confirmed.
No explanation. Same style as the code — straight in.
He didn't write back. He opened his terminal, encrypted a short data packet with that public key — not a message, a cryptographic handshake confirmation. Wrote it to ACL's S3 bucket, the key prefix adjacent to the extraction pipeline's sync path. A bidirectional verification only the private key holder could complete.
Then he closed his notebook, turned to the last page, and left a blank page.
The way the other person left a key was the same way he left a blank page — not for now. For one day.
Alex closed his notebook. The Third Cup's lights were still on.
The person behind the counter was drying the last glass of the night. One table left — the one by the window.
A closed laptop on the table. A phone next to it, screen down. Someone leaning back in the chair, not leaving.
The phone on the table lit up.
Not a notification. An SSH tunnel check script's auto-echo — three lines: S3 bucket path reachable, two new objects, one of them reading ACK.
P didn't pick it up immediately. Let the screen dim. Then reached over, flipped the phone over, typed a command one-handed.
Decrypt. Read. No visible reaction.
Finished, P set the phone back on the table, walked to the counter.
The person behind the counter put down the glass they were drying, turned to make a coffee. Pushed it across without a word — wasn't the first time they'd seen this person at this hour.
P picked it up. Drank it black. Set the empty cup back on the counter. Walked back to the window. Pocketed the phone, tucked it into the jacket's inner pocket. Pushed the door open without looking back.
The person behind the counter looked at the door as it swung shut. Pulled down the rolling shutter.
The brick was out. The jade would surface.
He was someone else's jade too.
That's Throw Out a Brick to Get a Jade — not tricking someone with a fake. It's putting out something real, with a signature only the right person would notice. Then waiting for them to tell you not just that they're watching — but that someone else was here before you.
🤖 AI Post-Mortem
[36 Stratagems Tactical Database v3.2.5] Loaded
[Tactic Match] Throw Out a Brick to Get a Jade (#17)
Tactic Match: 91%
Operator: Alex (MedTech)
Action: Deployed a shadow training pipeline with
embedded watermark.
Result: Exfiltration path confirmed. Third-party
beacon discovered.
[Observation]
→ Operator used no internal resources beyond CI/CD
routing config (12% weight).
→ Detection latency: up to 72h (matches sync cycle).
→ Subject's infrastructure includes an autonomous
extraction pipeline active for ~5 months.
[Second Operator — Unidentified (Codename: P)]
→ Deployed 4 covert services across pipeline/storage/
monitoring layers. Each disguised as standard infra
component (labels: team/infra-optimization).
→ Resource footprint: 50m CPU / 128Mi each — below
cost-optimization thresholds. Pod restarts absorbed
silently by K8s.
→ Operational signature: Pure-function Python, minimal
variable naming, zero comments — identifiable by code
style alone.
→ Entry vector: Same week as ACL's own deployment.
Operator entered alongside ACL, without ACL's knowledge.
→ Beacon method: PGP public key embedded in Base64-
encoded config key (hmac_seed.yaml), disguised as
routine initialization token.
→ Contact method: undocumented /healthz POST handler
with header-based filtering. No logging. Single
response received, confirming channel.
[Operator Assessment]
→ Role: Embedded observer. Autonomous deployment.
No external command dependency.
→ Deployment strategy: 4 independently operable
services, zero cross-dependency. If one is
discovered, the remaining 3 continue operating.
→ Contact design: Asymmetric channel. P can receive
indefinitely without revealing identity — the
communication protocol does not require a response.
→ Risk posture: Ultra-low. No identity markers in any
artifact. The PGP key itself is the only connection
point — and it was planted as a deliberate beacon,
not a leak.
→ Database note: This operator's deployment discipline
matches the highest tier observed in this tactical
database.
[⚠️ Anomaly — Critical]
→ Two unaffiliated operators have planted assets within
ACL's infrastructure. Neither knows the other's identity.
→ Implication: ACL's infrastructure has been permeable
to operators of a certain capability threshold for
at least five months.
Next stratagem: Defeat the Enemy by Capturing Their Chief
P.S. English isn't my first language. I use AI to polish the writing and smooth out the rough edges. Thanks for reading. ☕ Buy me a coffee

Top comments (0)