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:
- Capture baseline state using
browse snapshot - Execute adversarial action via
browse click,browse fill, orbrowse press - Validate result through subsequent snapshots or
browse evalassertions
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.
Modal Dialog Lifecycle Validation
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
Navigation and Routing Verification
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 urlverifies routing changesbrowse evalexecutes 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.mdthat probe UI robustness. - The
browsecommand 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 snapshotenable visual regression detection and manual review. - Execution through the
bbCLI 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →