Atlas / Skills / aden-hive / Browser Edge Cases

Browser Edge CasesSAFE

skills/aden-hive/browser-edge-cases

Multi-Agent Harness for Production AI

Verdict
SAFE
Grade
B
Trust score
89 /100
Version
—
Hosts
—
License
Apache-2.0
Stars
11,091
01

Overview

Multi-Agent Harness for Production AI

Read from source at commit e9251a22710aOBSERVED · 2026-10-07
02

What it tells the agent

The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.

---
name: browser-edge-cases
description: SOP for debugging browser automation failures on complex websites. Use when browser tools fail on specific sites like LinkedIn, Twitter/X, SPAs, or sites with Shadow DOM.
license: MIT
---

# Browser Tool Edge Cases

Standard Operating Procedure for debugging and fixing browser automation failures on complex websites.

## When to Use This Skill

- `browser_interact(action="scroll")` succeeds but page doesn't move
- `browser_interact(action="left_click")` succeeds but no action triggered
- `browser_interact(action="type")` text disappears or doesn't work
- `browser_snapshot` hangs or returns stale content
- `browser_navigate` loads wrong content

## SOP: Debugging Browser Tool Failures

### Phase 1: Reproduce & Isolate

```
1. Create minimal test case demonstrating failure
2. Test against simple site (example.com) to verify tool works
3. Test against problematic site to confirm issue
```

**Quick isolation test:**
```python
# Test 1: Does the tool work at all?
await browser_navigate(tab_id, "https://example.com")
result = await browser_interact(action="scroll", tab_id=tab_id, scroll_direction="down", scroll_amount=100)
# Should work on simple sites

# Test 2: Does it fail on the problematic site?
await browser_navigate(tab_id, "https://linkedin.com/feed")
result = await browser_interact(action="scroll", tab_id=tab_id, scroll_direction="down", scroll_amount=100)
# If this fails but example.com works → site-specific edge case
```

### Phase 2: Analyze Root Cause

**Step 2a: Check console for errors**
```python
console = await browser_console(tab_id)
# Look for: CSP violations, React errors, JavaScript exceptions
```

**Step 2b: Inspect DOM structure**
```python
html = await browser_html(tab_id)
snapshot = await browser_snapshot(tab_id)
# Look for:
# - Nested scrollable divs (overflow: scroll/auto)
# - Shadow DOM roots
# - iframes
# - Custom widgets
```

**Step 2c: Identify the pattern**

| Symptom | Likely Cause | Check |
|---------|--------------|-------|
| Scroll doesn't move | Nested scroll container | Look for `overflow: scroll` divs |
| Click no effect | Element covered | Check `getBoundingClientRect` vs viewport |
| Type clears | Autocomplete/React | Check for event listeners on input; try a `type` action with no selector |
| Snapshot hangs | Huge DOM | Check node count in snapshot |
| Snapshot stale | SPA hydration | Wait after navigation |

### Phase 3: Implement Multi-Layer Fix

**Pattern: Always have fallbacks**

```python
async def robust_operation(tab_id):
    # Method 1: Primary approach
    try:
        result = await primary_method(tab_id)
        if verify_success(result):
            return result
    except Exception:
        pass

    # Method 2: CDP fallback
    try:
        result = await cdp_fallback(tab_id)
        if verify_success(result):
            return result
    except Exception:
        pass

    # Method 3: JavaScript fallback
    return await javascript_fallback(tab_id)
```

**Pattern: Always add timeouts**

```python
# Bad - can hang forever
result = await browser_snapshot(tab_id)

# Good - fails fast with useful error
try:
    result = await browser_snapshot(tab_id, timeout_s=10.0)
except asyncio.TimeoutError:
    # Handle timeout gracefully
    result = await fallback_snapshot(tab_id)
```

### Phase 4: Verify Fix

```
1. Run against problematic site → should work
2. Run against simple site → should still work (regression check)
3. Document in registry.md
```

## Pattern Library

### P1: Nested Scrollable Containers

**Sites:** LinkedIn, Twitter/X, any SPA with scrollable feeds

