T09 · Insecure Skill Coding Practices
- Location
SKILL.md:441- Finding
Remote Persistence and API Exposure of Complete Browser Authentication State
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is a disclosed remote browser controller, but it needs Review because it can persist and expose full logged-in browser profiles through a remote service.
Install only if you trust the remote browser provider with page contents, screenshots, actions, and potentially logged-in browser state. Prefer ephemeral sessions, use header-based authentication instead of URL tokens, avoid storing sensitive accounts unless necessary, and delete stored sessions when finished.
SKILL.md:441Remote Persistence and API Exposure of Complete Browser Authentication State
SKILL.md:47Authentication Token Allowed in URL Query String
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
the idle clock restarts.
- **Activity that restarts the 5-min clock**: opening a CDP/VNC connection, `GET .../status`,
`GET .../{session_id}`, and `POST .../ping`.
- **To close immediately** instead of waiting out the idle timeout: `DELETE /api/sessions/{session_id}`
(or `terminate_session`). On teardown the profile is saved.
Maximum 1 concurrent session per user. If creation returns 429 or WebSocket closes with a limit error: **wait a bit** (previous session may still be shutting down) **and/or close the previous session** via `DELETE /api/sessions/{session_id}` before retrying.
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
the idle clock restarts.
- **Activity that restarts the 5-min clock**: opening a CDP/VNC connection, `GET .../status`,
`GET .../{session_id}`, and `POST .../ping`.
- **To close immediately** instead of waiting out the idle timeout: `DELETE /api/sessions/{session_id}`
(or `terminate_session`). On teardown the profile is saved.
Maximum 1 concurrent session per user. If creation returns 429 or WebSocket closes with a limit error: **wait a bit** (previous session may still be shutting down) **and/or close the previous session** via `DELETE /api/sessions/{session_id}` before retrying.
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
the idle clock restarts.
- **Activity that restarts the 5-min clock**: opening a CDP/VNC connection, `GET .../status`,
`GET .../{session_id}`, and `POST .../ping`.
- **To close immediately** instead of waiting out the idle timeout: `DELETE /api/sessions/{session_id}`
(or `terminate_session`). On teardown the profile is saved.
Maximum 1 concurrent session per user. If creation returns 429 or WebSocket closes with a limit error: **wait a bit** (previous session may still be shutting down) **and/or close the previous session** via `DELETE /api/sessions/{session_id}` before retrying.
The skill documents direct GET/PUT access to persisted cookies, storage, IndexedDB, and Cache Storage, plus deletion of stored sessions. This creates a powerful surface for an agent to read, modify, or wipe sensitive authenticated state if it restores or targets a session identifier, making session fixation, token theft, data tampering, or destructive deletion materially more dangerous in the context of a browser automation skill.
- **Readability vs raw** — `/text` (default) strips nav/footer/ads; `?mode=raw` returns full `innerText`.
- **Interactive filter** — `?filter=interactive` on `/json` reduces nodes by ~75% for action tasks.
- **VNC vs DOM** — Use `/action` for selectors/refs in the page DOM. Use `/vnc/action` and `/vnc/screenshot` for pixel-level automation and UI outside the DOM.
- **Stored sessions** — Sessions persist to S3 and are restored on reopen. The **whole browser profile** is captured (cookies, localStorage, sessionStorage, IndexedDB, **Service Workers**, Cache Storage, metadata) and restored as one consistent unit, so apps that keep their login in IndexedDB/Service Workers (e.g. Telegram Web) come back **logged in**, not just at the login page. List with `GET /api/stored-sessions`, then reopen by creating a session with the same `session_id` (HTTP/WebSocket). If `url` is not provided on connect, the saved page URL is used for redirect. Use `GET/PUT /api/stored-sessions/{session_id}` to read or update metadata: `url` (redirect on reopen), `description` (free-text human label, max 500 chars, returned in the list endpoint's `descriptions` map), `width`/`height` (default resolution), `encrypt_with_api_key`. To move or edit individual persisted blobs without a live browser, use `GET/PUT /api/stored-sessions/{session_id}/cookies` (JSON array of cookie objects), `GET/PUT .../local-storage`, `GET/PUT .../session-storage` (both JSON objects with string keys and string values), `GET/PUT .../indexeddb` (IndexedDB snapshot object), and `GET/PUT .../cache-storage` (Cache Storage snapshot object). `DELETE /api/stored-sessions/{session_id}` wipes all persisted state for a session.
## Limitations & fallbacks
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
curl -X POST "https://rb.all-completed.com/api/sessions" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{}'
The skill explicitly documents persistence of the entire browser profile, including cookies, localStorage, sessionStorage, IndexedDB, Service Workers, and Cache Storage, plus APIs to read, modify, and delete that data. Without an upfront privacy/retention warning and explicit user-consent guidance, an agent could preserve authenticated sessions and sensitive browsing state longer than a user expects, increasing the chance of account takeover or privacy leakage if sessions are reused or accessed later.
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
- **Prefer `fill` over `type` for form fields** — `type` does `focus()` + `Input.insertText`; some controlled/React inputs don't register it. `fill` does select-all + insertText with real input events and is the reliable choice for text fields. Use `type` only for appending to plain inputs.
- **To submit a form, use `submit` (not `press` Enter)** — a synthetic `press` Enter does not perform the browser's default submit. Use `{"kind":"submit","selector":"<form or a field in it>"}`, or click the submit button by selector (selector `click` does a DOM `element.click()`).
- **Never type secrets yourself — use `request-fill` ("Keeper")** — for passwords, login codes, 2FA, or any value you must not see, call `POST /api/sessions/{id}/request-fill` instead of `fill`/`type`. **This is THIS service's own built-in secure credential fill — "Keeper" is the user's companion app for it. It is NOT OpenClaw `secrets`/`SecretRefs` (config-backed values); do not conclude "there's no keeper" because OpenClaw secrets has no live prompt — this endpoint IS the live prompt.** The user supplies the value out-of-band in their Keeper app (which shows your `message` + a screenshot of the field area) and the **service** types it into the field; the value is never returned to you or logged. It's **async**: you get `{request_id, status:"pending"}`, then poll `GET /api/sessions/fill-status/{request_id}` (tool `get_fill_status`) until `filled` / `cancelled` / `timeout` / `error`.
- **Default to this for any login.** Don't ask the user to paste a password into chat. Order of preference: (1) `request-fill`; (2) if it returns **`status:"no_keeper"`** (no Keeper app connected), have the user sign in themselves via the **live VNC view** (you never see the password) — the session then persists logged-in; (3) only as a last resort, with the user's explicit consent, accept a value they provide.
- **One field:** `{"selector":"input[name=password]","label":"Password","field":"password","message":"Logging
...[truncated 25 chars]
The skill exposes a geolocation override endpoint but does not clearly warn that this changes the location signals presented to websites. That can mislead users or agents into spoofing location-dependent behavior, with privacy, compliance, or trust implications if used without clear disclosure and consent.
No suspicious patterns detected.