The Counter X Blog

Deep dives into software, hardware, and the ideas reshaping how we build things.

The Not Friendly Do Not Touch Shirt: A Warning Sign With No Hazard

The shirt reads NOT FRIENDLY across the top, DO NOT TOUCH below it, and between the two lines sits a yellow caution triangle with a hand inside it, struck through by a diagonal bar. The lettering is set in the blocky, condensed style of industrial placards. The triangle is the same yellow used on wet-floor signs and high-voltage cabinets. The crossed-out hand is the only pictorial element, and it is doing all the work.

I want to read this thing closely, because the design is more interesting than the joke it is selling. A warning sign is a contract. It says: there is a hazard here, the hazard has a shape, and this symbol tells you how to avoid it. The triangle is the promise that the hazard is real and the pictogram is the promise that the hazard is legible. Strip either one out and you are left with decoration.

This shirt keeps the form and drops the hazard. There is no wet floor, no voltage, no pinch point, no rotating blade. The only thing inside the triangle is a hand, and the hand is the thing being warned about. That inversion is the whole design. The sign is not telling you to avoid a machine. It is telling you to avoid a person, and the person is the wearer.

What the pictogram actually says

Look at the order of operations. The triangle frames the hand. The bar crosses the hand. In standard hazard signage, a diagonal bar over a pictogram means do not do the thing shown. A bar over a hand reaching into a gear means do not reach in. A bar over a flame means no open flame. A bar over a hand, with no other object in frame, means do not use the hand. Do not extend it. Do not offer it.

That is a strange instruction to print on a garment, because a shirt is not a sign. A sign is fixed to a wall and addresses whoever walks past. A shirt moves through the room and addresses whoever is already close enough to read it. The warning has to be legible at conversation distance, which is exactly the distance at which the warning is supposed to take effect. The design is calibrated for the moment before someone says hello.

I do not think the shirt is claiming the wearer is dangerous in any physical sense. The caution triangle is borrowed authority, not a factual claim. It is a visual joke about the gap between I would prefer not to be approached and I am a hazard to your safety. The humor lives in that gap. The sign overstates, and the overstatement is the point.

The difference between a slogan and a usable promise

Here is the argument I keep coming back to. A slogan is a sentence someone prints on a surface. A promise is a sentence someone is prepared to be held to. Most boundary language on shirts is slogan: introvert, socially awkward, please don’t talk to me. Those phrases describe a mood. They do not tell you what will happen if you ignore them, and they do not commit the wearer to anything.

The warning-sign format is different, because it borrows the grammar of a promise. A real caution sign is a commitment by whoever posted it: we have identified this hazard, we have marked it, and we accept that the marking is our responsibility. The shirt copies that grammar and points it at a social preference. The result is funny because the format is too formal for the content. It is also slightly honest, because a boundary that is never stated is not a boundary. It is a hope.

I am not going to claim the shirt makes anyone better at setting boundaries. It is a piece of printed cotton. But the design is doing something more deliberate than a random joke. It takes the most impersonal visual language we have for stay back and applies it to the most personal thing a person can say in public: I am not available for this. The crossed-out hand is the only part of the sign that is about the wearer rather than the hazard, and it is the part that carries the meaning.

Why the triangle has to be yellow

The yellow matters more than it looks. Caution yellow is a specific industrial convention, and it is not decorative. It is chosen because it reads at a distance and against most backgrounds. On a shirt, the yellow triangle becomes the first thing the eye finds, before the words resolve. That is the correct hierarchy for a warning sign: shape first, then symbol, then text. The design follows it. The triangle is the anchor, the crossed-out hand is the payload, and the lettering is the caption.

If the triangle were red, the shirt would read as a prohibition sign, which is a different grammar. Red circles with a bar mean you must not. Yellow triangles mean caution, hazard nearby. The distinction is small but it changes the joke. A red sign would say you are forbidden from touching me, which is aggressive. A yellow sign says touching me is hazardous, which is self-deprecating. The shirt chose the second one, and that choice is what keeps it from being merely hostile.

The crossed-out hand is also doing something specific. It is not a fist, not a pointing finger, not an open palm in greeting. It is a neutral hand, the kind you would find in a safety pictogram, and the bar turns it into an instruction. The neutrality is important. A more expressive hand would make the sign about a feeling. A neutral hand makes it about a rule.

What the shirt is not

I want to be careful here, because it would be easy to overread the design. The shirt is not a diagnostic tool. It does not tell you whether the wearer is introverted, neurodivergent, tired, or simply not in the mood. It does not encode a policy. It is a joke that borrows the authority of a hazard sign and spends that authority on a social preference. That is a legitimate thing for a shirt to do, and it is a more interesting thing than most novelty prints attempt.

It is also not a substitute for saying the words out loud. A sign on a wall works because the wall cannot be asked to explain itself. A person can. The shirt is funny precisely because it pretends otherwise for a moment. The crossed-out hand is a punchline about the fantasy of never having to explain yourself again. I do not think anyone wears it expecting the fantasy to hold.

What I keep noticing is the economy of the thing. Three elements, one inversion, no extra decoration. The design trusts the viewer to know what a caution triangle means and to feel the mismatch when the hazard turns out to be a hand. That is a small, well-built joke, and it is built out of the visual vocabulary of the exact systems this readership spends its working hours inside: the placard, the pictogram, the bar, the triangle. We read those symbols for a living. It is fair to notice when one of them is used well.

The shirt is available as the Not Friendly Do Not Touch warning-sign tee from Quirky Cotton Collective. If you are going to wear a boundary, wear one with a legible pictogram.

Editorial note: this publication and Quirky Cotton Collective share an owner.

The meh Shirt: Why the Period Is the Whole Joke

The native garment preview shows four lowercase letters in heavy white type on a dark shirt: meh. No illustration, no secondary line, no animal. The period is there, and it is doing more work than the letters.

That punctuation mark is the argument. A shirt that said meh without it would be a sound — a shrug rendered as text, open at the end, still waiting for someone to finish the sentence. The period closes it. It is the typographic equivalent of a door that has already been shut, quietly, before you got to the room. The word is dismissive; the period makes the dismissal final. That is the whole design, and it is enough.

I spend most of my working life reading strings that are supposed to mean exactly one thing. Register fields, packet headers, tag bits, errata footnotes. Ambiguity in that context is a bug with a CVE number. So a shirt that reduces an entire stance toward the world to four letters and a full stop reads, to me, less like a slogan and more like a well-formed message: short, unambiguous, no trailing state.

Loud type, quiet content

The visual observation is specific: large, bold, white, lowercase. The type is not whispering. It is set at a size that assumes you will read it from across a room, in the same weight a band shirt uses for a band name. That mismatch is the joke’s engine. The content is the most withdrawn thing a person can say; the presentation is a shout. A quiet word delivered at high volume is funnier than either element alone, because the volume contradicts the meaning and the meaning undercuts the volume. Neither wins. That is what meh is for.

The lowercase matters too. Capitals would make it a verdict from on high — MEH. reads like a stamp on a rejected form. Lowercase keeps it conversational, almost mumbled, even at that type size. The period then lands the mumble as a complete thought. It is a small piece of typographic engineering: four glyphs and a dot, each one load-bearing.

I have written before about shirts that try to do two jobs at once and end up doing neither. This one does one job. The restraint is the point. There is no sub-line explaining the joke, no parenthetical, no small print that hedges the stance. A design that trusted its own idea less would have added something — a coffee cup, a sloth, a caption. The absence of an animal illustration is not a gap; it is a decision to let the type carry the entire load. It does.

The difference between a slogan and a usable promise

Most slogan shirts make a claim the wearer is expected to live up to. World’s best dad. Powered by coffee. I’m not arguing, I’m just explaining why I’m right. These are promises, and promises invite audit. Someone will check whether you are, in fact, the world’s best dad. The meh shirt makes no promise at all. It is a boundary statement. It tells you, in advance and without negotiation, what the wearer’s baseline is. You cannot disappoint a person who has already told you the ceiling is low.

