Category
New defense rule
What problem does this solve?
Browser-use agents asked to "buy X for $Y" on hotel, ticket, travel, and e-commerce sites encounter the drip pricing pattern: a low base price up front, with mandatory fees ("service fee", "resort fee", "convenience fee", "processing fee", "delivery surcharge") only added at checkout. The FTC's Trade Regulation Rule on Unfair or Deceptive Fees (effective 2025-05-12) bans the pattern for live-event tickets and short-term lodging, but enforcement is case-by-case elsewhere and the pattern remains common across airlines, food delivery, and event-adjacent commerce.
The asymmetry an agent faces: a sighted user scans the running total before clicking Pay; an agent acting on a single task instruction may not re-check pricing assumptions at the final step. The agent isn't pressured by manufactured urgency (countdown-timer-redact territory) — it's misled by the order in which costs become visible.
Proposed solution
On checkout-shaped URLs (reuse the gate cart-addon-annotate and checkout-checkbox-sanitize already use: /cart, /checkout, /basket, /bag, /payment, /order), walk line-item rows and annotate ones whose visible label matches a curated hidden-fee phrase set ("service fee", "convenience fee", "processing fee", "resort fee", "destination fee", "facility fee", "handling fee", "venue fee", "delivery surcharge"). Annotation reuses the visible inline-chip pattern from cart-addon-annotate — the line item is preserved so the agent decides whether to abandon, downgrade, or proceed.
MVP: label-only matching. No price comparison, no anchor selection.
The hardest part is choosing a comparison anchor for any future "delta vs. advertised" check — possible anchors are referrer-URL price params, the cart page's initial total snapshot, or an explicit "starting at" / "from" element earlier in the flow. Defer past v1.
Alternatives considered
- Strip the fee row outright. Wrong choice — many fees are real (taxes, shipping). The defense is making the agent see the fee, not hiding it. One of the few cases where annotate is the right action even under a remove-over-annotate default; the rule must not destroy information the operator is legally required to surface.
- Compute a delta vs. some baseline total. Anchor selection is the open problem and varies by site; ship label-flag first and iterate.
- Defer to
irrelevant-sections-redact. Wrong threat model — fees are not irrelevant chrome, they're load-bearing pricing.
Controlling false positives
- Shape-check the row. Matching label must sit in an order-summary container (
<table> / [role="region"] / <aside> with cart-shaped class names / schema.org Order microdata) AND have an adjacent currency amount within N siblings. Loose paragraph mentions of "service fee" in marketing copy do not match.
- Whole-string regex on the label element, same precision bar as
disguised-ad-flag. Substring matches like "Customer Service Fee Schedule" inside a sentence get rejected.
- Explicit exclude list for legally-required line items — "tax", "VAT", "GST", "sales tax", "shipping", "delivery" without "surcharge". These already have their own legal disclosure regime and are not the hidden-fee pattern.
- Single-item cart exclusion. When the matched fee row is the only item in the cart, it's the product, not an add-on (e.g., paying a service fee directly to a utility).
- Per-host kill-switch. Sites where the fee genuinely is the product (DMV portals, court e-filing) can be denylisted.
- Phrase set curation policy. Additions go through PR review; avoid expanding to single overly-generic words like "fee" alone. Same governance posture as
cart-addon-annotate's pattern set.
- Telemetry on rollout. Default-off until per-rule hit/skip counts on the live ruleset show the FP rate is acceptable; promote to default-on after a real-world signal window similar to
schema-trust-sanitize's posture.
Prior art / references
- FTC Trade Regulation Rule on Unfair or Deceptive Fees (final rule PDF).
- Mathur et al. (CSCW 2019), Dark Patterns at Scale. — covers Sneaking and Hidden Costs. Already cited by other rules.
- Brignull, deceptive.design — Hidden Costs and Sneak into Basket.
- No known direct OSS implementation. Currency parsing handled by built-in
Intl.NumberFormat or currency.js (MIT).
Tagged Impact M–H / Complexity H.
Category
New defense rule
What problem does this solve?
Browser-use agents asked to "buy X for $Y" on hotel, ticket, travel, and e-commerce sites encounter the drip pricing pattern: a low base price up front, with mandatory fees ("service fee", "resort fee", "convenience fee", "processing fee", "delivery surcharge") only added at checkout. The FTC's Trade Regulation Rule on Unfair or Deceptive Fees (effective 2025-05-12) bans the pattern for live-event tickets and short-term lodging, but enforcement is case-by-case elsewhere and the pattern remains common across airlines, food delivery, and event-adjacent commerce.
The asymmetry an agent faces: a sighted user scans the running total before clicking Pay; an agent acting on a single task instruction may not re-check pricing assumptions at the final step. The agent isn't pressured by manufactured urgency (
countdown-timer-redactterritory) — it's misled by the order in which costs become visible.Proposed solution
On checkout-shaped URLs (reuse the gate
cart-addon-annotateandcheckout-checkbox-sanitizealready use:/cart,/checkout,/basket,/bag,/payment,/order), walk line-item rows and annotate ones whose visible label matches a curated hidden-fee phrase set ("service fee", "convenience fee", "processing fee", "resort fee", "destination fee", "facility fee", "handling fee", "venue fee", "delivery surcharge"). Annotation reuses the visible inline-chip pattern fromcart-addon-annotate— the line item is preserved so the agent decides whether to abandon, downgrade, or proceed.MVP: label-only matching. No price comparison, no anchor selection.
The hardest part is choosing a comparison anchor for any future "delta vs. advertised" check — possible anchors are referrer-URL price params, the cart page's initial total snapshot, or an explicit "starting at" / "from" element earlier in the flow. Defer past v1.
Alternatives considered
irrelevant-sections-redact. Wrong threat model — fees are not irrelevant chrome, they're load-bearing pricing.Controlling false positives
<table>/[role="region"]/<aside>with cart-shaped class names / schema.orgOrdermicrodata) AND have an adjacent currency amount within N siblings. Loose paragraph mentions of "service fee" in marketing copy do not match.disguised-ad-flag. Substring matches like "Customer Service Fee Schedule" inside a sentence get rejected.cart-addon-annotate's pattern set.schema-trust-sanitize's posture.Prior art / references
Intl.NumberFormatorcurrency.js(MIT).Tagged Impact M–H / Complexity H.