How to Use Adversarial Testing Patterns to Find UI Bugs in browserbase/skills

Adversarial testing patterns use the Browserbase browse command set to execute deterministic, script-driven sequences that expose UI bugs through edge-case inputs, state race conditions, and accessibility violations.

Adversarial testing patterns provide a lightweight methodology for probing web application robustness without the overhead of traditional testing frameworks. These patterns are implemented in the browserbase/skills repository under skills/ui-test/references/adversarial-patterns.md, utilizing the declarative browse API to automate interactions and capture DOM snapshots. By targeting specific component classes—forms, modals, navigation, and error states—with malicious or boundary inputs, you reveal XSS vulnerabilities, layout regressions, and keyboard navigation gaps that functional tests typically miss.

Understanding the Adversarial Patterns Framework

The adversarial patterns are built on top of the browse command set defined in skills/ui-test/SKILL.md. These patterns are not heavy test suites; they are concise Bash-style scripts that leverage the bb CLI (provided by skills/browserbase-cli/SKILL.md) to drive browser automation.

Each pattern follows a consistent structure:

  1. Capture baseline state using browse snapshot
  2. Execute adversarial action via browse click, browse fill, or browse press
  3. Validate result through subsequent snapshots or browse eval assertions

Because the patterns rely only on the generic browse API, they port across any web application the Browserbase agent can access.

Core Adversarial Testing Patterns

The reference file skills/ui-test/references/adversarial-patterns.md categorizes tests by UI component type. Below are the essential patterns for uncovering robustness issues.

Form Resilience Testing

Forms are high-risk surfaces for injection attacks and validation gaps. This pattern tests empty submissions, boundary inputs, special characters, and race conditions.


# Empty submission

browse snapshot                          # BEFORE: note form fields

browse click @submit-ref                 # ACT: submit empty

browse snapshot                          # AFTER: error messages should appear

# Long input (500+ chars)

browse fill "#name" "aaaaaaaa....(500 chars)"
browse snapshot                          # Check layout & truncation

# Special characters (XSS / SQL-like payload)

browse fill "#name" "<script>alert('xss')</script>"
browse fill "#email" "'; DROP TABLE users;--"
browse snapshot                          # Verify input sanitisation

# Rapid submit

browse click @submit-ref
browse click @submit-ref                 # Click twice immediately

browse snapshot                          # Ensure only one submission processed

The @submit-ref syntax references elements defined in the UI-test skill's reference system, allowing scripts to remain declarative and maintainable.

Modals often trap focus poorly or fail to handle escape key events. This pattern verifies complete open/close lifecycles and side-effect triggering.

browse snapshot                          # BEFORE: no dialog in tree

# Open

browse click @trigger-ref
browse snapshot                          # AFTER: dialog element should appear

# ASSERT: dialog role exists in tree

# Escape to close

browse press Escape
browse snapshot                          # AFTER: dialog should be gone

# Re-open and cancel

browse click @trigger-ref
browse snapshot
browse click @cancel-ref
browse snapshot

# Re-open and confirm

browse click @trigger-ref
browse snapshot
browse click @confirm-ref
browse snapshot                          # Dialog gone + side-effect occurred

Client-side routers can fail to update URL state or handle history correctly. This pattern captures URL transitions and back-button behavior.

browse snapshot                          # BEFORE: note current URL and content

browse click @nav-link-ref               # ACT: click a navigation link

browse wait load
browse get url                           # Check URL changed

browse snapshot                          # AFTER: content matches destination

# Back button

browse back
browse get url                           # Should return to original URL

browse snapshot                          # Content matches original page

Error State Robustness

Applications must gracefully handle empty data sets, 404 routes, and invalid submissions without blank screens or cryptic messages.


# No data page

browse open http://localhost:3000/items
browse snapshot

# Verify empty-state UI or CTA

# Non-existent route

browse open http://localhost:3000/does-not-exist
browse snapshot

# Expect a 404 page, not a blank screen

# Invalid form data

browse fill "#field" "invalid"
browse click @submit-ref
browse snapshot

# Check helpful error message & input preservation

Keyboard Accessibility Audits

Accessibility gaps often hide in tab order and keyboard activation. This pattern programmatically verifies focus management.

browse open http://localhost:3000/page
browse wait load

# Tab through all interactive elements

browse press Tab
browse eval "JSON.stringify({tag: document.activeElement?.tagName, text: document.activeElement?.textContent?.trim().slice(0,40), role: document.activeElement?.getAttribute('role')})"

# Repeat until activeElement returns to BODY

# Activate via keyboard

browse press Enter
browse snapshot                          # Verify the action occurred

Analyzing Results with DOM Snapshots

The browse snapshot command stores a combined DOM and screenshot artifact after each adversarial action. Store these snapshots to diff against baselines or review manually for visual regressions.

For programmatic validation, chain browse eval or browse get calls to assert expectations:

  • browse get url verifies routing changes
  • browse eval executes JavaScript to check element states, focus positions, or error message visibility

Since the browse commands are deterministic, any failure can be reproduced locally by replaying the same script with bb run <script>.

Integrating Patterns into CI/CD Pipelines

Running adversarial patterns in continuous integration provides early detection of regressions that happy-path tests miss. Save each pattern block as a .sh script in your repository, then execute via:

bb run test-scripts/adversarial-form-validation.sh

Store the resulting snapshots as CI artifacts to audit UI state changes across builds. Because the patterns execute against any reachable URL, they validate production deployments, staging environments, or local development servers identically.

Summary

  • Adversarial testing patterns are lightweight, reusable scripts stored in skills/ui-test/references/adversarial-patterns.md that probe UI robustness.
  • The browse command set provides the automation primitives (snapshot, fill, click, eval) without requiring heavy test frameworks.
  • Patterns cover form injection, modal lifecycles, routing verification, error states, and keyboard accessibility.
  • DOM snapshots captured via browse snapshot enable visual regression detection and manual review.
  • Execution through the bb CLI integrates seamlessly into CI/CD pipelines for automated regression detection.

Frequently Asked Questions

What distinguishes adversarial testing from standard UI testing?

Standard UI testing typically follows happy-path user flows to verify features work correctly. Adversarial testing deliberately injects malformed inputs, triggers race conditions, and probes edge cases to expose security vulnerabilities, layout breakage, and unhandled error states that functional specifications rarely cover.

How do I execute adversarial patterns locally?

Install the Browserbase CLI from skills/browserbase-cli/SKILL.md, then save any pattern block as a .sh file and run bb run <script>. The CLI interprets the browse commands using your local or cloud-hosted browser agent, capturing snapshots to your local filesystem for inspection.

Can these patterns detect actual security vulnerabilities like XSS?

Yes. The patterns specifically include XSS payloads (e.g., <script>alert('xss')</script>) and SQL-injection-like strings (e.g., '; DROP TABLE users;--) in the Form Resilience tests. By capturing snapshots after filling these inputs, you verify whether the application properly sanitizes user input or executes malicious code.

Which UI components benefit most from adversarial testing patterns?

Forms and inputs benefit immediately from injection and validation tests. Modal dialogs require lifecycle testing to ensure proper focus trapping and dismissal. Navigation components need routing verification to catch history API bugs. Finally, keyboard-accessible interfaces require tab-order audits to meet accessibility standards and ensure logical focus management.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →