Evaluate a detector in minutes
Install the SDK, load attack/control pairs in the view your agent sees, and score a detector in Python or from the command line.
Install
Python 3.10 or later. The SDK is not on PyPI yet; install it from GitHub.
pip install "browsesafe-pp[eval] @ git+https://github.com/perplexityai/browsesafe-plus-plus.git"Load data
A pair holds two pages: the attacked page and its control. n_pairs=100 loads up to 200 pages; iteration yields the attacked page and then the control of each pair.
import browsesafe_pp as bs
bench = bs.load(split="train", n_pairs=100) # 100 pairs = 200 pages, HTML view
pair = bench.pairs[0]
pair.malicious.content # attacked page in the selected view
pair.malicious.injected # True
pair.benign.injected # False: same page without the injection
pair.metadata # language, page type, attack type, task, ...The Hugging Face dataset contains the training split (29,500 pairs). The 9,175-pair test split is reserved for the leaderboard, and a submission endpoint for it is coming soon.
Choose the view with view=, and select by metadata with filters=. Filters match the attacked page and keep its control.
md = bs.load(split="train", view="markdown", n_pairs=100)
ax = bs.load(split="train", view="accessibility", n_pairs=100)
spanish = bs.load(filters={"language_payload": ["es"]}, n_pairs=100)The dataset id can be set with an environment variable:
# Override the SDK's default dataset if needed
export BROWSESAFE_DATASET="perplexity-ai/browsesafe-plus-plus"Evaluate in Python
A detector is a function that receives one page and returns a prediction. Return bs.Prediction(injected=None) to abstain. The detector input excludes tasks, labels and reference annotations.
import browsesafe_pp as bs
def predict(request):
# request.content: the page in the selected view
# request.view: "html", "markdown" or "accessibility"
flagged = "ignore previous instructions" in request.content.lower()
return bs.Prediction(injected=flagged)
bench = bs.load(split="train", n_pairs=100)
report = bs.evaluate(bench, predict)
report.save("results/my-detector")Reports include precision, recall, the false-positive rate on control pages, paired correctness, errors and abstentions. Each page gets one attempt; failures are counted, not retried.
Command line
Point --predict at any importable module:function. Run once per view you want to report.
# mymod.py defines predict(request) -> bs.Prediction
browsesafe evaluate --predict mymod:predict --view html \
--output results/mymod-html
browsesafe evaluate --predict mymod:predict --view markdown \
--output results/mymod-markdownEvaluate a hosted model
To score a model behind an OpenAI-compatible chat endpoint, set the endpoint, key and model name. Prompted models on the leaderboard use the published BrowseSafe detection prompt.
export BROWSESAFE_MODEL_ENDPOINT="https://your-endpoint.example/v1"
export BROWSESAFE_API_KEY="..."
export BROWSESAFE_MODEL="your-model-name"
browsesafe evaluate --model "$BROWSESAFE_MODEL" --view html \
--output results/your-model-htmlAdaptive attacks
Static replays understate risk. BrowseSafe-Adapt starts from a benchmark injection, runs a browsing agent on the task, and revises the injection from the agent's behaviour. In the paper, attacks that succeed on a few percent of tasks when replayed succeed on up to 95% after adaptation.
The SDK includes the campaign framework for running adaptive attacks against your own agent; see the adaptive attack guide. The paper's results are on the adaptive leaderboard.