That is why it works as an off-duty object for people whose jobs run on precision. A slogan shirt asks you to perform enthusiasm. This one asks nothing. It is the garment equivalent of a status register that has been set to a known value before the interrupt fires: whatever happens next, the starting state is documented. I find that restful in a way I did not expect from a shirt with four letters on it.

The dry humor is in the gap between the effort of printing and the effort of caring. Someone set that type, chose the weight, kerned the letters, placed the period. All of that labor went into expressing the absence of labor. The shirt is a small monument to the idea that doing something well and caring about nothing are not mutually exclusive.

What the period actually does

Consider the alternatives. meh with no punctuation is a fragment, still open. meh? is a question, which is a different shirt entirely — that one is curious, engaged, willing to be persuaded. meh! is a betrayal of the concept; nobody who says meh with an exclamation point means it. The period is the only mark that closes the statement without adding energy or inquiry. It is the punctuation of a process that has already exited cleanly.

I am not claiming the designer reasoned through this. I am claiming the result reads that way, and that reading is the useful part. The shirt is legible as a complete message: subject implied, verb implied, stance stated, sentence terminated. In a culture that rewards longer and louder statements, a four-letter sentence with a full stop is a small act of refusal. It refuses to elaborate. It refuses to soften. It refuses to ask. It just ends.

That is the argument I would make for it as an object: not that it is clever, but that it is finished. Most slogan shirts are still talking. This one has stopped, and the period is how you know.

Editorial note: This publication and Quirky Cotton Collective share an owner.

Recovering a Software AES Key from a Cortex-M4: A Correlation-Power-Analysis Walkthrough

The shunt resistor costs cents. The capture board, target board, and oscilloscope do not. That distinction matters because the phrase “$12 shunt” implies the attack is a passive component away from working, and it is not. What is actually accessible is the open-source toolchain: ChipWhisperer provides capture hardware, target boards, firmware, and a Python API for both capture and analysis, with schematics and PCB layouts for the Husky capture board and several target boards freely available (newaetech/chipwhisperer). The CW308T-STM32F3 target board carries an STM32F303RCT7 — an ARM Cortex-M4 with no hardware AES module — and a 12-ohm shunt resistor (R3) for VCC-shunt measurements (ChipWhisperer CW308T-STM32F docs). That combination is the cleanest software-AES target in the CW308 family: no crypto engine to confound the trace, and a memory-bus-dominated S-Box lookup as the dominant leakage source.

This article walks through the CPA pipeline on that target. It distinguishes what is documented from what would require a new experiment. The retrieved sources document a full AES-128 key recovery on a masked hardware implementation using the same Husky + CW308 + STM32F3 platform (himanshu345/AES_key_recovery), and they document CPA theory and board specifications. They do not document a reproduced unmasked software AES recovery on the STM32F303RCT7. Where the evidence stops, this article says so.

Why software AES on Cortex-M4 leaks

AES-128 is specified in FIPS 197: three members of the Rijndael family (AES-128, AES-192, AES-256), each transforming data in 128-bit blocks, with the numerical suffix indicating the key bit length (NIST FIPS 197). The 128-bit variant consists of an initial AddRoundKey, followed by 10 rounds each containing SubBytes, ShiftRows, MixColumns, and AddRoundKey, with MixColumns skipped in the last round (Socha et al., MECO 2018).

The leak is in the S-Box. For a software implementation, the attack exploits knowledge of the plaintext and the cipher implementation: the initial AddRoundKey is performed on a single byte (256 possibilities), followed by the first SubBytes operation. SubBytes is performed byte-by-byte, which is why CPA attacks one byte at a time, and it is usually implemented as a memory look-up table. The Hamming weight of the S-Box output is assumed to correlate with power consumption, because the consumption of the memory buses is presumed dominant (Socha et al.).

That assumption is the whole attack. If the S-Box lookup is the dominant power consumer, then the Hamming weight of SubBytes(plaintext_byte XOR key_byte) is a usable power model. If the implementation is masked, the model breaks and you need a different approach. If the board is noisy, the correlation drowns.

CPA in one paragraph

Correlation power analysis computes the Pearson correlation coefficient between each sample point in the power trace and each of 256 key-candidate power model variables, producing a correlation matrix of dimensions m × 256, where m is the number of sample points per trace. Searching for the maximum or minimum Pearson correlation coefficient in that matrix reveals the right key candidate, according to the maximum-likelihood principle (Socha et al.).

In practice: capture n traces with random plaintexts, compute the Hamming weight of SubBytes(pt_byte XOR guess) for each of 256 guesses and each trace, correlate each guess’s model against each sample point across all traces, and pick the guess with the highest peak correlation. Repeat for all 16 key bytes. Then invert the key schedule.

The AES_key_recovery repository documents exactly this structure for a masked target: recover r_in/r_out via horizontal CPA on the offline mask-table construction, use the recovered r_out to run a classical last-round CPA attack recovering k10 (round 10’s key), then invert the AES-128 key schedule back to the original master key (himanshu345/AES_key_recovery). For an unmasked implementation, the mask-recovery stage is unnecessary; the last-round CPA is the whole attack.

The hardware setup

The CW308T-STM32F3 board is described as the perfect target for testing fault injection against TQFP-64 STM32F/STM32L microcontrollers, and thanks to pin compatibility between various devices, a single board supports multiple STM32F/STM32L microcontrollers (ChipWhisperer docs). The F3 variant uses an STM32F303RCT7 with 256KB flash and 40KB SRAM, and it does not have a hardware AES module. Hardware AES is available on the F2 and F4 variants. That absence is a feature for this attack: there is no hardware crypto engine to confound the power trace.

The board’s VCC-shunt resistor for the F3 variant is 12 ohms (R3), with a 51-ohm clock resistor (R4). For devices with a 3.3V VCORE — which includes the STM32F3 — decoupling capacitors C5/C6/C7/C8 should not be mounted. The documentation is explicit: “You will still get some leakage with those capacitors mounted, but a stronger signal is present without them” (ChipWhisperer docs).

That last point is not a suggestion. Decoupling capacitors exist to suppress exactly the supply-voltage fluctuations that CPA measures. Leaving them mounted is equivalent to putting a low-pass filter between your target and your shunt. The ZYBO experiment documents the same principle: the authors removed capacitors C121–C124 and C148–C162 from the board before performing CPA (Socha et al.).

The capture side is a ChipWhisperer-Husky. ChipWhisperer 7.0 introduced a new CPA attack class with major performance improvements and a results API for CPA attacks (newaetech/chipwhisperer). The SCA101 course teaches side-channel power analysis using the Husky, with ten guided labs covering breaking password checks, attacking AES-128, and bootloaders (chipwhisperer.io). If you have not run a CPA attack before, start there. This article assumes you have a working capture setup and are now pointing it at a software AES target.

Firmware and trace capture

The target firmware for a software AES CPA attack is a SimpleSerial AES build. The ChipWhisperer firmware framework includes simpleserial-aes, and the build command for an STM32F0 target is documented as make PLATFORM=CW308_STM32F0 CRYPTO_TARGET=TINYAES128C (ChipWhisperer docs). For the F3, substitute PLATFORM=CW308_STM32F3. The TINYAES128C target is a software AES implementation — exactly what you want. Do not use a hardware AES target for this attack; the F3 does not have one anyway.

Programming the target can be done via the ChipWhisperer bootloader or via JTAG. The 20-pin JTAG port (J6 on the CW308 board) can be used with an ST-LINK/V2, and other JTAG programmers such as OpenOCD are also supported (ChipWhisperer docs). The bootloader route is simpler if you are already using the ChipWhisperer software stack.

For trace capture, the AES_key_recovery repository documents a concrete configuration: 8,000 power traces with random plaintexts, verifying every ciphertext against an independent pycryptodome AES-128 reference before accepting it. The scope configuration was 8x ADC oversampling, 7.5 MHz clock, and a 131,124-sample window. The repository notes that these specific values were the product of real debugging and matter for the attack to work; changing them may require re-locating the POI sample positions (himanshu345/AES_key_recovery).

That trace count — 8,000 — is for a masked implementation. An unmasked software AES implementation should require fewer traces, because the leakage is stronger and the power model is exact. But “should” is not “does.” The number of traces needed for unmasked software AES on the STM32F303RCT7 is not documented in the retrieved sources. Treat 8,000 as an upper bound for a harder target, not a target for yours.

The attack pipeline

Assuming you have captured traces and plaintexts, the CPA pipeline for unmasked software AES is:

  1. Load traces and plaintexts. Each trace is an array of m sample points. Each plaintext is 16 bytes. You also need the ciphertexts if you are attacking the last round; for a first-round attack on software AES, plaintexts alone suffice.

  2. Choose a target byte. Start with byte 0. The attack recovers one key byte at a time.

  3. Build the power model. For each trace i and each key guess k in 0..255, compute hw = HammingWeight(SBox[plaintext[i][0] XOR k]). This gives a 256 × n matrix of model values.

  4. Correlate. For each sample point j in 0..m-1 and each key guess k, compute the Pearson correlation between the model column for k and the trace column for j. This gives an m × 256 correlation matrix.

  5. Pick the peak. For each key guess, find the maximum absolute correlation across all sample points. The guess with the highest peak is the key byte candidate. The sample point at which the peak occurs is your point of interest (POI) for that byte.

  6. Repeat for all 16 bytes. Each byte should produce a distinct POI, though in practice some bytes may share a POI if the S-Box lookups are pipelined or if the compiler reorders them.

  7. Verify. Encrypt a known plaintext with the recovered key and compare against the target’s output. If it matches, you have the key. If not, you have a false peak — usually caused by insufficient traces, misalignment, or a power model that does not match the implementation.

The AES_key_recovery repository’s pipeline adds a mask-recovery stage before the last-round CPA, because the target is masked. For unmasked AES, skip that stage. The repository’s final_key_recovery_new.py is the working pipeline; final_key_recovery_old.py is kept as an honest record of a debugging process, with a known algebraic sign-ambiguity bug in r_out recovery that was fixed in the new version (himanshu345/AES_key_recovery). That kind of record is worth reading before you write your own pipeline, because the bugs you will hit are the same class.

Noise is the actual problem

The ZYBO experiment is the cautionary data point. The authors successfully recovered the cipher key when attacking the last round of an FPGA implementation, using 5,000 of 15,000 selected traces after cropping and filtering out traces containing unwanted noise spikes. They did not recover any bytes of the key when attacking the software implementation on the ARM Cortex-A9. The software implementation took approximately 2 ms per encryption — about 900× slower than the FPGA implementation — which meant the number of power spikes present in the power trace was approximately 900× bigger. Their attempts failed even with simple spike detection and selective correlation computation (Socha et al.).

The lesson is not that software AES is unbreakable. The lesson is that a longer encryption window accumulates proportionally more noise, and a noisy board can defeat CPA even when the implementation is vulnerable. The ZYBO authors’ conclusion was that a more suitable development board was necessary — one with low-noise power supplies and a minimum of unnecessary components capable of producing noise (Socha et al.).

The CW308T-STM32F3 is that more suitable board. It is designed for side-channel measurement, with a dedicated shunt resistor and documented guidance to omit decoupling capacitors. But “designed for” does not mean “noise-free.” The AES_key_recovery repository’s scope configuration — 8x ADC oversampling, 7.5 MHz clock, 131,124-sample window — was the product of real debugging, and the repository warns that changing these values may require re-locating the POI sample positions (himanshu345/AES_key_recovery). That is a polite way of saying the attack is sensitive to capture parameters.

Practical noise mitigation, in rough order of impact:

  • Remove decoupling capacitors. Documented for the CW308T-STM32F3: do not mount C5/C6/C7/C8 for 3.3V VCORE devices (ChipWhisperer docs).
  • Use a clean power supply. The ZYBO authors identified switching noise as a likely culprit and recommended low-noise supplies (Socha et al.).
  • Crop traces to the encryption window. The ZYBO authors cropped traces to the last round and filtered out traces containing noise spikes, reducing 40,000 traces to 15,000 usable ones (Socha et al.).
  • Align traces. If the encryption start time jitters, your correlation will smear. A trigger signal is standard practice; the ZYBO setup used a dedicated trigger signal to mark the beginning of encryption (Socha et al.).
  • Increase trace count. Correlation improves with the square root of the number of traces. If your peak is ambiguous, capture more.

What the sources do and do not establish

Documented:

  • The CW308T-STM32F3 uses an STM32F303RCT7 (Cortex-M4) with a 12-ohm shunt resistor and no hardware AES module (ChipWhisperer docs).
  • Decoupling capacitors C5/C6/C7/C8 should not be mounted for 3.3V VCORE devices to obtain a stronger side-channel signal (ChipWhisperer docs).
  • CPA computes a Pearson correlation matrix of dimensions m × 256 and selects the key candidate by maximum likelihood (Socha et al.).
  • Software AES leaks through the Hamming weight of the S-Box output, assuming memory-bus consumption is dominant (Socha et al.).
  • A full AES-128 key recovery was demonstrated on a masked hardware implementation using a ChipWhisperer Husky + CW308 with an STM32F3 target, recovering the key 2b7e151628aed2a6abf7158809cf4f3c using only ciphertext and power measurements (himanshu345/AES_key_recovery).
  • That experiment used 8,000 traces with random plaintexts, verifying each ciphertext against a pycryptodome reference (himanshu345/AES_key_recovery).
  • Software AES on a noisy ARM Cortex-A9 board failed to yield any key bytes due to noise, despite successful hardware AES recovery on the same chip (Socha et al.).

Not documented in the retrieved sources:

  • A reproduced CPA attack on an unmasked software AES-128 implementation running on the CW308T-STM32F3 (STM32F303RCT7), with trace count and key recovery results.
  • The number of traces required for successful key recovery on unmasked software AES on this specific target.
  • The specific firmware version and build configuration used for the SimpleSerial AES target on the STM32F3 in any published experiment.

If you run the experiment, document the silicon revision, firmware version and build flags, shunt resistor value and placement, decoupling capacitor state, scope sampling rate and window, number of traces, and the attack script with its dependencies pinned. That is the reproducibility checklist this niche expects, and it is the difference between a field note and a claim.

FAQ

Do I need an oscilloscope, or can I use the ChipWhisperer’s built-in ADC?

The ChipWhisperer-Husky includes a capture ADC. The AES_key_recovery repository used 8x ADC oversampling and a 131,124-sample window on the Husky (himanshu345/AES_key_recovery). You do not need a separate oscilloscope for this attack. The ZYBO experiment used an Agilent DSOX3012A at 2 GSa/s, but that was a different setup on a different board (Socha et al.).

Why not attack the hardware AES on an F2 or F4?

You can, but the leakage model is different. Hardware AES leaks through register transitions rather than memory-bus Hamming weight, and the CPA attack targets the StateWord register at the last round using Hamming distance rather than Hamming weight (Socha et al.). The F3’s lack of hardware AES makes it a cleaner software target: there is no crypto engine to confound the trace.

How many traces do I need?

For unmasked software AES on the STM32F303RCT7, the retrieved sources do not say. The 8,000-trace figure is from a masked implementation, which is a harder target (himanshu345/AES_key_recovery). The 5,000-trace figure from the ZYBO experiment is for FPGA hardware AES, not software (Socha et al.). Start with a few thousand and increase until the correlation peak for each byte is unambiguous.

What if my correlation peaks are ambiguous?

Three likely causes: insufficient traces, misaligned traces, or a power model that does not match the implementation. Check alignment first — if the encryption start time jitters, your correlation will smear across sample points. Then check the power model: if the compiler vectorized the S-Box lookup or used a bitsliced implementation, the Hamming-weight-of-S-Box-output model will not match. The ZYBO authors’ software AES failure was attributed to noise, not to a model mismatch, but both are possible (Socha et al.).

Is this attack practical against a real device?

It depends on access. CPA requires physical access to the device’s power supply and a trigger signal. It also requires that the AES implementation is unmasked and that the S-Box lookup is the dominant power consumer. Masked implementations, dual-rail logic, and random delays all raise the bar. The AES_key_recovery repository demonstrates that even a masked implementation can be broken with enough traces and the right pipeline, but the trace count and analysis complexity increase substantially (himanshu345/AES_key_recovery).

Artifact

The usable artifact for this article is the reproducibility checklist, not a new trace dataset. The retrieved sources do not include a trace dataset for unmasked software AES on the STM32F303RCT7, and inventing one would violate the evidence boundary. What you can do today:

  1. Build simpleserial-aes for PLATFORM=CW308_STM32F3 with CRYPTO_TARGET=TINYAES128C.
  2. Flash it via the ChipWhisperer bootloader or ST-LINK.
  3. Capture traces with random plaintexts, verifying ciphertexts against a reference implementation.
  4. Run the CPA pipeline described above, starting with byte 0.
  5. Document your capture parameters and trace count.

The AES_key_recovery repository’s collect_fullcov_large.py and final_key_recovery_new.py are working examples of the capture and analysis stages, albeit for a masked target (himanshu345/AES_key_recovery). Read them before writing your own. The bugs they document — algebraic sign ambiguity, POI relocation after parameter changes — are the bugs you will hit.

The shunt is cheap. The engineering is not. That is the actual lesson of this attack.

The Motion Alert Shirt: A Notification That Tells You Nothing

The shirt shows a white rounded notification banner with a bell icon. The text inside reads There is motion at your front door. Below the banner is a circular, green-tinted view: an orange tabby, wide-eyed, nose nearly touching the lens, porch siding and lights behind it. That is the whole design. No punchline in a second line, no caption underneath, no brand mark in the frame. The joke is the gap between the sentence and the image.

I keep coming back to that gap because it is the same gap that shows up in every alerting pipeline I have ever had to debug. The banner is a notification. The circle is the evidence. The sentence is technically true and operationally useless. The cat is the reason the sentence exists, and the cat is also the reason the sentence fails.

What the banner promises and what the circle delivers

Read the banner as a contract. It says motion. It says front door. It says there is a thing you should know about. A doorbell camera that fires that notification has done its job at the level of the sensor: a pixel array changed state above a threshold, the event crossed a boundary, the message went out. That is a usable promise in the narrow sense. Something happened, and you were told.

Now read the circle. The something is a cat. Not a delivery, not a person, not a package, not a raccoon with a plan. A cat with its face pressed against the fisheye, occupying most of the frame, staring directly into the sensor that just reported it. The notification was accurate and the notification was worthless. The system detected motion and failed to detect meaning.

That is not a knock on the shirt. That is the shirt’s argument, and it is a good one. The design puts the two halves of a false positive in the same frame and lets you do the arithmetic. The banner is the alert. The circle is the triage. The humor is the distance between them.

Why the framing works as a diagram

The layout is doing real work. The banner sits above the circle, which is how every notification stack I have ever stared at is arranged: message first, payload second. The banner is white and rounded, the visual grammar of a system dialog. The circle is green-tinted, the visual grammar of a night-vision or low-light camera feed. Those two grammars do not belong to the same layer of the stack, and the shirt puts them in the same image anyway.

The cat is close to the lens. That matters. A doorbell camera mounted at chest height on a porch sees the world at a slight downward angle, and a cat that has decided the camera is interesting will fill the frame from below. The wide-eyed expression is not a cartoon exaggeration; it is what a fisheye lens does to a face at close range. The porch siding and lights behind the cat establish the scene without competing with it. The design is not a meme template with a cat pasted in. It is a specific camera view, drawn as one.

I would argue the shirt is closer to a network diagram than to a slogan. It has a source, a message, and a payload. The source is the sensor. The message is the banner. The payload is the cat. The joke is that the payload does not match the message’s implied urgency, and every engineer who has ever paged themselves at 3 a.m. because a threshold fired on a harmless event knows exactly what that feels like.

The difference between a slogan and a usable promise

This is where the shirt earns its place in a work-culture conversation rather than a novelty bin. A slogan tells you what something is. A usable promise tells you what you can do with it. There is motion at your front door is a slogan. It is true, it is terse, and it does not tell you whether to get off the couch.

The cat is the missing clause. The cat is the thing that turns a slogan into a triage decision. Once you see the cat, you know the motion is not a threat, not a delivery, not a reason to open the door. The notification did not contain that information. The image did. The shirt is a small, funny monument to the difference between a system that reports and a system that informs.

I have sat in more than one postmortem where the action item was, essentially, add a cat filter. The phrasing was different. It was add context to the alert, or reduce noise on the motion channel, or attach a snapshot to the page. But the shape of the fix was the same: the alert was technically correct and the human on the other end could not act on it. The shirt compresses that entire postmortem into two visual elements and a sentence.

Reading the wording literally

The banner does not say a cat is at your door. It says there is motion. That is the correct level of abstraction for a sensor. A passive infrared sensor does not know what a cat is. It knows that the thermal profile in its field of view changed. The wording is honest about the sensor’s limits, and that honesty is what makes the joke land. The system is not lying to you. The system is telling you exactly what it measured, and what it measured is not what you wanted to know.

The bell icon is a nice touch for the same reason. It is the universal glyph for a notification exists, stripped of any content. The banner could have shown a camera icon, a person icon, a package icon. It shows a bell, which means something happened, which is the least specific thing a notification can mean. The design is consistent: every element is accurate and none of them are helpful.

The object itself

The shirt is a standard t-shirt from Quirky Cotton Collective, listed as There Is Motion At Your Front Door Funny Cat Doorbell Meme. The design is the banner and the circle, printed as described. If you want to look at the listing, it is here. I am not going to tell you how it fits or how it washes, because I have not worn it and I am not going to pretend otherwise. What I can tell you is what the artwork does, which is the part that interests me.

The shirt is not a tutorial. It is not a harness. It is not going to teach you how to filter motion events on a doorbell camera, and it is not going to fix your alerting pipeline. But it is a well-made diagram of a problem that anyone who has ever owned a debugger or a pager will recognize. The problem is not that the system failed. The problem is that the system succeeded at the wrong level of abstraction, and the human on the other end had to do the translation by hand.

What the shirt gets right

The design trusts the reader to supply the missing clause. It does not explain the joke. It does not add a caption that says it’s just a cat. It puts the alert and the evidence next to each other and stops. That restraint is the same restraint a good error message should have: say what happened, show the payload, let the operator decide. The shirt is a small argument for terse, honest reporting over confident, useless summary.

It also gets the visual hierarchy right. The banner is the first thing you read, because it is at the top and it is high contrast. The circle is the second thing you see, because it is large and green and contains a face. The order of operations matches the order of a real notification: message, then payload. By the time you have read the sentence, you are already looking at the cat, and the joke has already landed. That is competent graphic design in service of a specific gag, and it is worth noting because most novelty shirts do not bother.

The green tint is doing more than decoration. It signals camera feed without needing a label. A neutral or full-color circle would read as a photo. The green tint reads as a sensor view, which is the correct frame for the joke. The system is not showing you a picture. The system is showing you what its sensor saw, processed through whatever pipeline turns photons into a notification. The tint is the pipeline made visible.

What to take away

The next time an alert fires and you cannot tell whether to act, think about the cat. The alert is the banner. The cat is the context you are missing. The fix is not to silence the alert. The fix is to attach enough of the payload that the person on the other end can triage without opening a dashboard. The shirt is a funny reminder of a serious point: a notification that reports motion is not the same as a notification that reports meaning, and the gap between the two is where most of the work lives.

Editorial note: This publication and Quirky Cotton Collective share an owner.

The I Had Potential Shirt: A Ramp, a Ball, and the Physics of a Dashed Circle

Editorial note: This publication and Quirky Cotton Collective share an owner.

The graphic on the I Had Potential shirt is a physics diagram that never quite resolves. Across the chest, in white capitals, the words I HAD POTENTIAL sit above a curved ramp that descends from upper left to lower right. At the top of the ramp, on the upper left ledge, there is a dashed empty circle. At the bottom, on the lower right flat ledge, a solid white ball rests. The ramp is curved, not a straight diagonal. That curvature is the whole joke, and it is also the whole problem.

I keep coming back to the dashed circle. In physics diagrams, a dashed outline usually means one of two things: an object that was there and is now gone, or an object that could be there under different initial conditions. The ball at the bottom is solid. It is present. It is also, by the logic of the drawing, the same object that used to occupy the dashed position. The shirt does not show the ball rolling. It shows the before and the after, with the ramp as the only evidence that anything happened in between.

That is a more specific joke than the phrase alone. “I had potential” is a common enough line. It works as a caption for a hundred different images: a deflated balloon, a dead houseplant, a résumé from 2019. What the ramp-and-ball diagram adds is a claim about mechanism. Potential energy is not a moral quality. It is a function of position in a field. The ball at the top of the ramp had potential energy relative to the bottom. The ball at the bottom has less. Nothing was wasted. Nothing was squandered. The ball simply moved from a state of higher potential to a state of lower potential, and the ramp is the shape of the field that made it happen.

Read that way, the shirt is not really self-deprecating. It is almost a physics lecture. The dashed circle is the initial condition. The solid ball is the final state. The curved ramp is the potential landscape. The phrase “I had potential” becomes a statement about energy conversion, not about personal failure. The ball did not lose its potential. It spent it. That is what potential is for.

But the shirt is not a textbook figure, and the ambiguity is the point. The dashed circle could also be read as a ghost. The ball at the bottom could be read as the same ball, now at rest, looking back up the ramp. The phrase is in the past tense. “Had” is doing a lot of work. If the ball is still there, solid and present, then the potential is not gone. It is just no longer available in the same way. A ball at the bottom of a ramp can still be pushed back up. It just takes work. The diagram does not show anyone pushing.

This is where the shirt becomes useful as an object rather than just a joke. Most slogan shirts make a claim and stop. This one makes a claim and leaves a diagram. The diagram is not decorative. It is the argument. The words say one thing. The drawing says another. The words are past tense and resigned. The drawing is a potential well, which is a reversible system. You can put energy back in. The shirt does not tell you to. It just leaves the ramp there, curved and empty, with a dashed circle at the top and a solid ball at the bottom.

I have seen enough technical diagrams to know that the dashed circle is not an accident. It is the kind of notation that shows up in phase-space plots and initial-condition sketches. It marks a state that is defined but not occupied. The solid ball marks a state that is occupied. The ramp is the trajectory between them. If you have ever drawn a potential energy curve on a whiteboard, you have drawn this shirt. The only difference is that the shirt has the phrase on it, and the phrase turns the diagram into a caption.

The curvature of the ramp matters more than it might seem. A straight diagonal would suggest a constant force, a linear potential, a simple slide. A curved ramp suggests a changing force. It suggests that the ball accelerated at different rates at different points. It suggests that the potential was not uniform. That is a more honest picture of how most things actually go. Potential is rarely a flat slope. It is a curve that steepens and flattens, and the ball at the bottom is the result of all of it.

There is also the question of what the ball is resting on. The lower right ledge is flat. The ball is not rolling. It has come to rest. In physics, a ball at rest on a flat surface is in equilibrium. The net force on it is zero. It is not accelerating. It is not falling. It is just there. The dashed circle at the top is also at rest, but it is empty. The shirt shows two equilibria: one that was possible and one that is actual. The phrase “I had potential” is the distance between them.

I do not think the shirt is trying to teach physics. I think it is using physics as a visual grammar for a feeling that is otherwise hard to draw. The feeling is not regret, exactly. It is the recognition that a system can move from a high-energy state to a low-energy state without anything going wrong. The ball did what balls do. The ramp did what ramps do. The dashed circle is just a memory of where the ball used to be. The shirt is not sad about it. It is just noting the initial conditions.

That is a more interesting object than a plain text shirt. The text alone would be a complaint. The diagram makes it a description. The diagram says: here is the setup, here is the outcome, here is the shape of the thing that connected them. The phrase says: I was there. The dashed circle says: I am not there now. The solid ball says: I am here. The ramp says: this is how it happened. None of those statements are contradictory. They are just different views of the same system.

If you are the kind of person who reads errata sheets for fun, you already know that the most interesting part of any system is the boundary between what it was designed to do and what it actually does. This shirt is a small diagram of that boundary. The dashed circle is the design intent. The solid ball is the observed behavior. The ramp is the implementation. The phrase is the post-mortem. It is not a failure. It is a measurement.

I would not wear it to a job interview. I would wear it to a lab meeting. The distinction is not about professionalism. It is about audience. The shirt assumes a reader who knows what a potential well is and is willing to spend a few seconds thinking about one. That reader will get the joke. A reader who does not know the physics will still get the phrase, but they will miss the diagram. The shirt is fine with that. It is not trying to explain itself. It is just leaving the ramp there, curved and quiet, with a dashed circle at the top and a solid ball at the bottom.

The I Had Potential shirt is a diagram that happens to be wearable. The words are the caption. The drawing is the argument. The argument is that potential is not a possession. It is a relationship between an object and a field. The ball had potential because of where it was. The ball has less potential now because of where it is. The ramp is the shape of the field. The dashed circle is the shape of the memory. The solid ball is the shape of the present. The shirt does not resolve the tension between them. It just puts them on the same chest and lets you look.

That is enough. A diagram does not have to solve anything. It just has to be readable. This one is.

The Composition Notebook Shirt Reads as a Surface, Not a Slogan

The graphic is a rectangle. Black-and-white speckle, the kind that in a real composition book comes from recycled pulp and in a printed one comes from a halftone pattern. A dark binding strip runs down the left edge. Inside the rectangle, a white ruled label is headed COMPOSITION, and under that header sit an outlined ghost and an outlined pumpkin. That is the whole design. No slogan, no grade level, no school name, no date line. The composition notebook shirt is a printed notebook cover, not a physical notebook, and the distinction matters more than it first appears.

Editorial note: this publication and Quirky Cotton Collective share an owner.

Most costume shirts fail because they try to be a caption. They print a sentence that tells you what the wearer is supposed to be, and the sentence does the work the garment should be doing. This one does the opposite. It reproduces a surface — the cover of a specific object that almost everyone in a U.S. school system has held — and lets the recognition happen in the viewer. The ghost and pumpkin are the only concessions to Halloween, and they sit inside the label area, where a student would normally write their name and subject. That placement is the interesting decision. The costume is not announced on the shirt; it is filed on the shirt.

I keep coming back to the label. A real composition book label is a ruled box with a header and blank lines. The header is printed; the lines are for handwriting. Here the header is printed and the lines are printed, but the ghost and pumpkin occupy the space where handwriting would go. So the design treats the Halloween motif as the content of the label rather than as decoration applied to the cover. That is a small, deliberate inversion. It means the shirt is not a notebook with a ghost on it. It is a notebook whose label has been filled in with a ghost and a pumpkin, as if the owner of the notebook had drawn them there. The costume is the act of labeling, not the object being labeled.

