QA practice11 min read

Red-Team the Work, Not the People

Adversarial review for creative and functional QA: testing assumptions instead of the happy path, visual fuzzing, abuse cases, and the cultural boundary that keeps the practice alive.

Most testing is designed to confirm that something works.

You open the form, fill it in the way it was meant to be filled in, submit it, and see the confirmation. You open the page, look at the heading, and it looks like the mockup. You read the post, and it says what it was supposed to say.

That is the happy path.

It is necessary, and it is almost never where the problem is.

Security learned this a long time ago. A vulnerability is rarely found by using an application correctly. It is found by asking what the developer assumed would always be true, and then making that assumption false.

This is the fourth article in this series. Assume Error argued that processes should be designed around the certainty of mistakes. This article is about the technique that actually finds them.

The Question Both Disciplines Start From

A security researcher reading code does not primarily look for bad code. They look for confidence.

They see a line like:

$id = $_GET['id'];

and the thought is not "this is badly written."

The thought is:

"Who decided that this id belongs to the person asking for it?"

Nothing in that line is wrong. Something in it is assumed.

Now take a designer's artboard with a placeholder that reads Product title goes here, or a developer's template with {{ product.title }} inside a fixed-height card.

The equivalent thought is:

"Who decided the title would be forty characters?"

Or take a button labeled Submit, wired to a handler that creates an order.

"Who decided Submit would only ever run once?"

It is the same mental discipline pointed at different consequences. One ends in a data breach and the other ends in a layout that collapses on a real product name, but both were produced by the same thing: a belief about the input that was never written down and never tested.

This gives us the question worth building a review practice around.

Good security testing and good QA begin with the same question: what are we assuming will always be true?

And then the second half, which is the part that requires deliberate effort:

Systematically make those assumptions false.

Functional QA: Break the Path, Not the Button

Traditional functional QA asks whether the form works.

Adversarial functional QA asks a different question:

"In how many ways can I break this flow and still get the system to do something wrong?"

Take a checkout. The expected sequence is clean:

Cart → Checkout → Payment → Confirmation

Testing the happy path means walking that line. Testing assumptions means attacking the line itself.

  • What happens if I add the product twice, very fast?
  • What happens if I use the browser's Back button?
  • What happens if I open two tabs?
  • What happens if the price changes while my cart is open?
  • What happens if I submit the form without completing the previous step?
  • What happens if I modify a parameter in the request?
  • What happens if I lose connection immediately after clicking?
  • What happens if I double-click Place Order?
  • What happens if my session expires mid-flow?
  • What happens if my permissions are not the ones the flow expects?

That list is threat modeling applied to functional behavior.

A useful way to keep it structured is to walk four things and try to violate each one:

Input → State → Transition → Output

Which turns the clean sequence above into a much more interesting set of questions:

Cart → Confirmation, skipping everything between?
Checkout → Refresh → Payment submitted twice?
Payment → Back → Pay again?
Expired session → Checkout anyway?
Different user → Same confirmation URL?

You are not necessarily hunting for a vulnerability here.

You are hunting for states the designer never imagined, which is a much larger category and the one that produces most real-world defects.

Visual QA: Fuzzing a Component

The same thinking applies to work that has nothing to do with requests and sessions, although it is rarely described this way.

Standard visual review asks whether the heading looks right.

Adversarial visual review asks:

"What content or condition makes this component stop looking right?"

A name field renders Jane beautifully.

Now try:

Alexandria Catherine Montgomery-Worthington III

Or:

WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW

Or an email address like verylongdepartmentname@extremely-long-company-domain.example.

This is fuzzing, applied to a layout instead of a parser. The technique is identical: feed the thing valid input from outside the range it was designed around, and watch what breaks.

The catalog is long, and most of it takes seconds to try:

  • Empty titles.
  • Titles of two hundred characters.
  • Vertical images where the design expected horizontal ones.
  • Missing images.
  • SVGs with unusual intrinsic dimensions.
  • A price of $9.99 next to a price of $12,999,999.99.
  • A quantity of 1 next to a quantity of 99999.
  • Buttons whose labels are much longer than the design's.
  • Unexpected HTML inside the content.
  • Emoji.
  • Unicode outside the Latin range.
  • A more verbose language than the one the design was built in.
  • Zoom at 200%.
  • An extremely narrow viewport.