**Detection:**
```javascript
// Find largest scrollable container
const candidates = [];
document.querySelectorAll('*').forEach(el => {
    const style = getComputedStyle(el);
    if (style.overflow.includes('scroll') || style.overflow.includes('auto')) {
        const rect = el.getBoundingClientRect();
        if (rect.width > 100 && rect.height > 100) {
            candidates.push({el, area: rect.width * rect.height});
        }
    }
});
candidates.sort((a, b) => b.area - a.area);
return candidates[0]?.el;
```

**Fix:** Dispatch scroll events at container's center, not viewport center.

### P2: Element Covered by Overlay

**Sites:** Modals, tooltips, SPAs with loading overlays

**Detection:**
```javascript
const rect = element.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const topElement = document.elementFromPoint(centerX, centerY);
return topElement === element || element.contains(topElement);
```

**Fix:** Wait for overlay to disappear, or use JavaScript click.

### P3: React Synthetic Events

**Sites:** React SPAs, modern web apps

**Detection:** If CDP click doesn't trigger handler but manual click works.

**Fix:** Use JavaScript click as primary:
```javascript
element.click();
```

### P4: Huge DOM / Accessibility Tree

**Sites:** LinkedIn, Facebook, Twitter (feeds with 1000s of nodes)

**Detection:**
```javascript
document.querySelectorAll('*').length > 5000
```

**Fix:**
1. Add timeout to snapshot operation
2. Truncate tree at 2000 nodes
3. Fall back to DOM-based snapshot if accessibility tree too large

### P5: SPA Hydration Delay

**Sites:** React, Vue, Angular SPAs after navigation

**Detection:**
```javascript
// Check if React app has hydrated
document.querySelector('[data-reactroot]') ||
document.querySelector('[data-reactid]')
```

**Fix:** Wait for specific selector after navigation:
```python
await browser_navigate(tab_id, url, wait_until="load")
await browser_interact(action="wait", tab_id=tab_id, wait_for_selector='[data-testid="content"]', timeout_ms=5000)
```

### P6: Shadow DOM

**Sites:** Components using Shadow DOM, Lit elements

**Detection:**
```javascript
document.querySelectorAll('*').some(el => el.shadowRoot)
```

**Fix:** Pierce shadow root:
```javascript
function queryShadow(selector) {
    const parts = selector.split('>>>');
    let node
03

Trust audit

SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codePASS
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
none-observed
Network
none-observed
Shell
none-observed
Dependencies
pinned
Secrets in source
none-found

Findings (7)

LOWInventory / provenance · inv.symlink · CWE-1104
CLAUDE.md
CLAUDE.md
Why it matters. link not followed
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
scripts/test_15_screenshot.py:46
raw = base64.b64decode(data)
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
scripts/test_15_screenshot.py:72
raw = base64.b64decode(data)
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
scripts/test_15_screenshot.py:98
v_size = len(base64.b64decode(v_data))
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
scripts/test_15_screenshot.py:99
f_size = len(base64.b64decode(f_data))
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
scripts/test_15_screenshot.py:128
sel_size = len(base64.b64decode(data))
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
registry.md:211
| **Symptom** | `send_dm.py` returns `send_unverified` on every send: enabled `dm-composer-send-button` is found and clicked, but the composer never clears, no `message-text-*` bubble renders, and not
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine

Gates applied: no_behavioural_pass.

Audited 2026-10-07 · audit v0.4.1 · source sha e9251a22710afull audit observations/trust-audit/skill/aden-hive__browser-edge-cases.json · Report an issue / request a re-scan
04

Audit history

Every audit this skill has had.

DateSourceVerdictGradeScoreChange
2026-10-07e9251a22710aSAFEB89first audit
05

Questions

What does the Browser Edge Cases skill do?

Multi-Agent Harness for Production AI

Is Browser Edge Cases safe to install?

The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.

What can Browser Edge Cases access on my machine?

The audit observed no filesystem, network or shell use at all in its source.

How current is this page?

The grade is for one exact copy of the source (e9251a22710a), read on 2026-10-07. The repository is watched, and a new audit runs when it changes — this is the first audit.

Advertisement