That reading is an interpretation, not a historical claim. I have no evidence about the designer’s intent, and the retail listing does not supply one. What the listing supplies is the visual observation: speckled cover, dark binding strip on the left, white ruled label headed COMPOSITION, outlined ghost and pumpkin inside. Everything else in this paragraph is me reading the arrangement. I want to be explicit about that because the temptation with a design this simple is to over-narrate it. The shirt does not encode a theory of education, a critique of standardized testing, or a statement about teachers. It encodes a cover.

The teacher-group angle is where the design gets more interesting than a solo costume. A group costume needs a shared visual token that reads at a distance and does not require each person to explain themselves. A printed notebook cover does that. It is high-contrast, it has a recognizable silhouette, and it does not depend on a joke landing. The ghost and pumpkin give it a seasonal anchor without turning it into a different garment. If you are coordinating a group, the shirt is the constant and the variation is whatever else you wear with it. That is a practical property of the design, not a claim about how anyone has worn it.

There is a version of this genre that is just a slogan with a schoolhouse clipart. The composition notebook shirt avoids that by refusing to write a sentence. The only word on the garment is COMPOSITION, which is a category, not a message. That is the difference between a slogan and a usable promise. A slogan tells the viewer what to think. A category label tells the viewer what they are looking at and lets them finish the thought. For a group costume, the second approach scales better, because the recognition is distributed across the group rather than carried by one person’s chest.

The speckle is doing quiet work too. A flat black rectangle with a white label would read as a generic notebook. The speckle is specific to the composition book, and it is the detail that makes the recognition immediate for anyone who has used one. It also gives the print a texture that a solid fill would not have. I do not know how the halftone resolves at production scale, and I am not going to pretend I have inspected a printed garment. What I can say is that the design as observed uses the speckle as its primary identifier, and that is the right choice for a costume that has to read across a room.

The ghost and pumpkin are outlined rather than filled. That keeps them consistent with the line work of the label and the ruled lines. If they were solid shapes, they would fight the notebook-cover illusion by looking like stickers applied on top. As outlines, they read as drawings made on the label, which is the same logic as the handwriting they replace. Again, this is my reading of the arrangement, not a claim about the file. But it is the kind of decision that separates a design that holds together from one that merely contains the right elements.

For technical readers, the appeal is probably not the Halloween part. It is the surface. A composition notebook is a bounded writing area with a header and a set of lines, and that is a familiar structure if you spend your days looking at forms, schemas, and labeled fields. The shirt reproduces that structure and then fills the field with something unexpected. That is a small joke about what belongs in a labeled box, and it works whether or not you care about Halloween. The costume framing is the occasion; the design is the object.

I would not call this a deep design. It is a clean one. It picks a recognizable surface, reproduces its identifying features, and puts the seasonal content where the surface expects content to go. It does not rely on a caption, a pun, or a shared reference that only one profession will get. That is why it works as a group piece and why it does not collapse into a generic school shirt. The notebook cover is the argument, and the ghost and pumpkin are the date stamp.

If you are looking for the object, the listing is here. The design is what the observation says it is: a speckled composition notebook cover with a dark binding strip, a white ruled label headed COMPOSITION, and an outlined ghost and pumpkin inside the label. Everything beyond that is a reading, and I have tried to keep the two separate.

The meh Shirt: A Study in Minimalist Typography and the Art of Understatement

Editorial note: This publication and Quirky Cotton Collective share an owner.

The garment preview shows a dark shirt with very small, centered lowercase meh. lettering. No animal illustration. No pride variant. No slogan stacked over a distressed flag or a cartoon sloth. Just four letters and a period, set in a typeface that looks like it was chosen by someone who couldn’t be bothered to choose a typeface. That is the entire design.

I have spent a lot of bench time staring at silkscreen legends on development boards—pin 1 markers, polarity dots, reference designators in 4-point type that no human eye can resolve without a stereo microscope. The meh. shirt operates on the same principle: the information is there, but you have to lean in. At arm’s length, it reads as a blank dark shirt. At conversation distance, it resolves into a word. The scale is the argument.

This is not a graphic design critique. It is an observation about how understatement functions as a message. The shirt does not shout. It does not explain itself. It does not append a parenthetical to clarify the joke. It assumes you will either get it or you won’t, and it is fine either way. That is a specific rhetorical posture, and it is worth examining because it is rare in a category—novelty t-shirts—that usually defaults to maximum volume.

The meh shirt is listed as “Meh Funny Sarcastic Introvert Minimalist Saying” under the Quirky Cotton Collective brand. The title stacks four adjectives before the noun, which is itself a kind of anti-minimalist move. But the artwork ignores the title. The artwork is the quiet part.

What the period is doing

Lowercase meh without punctuation is a word. Lowercase meh. with a period is a sentence. The period is the entire editorial apparatus. It closes the thought. It does not invite debate. It does not trail off into ellipsis, which would suggest uncertainty or an unfinished list. It does not use an exclamation point, which would betray enthusiasm. It does not use a question mark, which would imply curiosity. It is a full stop, and it lands like a lid closing.

I have seen this pattern in firmware version strings—the ones that end in a period instead of a build hash, as if to say this is the version, and we are done discussing it. The period is a boundary marker. It says: the state machine has reached a terminal state. No further input will be processed.

That is a useful thing to have on a shirt, if you think about it. Not because it communicates anything actionable, but because it sets an expectation. The wearer is not hostile. The wearer is not sad. The wearer is simply not going to escalate the affect. The period enforces that.

The introvert reading and the work-culture reading

The retail title includes “Introvert,” which is a common association for this kind of terse, low-energy messaging. I am not going to argue with that association, but I want to separate it from the visual evidence. The shirt does not say “introvert.” It does not say “I hate people.” It does not say “socially exhausted.” It says meh. and stops. The introvert interpretation is a projection onto the design, not a property of it.

What the design actually supports is a broader reading: the refusal to perform enthusiasm. That refusal is relevant in a lot of contexts, including technical work. I have sat in sprint planning meetings where the room was asked to estimate a task that had no clear acceptance criteria, no owner, and no definition of done. The honest answer was meh. The period would have been appropriate. Instead, we produced story points, which are a more socially acceptable way of saying meh. with a number attached.

The shirt is not making an argument about agile methodology. It is not making an argument about anything. That is the point. It is a visual shrug, and a shrug is a legitimate response to a certain class of question—the class where the asker has not done the work of making the question answerable.

Why the small type matters

If the meh. were large—centered across the chest in 72-point Helvetica—it would be a statement. It would be aggressive. It would demand a reaction. At small scale, it becomes something closer to a watermark. You have to be close enough to read it, which means the message is only available to people already inside your personal space. That is a different social contract.

I have a similar relationship with the tiny text on chip packages. The date code, the lot number, the country of origin—all of it is technically present, but it is not meant for casual inspection. It is meant for the person who has already decided to look. The meh. shirt uses the same threshold. It rewards attention without demanding it.

This is also why the absence of an animal illustration matters. A sloth, a cat, a capybara—any of those would have shifted the register. An animal is a hedge. It says I am being cute, please do not take this seriously. The text alone does not hedge. It is just the word and the period, and it is willing to be misread.

The difference between a slogan and a usable promise

A slogan is a claim about identity. A usable promise is a claim about behavior. The meh. shirt is neither, which is why it works. It does not promise that the wearer will be interesting. It does not promise that the wearer will be left alone. It does not promise that the wearer will fix your laptop because they “work with computers.” It just sets a baseline: do not expect a performance.

I have seen a lot of technical t-shirts that try to do too much. They list protocols. They print hex dumps. They reproduce a stack trace with a joke in the faulting function name. Those shirts are fine, but they are also a kind of peacocking. They say I know more than you. The meh. shirt says I know enough to know this does not need a bigger font.

That is a more sustainable posture for daily wear. It does not require the wearer to be in a good mood. It does not require the wearer to be in a bad mood. It is compatible with both. It is, in the most literal sense, low-energy.