The underlying question never changes:

What assumptions does this component make about its input?

Use Cases Have Abuse Cases

Traditional QA works from use cases:

Use case: the user uploads a profile picture.

A security-influenced process adds a second column:

Abuse case: the user uploads something technically valid and completely outside what the designer expected.

Note that nothing here has to be malicious. Ordinary people generate abuse cases constantly, without any intent at all.

Somebody uploads an image that is 20 × 5000 pixels.

Somebody uploads a file named:

final-final-FINAL-version-approved-this-one-really-final-2026-08-15.png

Somebody writes a product description with no spaces in it.

None of that is an attack. All of it is realistic. And the results are the defects that fill agency bug lists: overflow, layout shift, buttons pushed out of reach, content stacking on top of other content, cards with absurd heights, responsive behavior that only worked for the sample data, truncated information, and actions that quietly disappear off the edge of a container.

Every one of those was a use case that never had its abuse case written.

Three Levels of QA

It helps to name the levels explicitly, because most teams only ever operate at the first one and believe they are doing the third.

Level 1. Expected QA. Does it work under expected conditions? Normal user, normal data, normal flow.

Level 2. Edge-case QA. Does it still work under unusual conditions? Maximum values, minimum values, empty, slow, duplicated, expired, offline.

Level 3. Adversarial QA. What happens if the assumptions of the system are deliberately violated?

All three apply to functional work, and all three apply to visual work.

Most creative teams are competent at Level 1 and inconsistent at Level 2. Level 3 usually does not exist, not because it is difficult, but because nobody has been given permission to do it.

That permission is the actual deliverable of this article.

Somebody Has to Be Allowed to Be Hostile

Before something is released, one person should be explicitly authorized to approach it with a deliberately hostile question:

What is wrong with this?

Not "can I approve it quickly?" Not "does it basically look okay?"

Give that person the checklist their medium deserves:

  • What would embarrass us if the client found it?
  • Which claim have we assumed is correct?
  • Which link did nobody actually click?
  • Which date came from memory instead of from the source?
  • What would a real customer misunderstand?
  • What happens on mobile?
  • What happens when the content is longer than the sample?
  • Does this image belong to this client?
  • Which part of this was generated, and who verified it?

That last one is not optional any more, and it is the subject of its own article later in this series: AI Made QA More Important, Not Less.

The Boundary That Makes It Survivable

Everything above is easy to describe and easy to get badly wrong, because adversarial review has an obvious failure mode.

The rule that prevents it is short enough to put on a wall:

Challenge the work adversarially. Do not treat your coworkers as adversaries.

This is not a softening of the technique. It is what makes the technique sustainable.

An organization that red-teams work well has reviewers who are motivated to find things, and creators who are comfortable receiving what gets found. Those two states have to exist at the same time. Remove either one and the practice collapses within a quarter: either the reviewers stop looking hard, or the creators start defending instead of fixing.

In practice the boundary lives in a few habits.

Findings describe the artifact, not the author. "The card breaks at 320px with a two-line title" is a finding. "You didn't check mobile" is an accusation wearing a finding's clothes.

The response to a finding is "good catch," and it comes from the person whose work was reviewed as often as from the reviewer. That sentence is doing more organizational work than it appears to.

And the team's opponent is stated explicitly: it is the escaped defect, not each other. Every finding at Level 3 is a defect that a customer will now never see. That is the scoreboard, and it is a shared one.

Where that stops being a matter of tone and becomes a real question about individual performance is a genuine problem, and it deserves a full article rather than a paragraph. It is the next one: A Blame-Free Culture Is Not an Accountability-Free Culture.

Assumptions Are the Actual Deliverable

There is a side effect of working this way that is easy to miss.

When a team red-teams its own work regularly, it stops carrying so many unexamined assumptions in the first place. The designer who has watched a card break under a real product name starts designing for the long one. The developer who has watched a double-clicked Submit create two orders starts building the guard without being asked.

Adversarial review does not only catch defects. It slowly converts private assumptions into stated requirements, which is the only place they can actually be checked.

That is the deeper reason the technique is worth the effort.

You are not just looking for what is broken today.

You are finding out what your team believes will always be true, and writing it down before reality gets a vote.