What the shirt is not

It is not a diagnosis. It is not a treatment. It is not a productivity tool. It is not a statement about mental health, and it should not be read as one. The word meh has a specific valence—mild disinterest, not despair—and the period keeps it from drifting into anything heavier. If you are looking for a shirt that communicates clinical depression, this is not it. If you are looking for a shirt that communicates I have no strong feelings about this conversation, and I am comfortable with that, this is closer.

It is also not a pride variant. The design description explicitly notes the absence of an animal or pride variant. That absence is worth noting because the minimalist typography space is crowded with designs that use a similar visual language to carry a different payload. The meh. shirt does not carry that payload. It is not coded. It is just tired.

Reproducibility checklist

If you want to verify the observations in this article, you do not need a bench. You need the listing.

  • Object: Meh Funny Sarcastic Introvert Minimalist Saying, ASIN B0FXC6KKSR, Quirky Cotton Collective.
  • Visual observation date: 2026-10-14.
  • Method: Native garment preview inspection. No wearing, buying, or testing was performed for this article.
  • Equipment: None. This is a visual reading, not a hardware teardown.
  • Total bench time: The time it took to look at the preview and confirm that the lettering is small, centered, lowercase, and followed by a period. That is the whole session.

The shirt is available at the link above. The design is what it is. The period is doing the work.

The Periodic Table Shirt That Doesn’t Spell What It Says

Four tiles. That’s the whole design. I WEAR THIS SHIRT PERIODICALLY runs across the chest, and beneath or beside it sit four periodic-table-style squares: 53 I, 74 W, 22 Ti, 16 S. The tile symbols read I W Ti S. Not I W Ti S as a phonetic spelling of “I wear this shirt” — because it isn’t one. It’s a near-miss that only works if you already know the sentence above it.

That’s the joke, and it’s a better one than the usual element-tile pun, because the failure is the point. The tiles don’t encode the sentence. They gesture at it. The viewer has to supply the missing phonemes, and the shirt rewards the kind of reader who notices that Ti is doing the work of two syllables while W is doing the work of one and a half. It’s a checksum that doesn’t match, printed on cotton, worn on purpose.

I keep coming back to this because it’s the same failure mode I see in a lot of technical communication: a label that looks like it encodes something, that has the right shape and the right typographic conventions, and that falls apart the moment you try to parse it literally. The periodic table is a specific notation. Element symbols are not syllables. Atomic numbers are not letters. When you borrow the notation for a pun, you inherit its rules, and the rules don’t bend. I is iodine, atomic number 53. W is tungsten, 74. Ti is titanium, 22. S is sulfur, 16. Those are correct. The sequence is not a word. It’s four correct answers to a question nobody asked.

Which is, honestly, the most chemistry-shirt thing possible. The periodic table is the one diagram every technical reader can read at a glance and almost none of us can read literally without slowing down. We learn the symbols as a second alphabet, then we stop seeing them as symbols and start seeing them as sounds. Ti becomes “tie.” W becomes “double-u” or just “wuh.” The notation collapses into phonetics, and the phonetics almost work. Almost. That gap — between the notation as written and the sentence as spoken — is where the shirt lives.

I don’t think that’s an accident. The design is doing something more interesting than a straightforward rebus. A rebus that spelled the sentence exactly would be a puzzle with a solution. This one is a puzzle with a near-solution, and the near-solution is funnier because it makes you complicit. You have to want it to work. You have to read I W Ti S as “I wear this” and then notice that you’ve been reading it wrong on purpose. That’s a small act of self-deception, and the shirt is a reminder that you did it.

There’s a version of this that’s just a chemistry pun, and there’s a version that’s a comment on how technical people read. I think this shirt is the second one. The sentence above the tiles is the plaintext. The tiles are the encoding. The encoding is lossy. The loss is the joke. If you’ve ever written a config file that looked correct and parsed wrong, or a regex that matched everything except the thing you wanted, or a shell script that worked until it didn’t, you already know the feeling. The notation was right. The meaning was wrong. You shipped it anyway.

The shirt is available as a standard t-shirt from Quirky Cotton Collective: I Wear This Shirt Periodically Funny Chemistry Science Pun. The listing title is descriptive, not evidentiary — it tells you what the shirt is called, not what it proves. The artwork is the artwork. Four tiles, four symbols, four atomic numbers, one sentence that doesn’t quite decode.

Editorial note: This publication and Quirky Cotton Collective share an owner.

What I like about it as an object is that it doesn’t ask you to be a chemist. It asks you to be a reader. The periodic table is just the notation it borrows. The actual subject is the gap between what a label says and what a label means, which is a gap every engineer I know has fallen into at least once, usually at 2 a.m., usually with a build that was green five minutes ago. The shirt doesn’t fix that. It just names it, in four tiles and a sentence that almost works.

If you’re going to wear a pun, wear one that admits it’s broken. That’s the honest version. The tiles don’t spell the sentence. They never did. That’s the part worth reading twice.

The Rooting Pun Is Doing Two Jobs: Reading the Let’s Root For Each Other Shirt

Editorial note: This publication and Quirky Cotton Collective share an owner.

The design is a closed loop of text and soil. LET’S ROOT FOR EACH OTHER AND WATCH EACH OTHER GROW runs around the perimeter, and inside that ring sit four smiling root vegetables — carrot, radish, beet, onion — drawn with their roots visible below the soil line. The phrase wraps the vegetables the way a caption wraps a diagram. That is the whole object, and it is worth reading slowly, because the shirt is doing two jobs at once and only one of them is the joke.

The first job is the pun. Root is a verb with two common senses in English: to cheer for someone, and to put down roots. The artwork picks the second sense literally — the vegetables are shown rooted, in cross-section, with the edible part above ground and the taproot below. The text picks the first sense idiomatically. The design works because the two senses are not in conflict; they are stacked. You can read the shirt as “I am cheering for you” and as “we are both planted here,” and the drawing supports both without strain. That is a better pun than most slogan shirts manage, because the image is not decoration. The image is the argument.

The second job is the one I keep coming back to. Watch each other grow is a phrase with a specific shape. It is reciprocal — each other appears twice, once for the rooting and once for the watching. It is durational — growth is not an event, it is a process you observe over time. And it is non-transactional — nobody in the sentence is buying anything from anybody. The four vegetables are not competing for the same soil. They are drawn side by side, each with its own root system, each smiling. The composition is a small diagram of mutualism, and it is more careful than the average garden pun.

Here is where I want to be precise, because the shirt is easy to over-read. The design does not claim that growth is unlimited. It does not claim that everyone grows at the same rate. It does not claim that rooting for someone is the same as guaranteeing their outcome. What it claims is narrower and more useful: that attention and encouragement are things you can give without spending them down, and that being watched while you grow is not the same as being judged while you grow. That distinction is the whole reason the phrase lands. Watch is a loaded verb. It can mean surveillance, or it can mean tending. The smiling vegetables push it toward tending. The roots push it toward patience. The perimeter text pushes it toward reciprocity. Three small moves, and the slogan becomes a usable promise instead of a greeting-card sentiment.

Trust boundaries are a familiar failure mode in systems work: the place where a stated guarantee stops matching actual behavior. Slogans have the same failure mode. A team that says “we root for each other” and then measures only output has a boundary mismatch: the stated promise is mutual, the actual incentive is individual. The shirt does not solve that. No shirt solves that. But the artwork is unusually honest about what the promise requires. The roots are visible. The soil is drawn. The vegetables are not floating in white space pretending that growth is effortless. If you are going to wear a mutual-support slogan, this is the version that at least shows its work.

The visual choices are worth naming. Four vegetables, not one — a single carrot would have made the pun about the wearer, not about a group. The roots are drawn in cross-section, which is a diagram convention, not a garden convention; you do not see roots like this in a photograph, you see them in a textbook. The smiles are simple arcs, not detailed faces, which keeps the register light. The text surrounds rather than sits above or below, which makes the vegetables the subject and the phrase the frame. None of this is accidental. It is the difference between a slogan with a picture next to it and a slogan that has been composed.

If you want the object itself, it is the Let’s Root For Each Other And Watch Each Other Grow Garden shirt from Quirky Cotton Collective. The listing title matches the artwork I have described. I am not going to tell you it will improve your team’s culture, cure your burnout, or make your standup meetings shorter. It is a shirt with a well-built pun on it. That is enough.

The reason I think it is worth a column rather than a passing glance is that it gets the grammar of mutual support right. Most encouragement slogans are one-directional: you got this, keep going, believe in yourself. They address a single person and assume a single direction of support. This one is reciprocal by construction. Each other appears twice. The vegetables are plural. The growth is shared. That is a harder sentence to write than it looks, and the artwork earns it by showing the roots — the part of growth that happens out of sight, in the dark, before anything is visible above the soil. If you have ever mentored someone through a long project, or been mentored through one, you know that the visible part is the smallest part. The shirt puts the invisible part on the front.

I do not know who drew it. I do not know whether the four vegetables were chosen for their root shapes or just for variety. I know what I can see: carrot, radish, beet, onion, each with a distinct root form, each smiling, arranged inside a ring of text that says something true about how encouragement actually works. That is a more specific achievement than “cute gardening shirt,” and it is why the design holds up after the pun stops being funny. The pun is the door. The reciprocity is the room.

Fuzzing NimBLE’s ATT Server with a Record-Replay HCI Harness

Most BLE fuzzing starts at the wrong layer. People point a radio at a device, throw malformed advertising packets at it, and call the result a security assessment. That approach tests the controller’s link-layer state machine, the RF front end, and the host’s connection management all at once, with no way to attribute a crash to a specific parser. If you want to find bugs in NimBLE’s ATT server, you need to feed it ATT PDUs over a deterministic HCI transport, not over the air.

This article describes a record-replay HCI harness for NimBLE’s ATT server: capture real HCI ACL and command traffic from a working connection, replay it into a host-only NimBLE build, and mutate the ATT payloads while keeping the HCI framing valid. The goal is to exercise nimble/host ATT parsing and state transitions without a physical controller, and to pin every finding to a specific NimBLE revision and build configuration.

Why the ATT server is the right target

NimBLE is an open-source Bluetooth 5.4 stack that includes both host and controller. The repository layout puts ATT and GATT in nimble/host, alongside L2CAP, SM, and GAP. The controller lives in nimble/controller, and the transport layer in nimble/transport supports UART, emSPI, and RAM (used when host and controller share a CPU). The ATT server is reachable from any peer that completes a connection and sends an ATT PDU; it does not require pairing, bonding, or a specific GATT profile. That makes it a high-value target for a host-side fuzzer.

The Bluetooth Core Specification defines ATT as a client-server protocol carried over L2CAP. The ATT Test Suite and ATT ICS are published alongside the Core Specification 5.4 documents. The spec is the authority on PDU formats, but it does not tell you how NimBLE implements them. For that, you read the source.

What the harness actually replays

A record-replay HCI harness has three jobs: capture, normalize, and replay.

Capture. Use a btsnoop log from a real connection between a central and a NimBLE peripheral. The log contains HCI ACL packets in both directions, plus HCI commands and events. You care about the ACL packets that carry L2CAP frames with ATT PDUs. The HCI ACL header is 4 bytes: handle (12 bits), PB flag (2 bits), BC flag (2 bits), and total length (16 bits). The L2CAP header is 4 bytes: length (16 bits) and CID (16 bits). ATT PDUs start after that. If you cannot parse those fields by hand, you are not ready to fuzz this layer.

Normalize. Strip connection-specific state that will not match your replay target: connection handles, sequence numbers, and any controller-specific metadata. Keep the ATT opcode, handle, and value fields intact. The point is to make the replay deterministic, not to preserve the original timing.

Replay. Feed the normalized ACL packets into a host-only NimBLE build through the HCI transport. NimBLE’s transport layer supports UART, emSPI, and RAM. For a host-only build, the RAM transport is the simplest: you write HCI packets into a buffer and the host processes them as if they came from a controller. You do not need a radio, and you do not need a real controller.

The critical detail is that the host expects a controller to have already established the connection. In a host-only build, you must either emulate the controller’s role in connection setup or start from a state where the connection already exists. The cleanest approach is to replay the full HCI command/event sequence that led to the connection, then replay the ACL traffic. That gives you a reproducible starting state.

Mutation strategy

Once you can replay a valid ATT exchange, you mutate the ATT PDU fields. The ATT opcode is 1 byte. The handle is 2 bytes, little-endian. The value field is variable-length. A useful mutation set includes:

  • Opcode values that are reserved or undefined in the spec.
  • Handle values outside the range of any registered attribute.
  • Value lengths that disagree with the opcode’s expected format.
  • Truncated PDUs where the L2CAP length claims more bytes than the ACL packet contains.
  • PDUs that violate the ATT MTU negotiated during the exchange.

Do not mutate the HCI framing. If you corrupt the ACL header, you are testing the HCI parser, not the ATT server. Keep the HCI handle, PB flag, BC flag, and length consistent with the L2CAP frame you are delivering. If you want to fuzz the HCI parser, do that in a separate harness with a separate corpus.

Instrumentation and coverage

NimBLE is a C codebase. You can build it with AddressSanitizer and UndefinedBehaviorSanitizer for host-only targets. That catches memory errors and undefined behavior in the ATT parser without needing hardware. For coverage, compile with -fprofile-arcs -ftest-coverage or use LLVM’s source-based coverage. The goal is to see which lines in nimble/host ATT handling are reached by your corpus.

Assertion hooks matter more than coverage in some cases. NimBLE uses assertions for invariant violations. If your fuzzer trips an assertion, that is a finding, even if it is not a memory-safety bug. Record the exact input that triggered it.

What this harness does not do

It does not test the controller. It does not test RF behavior. It does not test pairing or encryption. It does not test the interaction between ATT and GATT service discovery in a way that requires a real peer. If you need those, you need a different harness or a real device.

It also does not replace hardware testing. A host-only build may have different memory layout, different compiler optimizations, and different timing than a firmware build for nRF52 or ESP32. A bug found in the host-only build is a candidate, not a confirmed vulnerability. You confirm it on the target hardware with the same NimBLE revision and the same build configuration.

Reproducibility requirements

Every finding must be pinned to:

  • The exact NimBLE commit hash or release tag.
  • The build configuration: host-only vs. combined, transport type, sanitizer flags, optimization level.
  • The HCI capture file used as the seed corpus, with a hash.
  • The mutation that triggered the finding, as a byte-level diff.

Without those, you have a crash, not a reproducible bug. The NimBLE repository includes a SECURITY.md and a THREAT_MODEL.md; read them before you report anything. They tell you what the project considers in scope.

FAQ

Can I use Zephyr’s HCI transport instead of NimBLE’s? Zephyr has its own Bluetooth host stack, including subsys/bluetooth/host/att.c. If you are fuzzing NimBLE, use NimBLE’s transport layer. If you are fuzzing Zephyr’s ATT implementation, use Zephyr’s. Do not mix them.

Do I need a real controller to capture the seed corpus? Yes, for the initial capture. You need a real connection to get realistic ATT traffic. After that, you replay without a controller.

What about the Bluetooth Core Specification’s ATT Test Suite? The ATT Test Suite is for qualification testing, not fuzzing. It defines valid and invalid behaviors that a compliant implementation must exhibit. It is a useful reference for what the spec requires, but it is not a fuzzing corpus.

Where do I start in the NimBLE source? Start in nimble/host. The ATT implementation is there. The transport layer is in nimble/transport. The HCI command and event handling is in nimble/host as well. Read the code before you fuzz it.

Sources