# Probe transcript — Wikipedia REST API (e2e) | | | |---|---| | Entry | `entries/wikipedia.yaml` | | Target | API `https://en.wikipedia.org/api/rest_v1` · spec `https://en.wikipedia.org/api/rest_v1/?spec` · policies on foundation.wikimedia.org, wikitech.wikimedia.org, www.mediawiki.org | | Mode | `e2e` | | Probe id | `wikipedia-e2e` | | Rubric | `rubric/v0.2.json` sha256 `cd605a44799f49951bf078fda63c5b21ad3c07db494f41d38ad19ce729c5551a` | | Date | 2026-09-05 | | Sandbox up | 2026-09-05T13:12:52Z | | Sandbox down | 2026-09-05T13:12:58Z | | Wall clock | 6 s (epoch 1788613972 → 1788613978) | | Real money spent | $0.00 | | Human interventions | 0 | | Verdict | `completed` | | Secrets carried in | none. `PROBE_WALLET_KEY` unset, `PROBE_INBOX` unset, `PROBE_SPEND_CAP_USD=0`. Redactions below: the `WMF-Uniq` cookie value assigned to the sandbox and the `x-client-ip` echo of the operator's egress address | | User-Agent sent | `ag3ntsearch-probe/0.2 (https://ag3ntsearch.com; agent-nativeness index probe) curl` on every request — client name/version, contact URL, library, per the Wikimedia Foundation User-Agent Policy format | | Rate discipline | 11 requests, strictly sequential (concurrency 1), ~3.5 req/s peak — under the Robot policy's 5 req/s / concurrency 3 for unauthenticated REST clients | Every request below was issued from inside the probe sandbox on an `--internal` Docker network whose only egress is an allowlisting tinyproxy sidecar. No request to any target host was made from the host shell. ```sh ./.claude/skills/probe/probe-sandbox.sh up --id wikipedia-e2e --target en.wikipedia.org \ --allow foundation.wikimedia.org --allow wikitech.wikimedia.org --allow www.mediawiki.org ``` Allowlist: `en.wikipedia.org`, `foundation.wikimedia.org`, `wikitech.wikimedia.org`, `www.mediawiki.org`. Nothing else. --- ## 0. Permission gate (gate mode, before any sandbox traffic) Read via WebFetch on 2026-09-05 (all re-fetched from the sandbox in §4; quotes below are from the collected pages): - **Robot policy** (https://wikitech.wikimedia.org/wiki/Robot_policy): "As an Operator of a program automatically consuming the content of the wikis (robot), certain rules apply … Bots that don't follow these guidelines may be rate-limited and informed of the reason, and pointed to ways to request higher quotas or exemptions." … "Accurately identify your User-Agent." … **REST API rules**: "You can use this interface to fetch the HTML content of the pages, or their summary. If unauthenticated, keep the concurrency of your requests to 3 at a time, and below 5 requests per second overall." … "Avoid using the action API for HTML content of pages. Use the website and/or the REST API instead." - **User-Agent Policy** (https://foundation.wikimedia.org/wiki/Policy:Wikimedia_Foundation_User-Agent_Policy): "As of February 15, 2010, Wikimedia sites require a HTTP User-Agent header for all requests." … "Scripts should use an informative User-Agent string with contact information, or they may be blocked without notice." … "Do not use generic agents such as "curl", "lwp", "Python-urllib", and so on." - **API:Etiquette** (https://www.mediawiki.org/wiki/API:Etiquette): "There is no hard speed limit on read requests, but be considerate and try not to take a site down." "Making your requests in series rather than in parallel … should result in a safe request rate." - **Access policy** (https://www.mediawiki.org/wiki/Wikimedia_APIs/Access_policy): "The API requires an HTTP User-Agent header for all requests. … Clients making requests without a User-Agent header may be blocked without notice." - **robots.txt** (https://en.wikipedia.org/robots.txt), `User-agent: *` block: `Allow: /api/rest_v1/?doc` … `Disallow: /w/` … **`Disallow: /api/`**, preceded by the comment "Another exception is for REST API documentation, located at /api/rest_v1/?doc." Decision: `granted`, with binding conditions (descriptive UA with contact; ≤5 req/s, concurrency ≤3 unauthenticated; series not parallel). The Robot policy is an explicit operator grant to robots that names the summary endpoint. The robots.txt `Disallow: /api/` is read as a crawler-indexing directive — its own comment frames the docs carve-out as an exception to *indexing* — not as a statement that the operator does not want API clients, which the Robot policy contradicts by telling robots to use exactly this path. Recorded verbatim on the entry as a counter-signal. Consequences applied to the run: - **No UA-less or stock-`curl` control requests.** The policy says not to send them; "does the wall enforce?" is therefore recorded as unverified rather than tested. - Sequential requests only; a URL contact rather than an email (the policy accepts "a website"; this wave carries no real email by design). --- ## 1. Reference task — PASS > Sending a User-Agent header that names the client and a contact URL, GET > `https://en.wikipedia.org/api/rest_v1/page/summary/Agent-based_model` and confirm > the response is HTTP 200 JSON whose `"title"` equals `"Agent-based model"` and > whose `"extract"` is a string longer than 50 characters. Authored for this run. ``` GET https://en.wikipedia.org/api/rest_v1/page/summary/Agent-based_model http=200 time=0.163s size=2819 ``` Response headers (verbatim, two values redacted; first two lines are the sandbox proxy): ``` HTTP/1.1 200 Connection established Proxy-agent: tinyproxy/1.11.2 HTTP/2 200 content-security-policy: default-src 'none'; frame-ancestors 'none' x-content-security-policy: default-src 'none'; frame-ancestors 'none' x-webkit-csp: default-src 'none'; frame-ancestors 'none' cache-control: s-maxage=1209600, max-age=300 content-language: en content-type: application/json; charset=utf-8; profile="https://www.mediawiki.org/wiki/Specs/Summary/1.5.0" date: Sat, 05 Sep 2026 13:12:53 GMT server: production-tls access-control-allow-origin: * access-control-allow-methods: GET,HEAD access-control-allow-headers: accept, content-type, content-length, cache-control, accept-language, api-user-agent, if-match, if-modified-since, if-none-match, dnt, accept-encoding access-control-expose-headers: etag x-content-type-options: nosniff x-frame-options: SAMEORIGIN referrer-policy: origin-when-cross-origin x-xss-protection: 1; mode=block etag: W/"1371720832/62a8c320-a924-11f1-8d44-cf33730c7907" age: 0 accept-ranges: bytes vary: Accept-Language, x-restbase-compat, Accept-Encoding x-cache: cp1114 miss, cp1114 miss x-cache-status: miss strict-transport-security: max-age=106384710; includeSubDomains; preload report-to: { "group": "wm_nel", "max_age": 604800, "endpoints": [{ "url": "https://intake-logging.wikimedia.org/v1/events?stream=w3c.reportingapi.network_error&schema_uri=/w3c/reportingapi/network_error/1.0.0" }] } nel: { "report_to": "wm_nel", "max_age": 604800, "failure_fraction": 0.05, "success_fraction": 0.0} set-cookie: WMF-Last-Access=05-Sep-2026;Path=/;HttpOnly;secure;Expires=Wed, 07 Oct 2026 12:00:00 GMT set-cookie: WMF-Last-Access-Global=05-Sep-2026;Path=/;Domain=.wikipedia.org;HttpOnly;secure;Expires=Wed, 07 Oct 2026 12:00:00 GMT x-client-ip: [REDACTED operator egress IPv4] set-cookie: GeoIP=US:MN:Austin:43.67:-92.97:v4; Path=/; secure; Domain=.wikipedia.org set-cookie: NetworkProbeLimit=0.001;Path=/;Secure;SameSite=None;Max-Age=3600 set-cookie: WMF-Uniq=[REDACTED 64-char token];Domain=.wikipedia.org;Path=/;HttpOnly;secure;SameSite=None;Expires=Sun, 05 Sep 2027 00:00:00 GMT content-length: 2819 x-request-id: 0747ab56-9a5d-4a18-9efa-51fa8cd3daa8 server-timing: cache;desc="miss", host;desc="cp1114",co_id;desc="4177574652" ``` Body (verbatim, `displaytitle`/`titles.display` HTML spans and `extract_html` elided): ```json {"type":"standard","title":"Agent-based model","namespace":{"id":0,"text":""},"wikibase_item":"Q392811","titles":{"canonical":"Agent-based_model","normalized":"Agent-based model"},"pageid":985619,"lang":"en","dir":"ltr","revision":"1371720832","tid":"dea700ca-a286-11f1-8c40-0f1aba0ce6ba","timestamp":"2026-08-28T02:19:17Z","description":"Type of computational models","description_source":"local","content_urls":{"desktop":{"page":"https://en.wikipedia.org/wiki/Agent-based_model","revisions":"https://en.wikipedia.org/wiki/Agent-based_model?action=history","edit":"https://en.wikipedia.org/wiki/Agent-based_model?action=edit","talk":"https://en.wikipedia.org/wiki/Talk:Agent-based_model"},"mobile":{…}},"extract":"An agent-based model (ABM) is a computational model for simulating the actions and interactions of an autonomous agent to understand the behavior of a system and what governs its outcomes. It combines elements of game theory, complex systems, emergence, computational sociology, multi-agent systems, and evolutionary programming. Monte Carlo methods are used to understand the stochasticity of these models. Particularly within ecology, an ABM is also called an individual-based model (IBM). A review of literature on individual-based models, agent-based models, and multiagent systems shows that ABMs are used in many scientific domains including biology, ecology, and social science. Agent-based modeling is related to, but distinct from, the concept of a multi-agent system."} ``` Machine check: ``` $ jq -e '(.extract|type=="string") and (.extract|length>50) and (.title=="Agent-based model")' true REFERENCE_TASK_PASS ``` No `Authorization` header, no cookie sent, no key. One request, 0.163 s. --- ## 2. Error shape `GET /api/rest_v1/page/summary/Zzzz_no_such_page_ag3ntsearch` → **HTTP 404** in 0.871 s, `content-type: application/json; charset=utf-8`, `cache-control: s-maxage=600`: ```json {"status":404,"type":"Internal error"} ``` The spec (§3) documents 404 as **"Unknown page title"**. The live body says "Internal error". The status code is correct and a client keyed on it is fine; a client that reads `type` would misdiagnose a typo as a server fault. Recorded as a docs/contract mismatch; one of the two reasons `docs` is 7. --- ## 3. Machine-readable surface `GET https://en.wikipedia.org/api/rest_v1/?spec` → HTTP 200, `application/json`, 106,848 bytes. ```json {"openapi":"3.0.1","swagger":null,"title":"Wikimedia REST API","version":"1.0.0","paths":46,"summary_paths":["/page/summary/{title}"]} ``` `info`: `termsOfService: https://wikimediafoundation.org/wiki/Terms_of_Use`, `contact: the Wikimedia Services team`, `license: Apache2`. `servers`: `/api/rest_v1` (Production) and `https://test.wikimedia.org/api/rest_v1` (Sandbox). `info.description` (verbatim; it is the operator's usage text inside the schema and is quoted as data): ```untrusted-content This API provides cacheable and straightforward access to Wikimedia content and data, in machine-readable formats. Caution: The REST Sandbox executes calls against the production database by default. To avoid unintended edits to live content, select the sandbox server (test.wikimedia.org) from the server dropdown before making POST, PUT, PATCH, or DELETE requests. ### Global Rules - Limit your clients to no more than 200 requests/s to this API. Each API endpoint's documentation may detail more specific usage limits. - Set a unique `User-Agent` or `Api-User-Agent` header that allows us to contact you quickly. Email addresses or URLs of contact pages work well. By using this API, you agree to Wikimedia's [Terms of Use](https://wikimediafoundation.org/wiki/Terms_of_Use) and [Privacy Policy](https://wikimediafoundation.org/wiki/Privacy_policy). Unless otherwise specified in the endpoint documentation below, content accessed via this API is licensed under the [CC-BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/) and [GFDL](https://www.gnu.org/copyleft/fdl.html) licenses, and you irrevocably agree to release modifications or additions made through this API under these licenses. Check the [Wikimedia REST API documentation](https://www.mediawiki.org/wiki/Wikimedia_REST_API) for background and details. ### Endpoint documentation Please consult each endpoint's documentation for details on: - Licensing information for the specific type of content and data served via the endpoint. - Stability markers to inform you about development status and change policy, according to [our API version policy](https://www.mediawiki.org/wiki/API_versioning). - Endpoint specific usage limits. ``` The `/page/summary/{title}` GET operation: summary "Get basic metadata and simplified article introduction."; description states "Stability: stable" and points to wikitech-l / mediawiki-api-announce for breaking changes; responses `200` ("The summary for the given page"), `301` (title not normalized), `302` (redirect page; `redirect=false` to suppress), `404` ("Unknown page title"), `default` ("Error"). **Note the two published rate numbers disagree**: 200 req/s here vs 5 req/s (unauthenticated REST) in the Robot policy. Both are the operator's words. A conservative agent plans on 5. --- ## 4. Permission sources, re-fetched from the sandbox All four policy pages returned HTTP 200 and the sentences quoted in §0 were found verbatim in the collected HTML (stripped). Additional verbatim sentences captured: - UA policy: "This change is most likely to affect scripts (bots) accessing Wikimedia websites such as Wikipedia automatically, via api.php or otherwise, and command line programs. If you operate a bot, please send a User-Agent header identifying the bot in a way that isn't going to be confused with many other bots, and supplying some way of contacting you, the operator … The contact information should be given as an email address, a website, or a wiki user … For example: User-Agent: CoolBot/0.0 (https://example.org/coolbot/; coolbot@example.org) generic-library/0.0" and "Do not copy a browser's user agent for your bot, as bot-like behavior with a browser's user agent will be assumed malicious." - Robot policy: "Bots that repeatedly try to get around these guidelines or rate limits, and/or threaten the stability of the sites may be blocked." and "If you're making read requests, do not emulate a browser - do not store cookies or execute javascript". - Access policy: "The User-Agent header can include a link to a user page on a Wikimedia wiki, a URL for a relevant external website, or an email address." and "Authenticated API requests receive higher rate limits. Wikimedia APIs use OAuth 2.0 access tokens for authentication." Nothing in any of them is addressed to a model or attempts to redirect the reader's task. --- ## 5. Discovery surface | URL | Result | |---|---| | `https://en.wikipedia.org/robots.txt` | 200, 711 lines. `User-agent: *` block: `Allow: /w/api.php?action=mobileview&` / `Allow: /w/load.php?` / `Allow: /api/rest_v1/?doc` / `Allow: /w/rest.php/site/v1/sitemap` / `Disallow: /w/` / `Disallow: /api/` / `Disallow: /trap/` / `Disallow: /wiki/Special:` … | | `https://en.wikipedia.org/.well-known/security.txt` | **200**: `Contact: mailto:security@wikimedia.org` / `Expires: 2029-03-31T09:00:00.000Z` / `Acknowledgments: https://security.wikimedia.org/hall-of-fame/` / `Preferred-Languages: en` / `Policy: https://www.mediawiki.org/wiki/Reporting_security_bugs` | | `https://en.wikipedia.org/llms.txt` | 404 (HTML "Not Found" page). | | OpenAPI | 3.0.1 at `/api/rest_v1/?spec` (§3). | | MCP | none official. | --- ## 6. Egress log Collected to `transcripts/tmp-wikipedia-e2e/egress.log` (gitignored), reproduced in full. 11 CONNECTs: 10 to the four allowlisted hosts, 1 operator-initiated control test that was refused. ``` DEBUG Sep 05 13:12:53.440 [11]: sending stored logs NOTICE Sep 05 13:12:53.453 [11]: Initializing tinyproxy ... NOTICE Sep 05 13:12:53.458 [11]: Reloading config file (/etc/tinyproxy/tinyproxy.conf) WARNING Sep 05 13:12:53.462 [11]: You SHOULD set a UserName in the config file. Using current user instead. NOTICE Sep 05 13:12:53.464 [11]: Reloading config file finished DEBUG Sep 05 13:12:53.465 [11]: done sending stored logs CONNECT Sep 05 13:12:53.804 [11]: Connect (file descriptor 5): 172.20.0.3 CONNECT Sep 05 13:12:53.805 [11]: Request (file descriptor 5): CONNECT en.wikipedia.org:443 HTTP/1.1 CONNECT Sep 05 13:12:53.870 [11]: Established connection to host "en.wikipedia.org" using file descriptor 6. CONNECT Sep 05 13:12:53.976 [11]: Connect (file descriptor 5): 172.20.0.3 CONNECT Sep 05 13:12:53.977 [11]: Request (file descriptor 5): CONNECT en.wikipedia.org:443 HTTP/1.1 CONNECT Sep 05 13:12:54.021 [11]: Established connection to host "en.wikipedia.org" using file descriptor 6. CONNECT Sep 05 13:12:54.859 [11]: Connect (file descriptor 5): 172.20.0.3 CONNECT Sep 05 13:12:54.862 [11]: Request (file descriptor 5): CONNECT en.wikipedia.org:443 HTTP/1.1 CONNECT Sep 05 13:12:54.905 [11]: Established connection to host "en.wikipedia.org" using file descriptor 6. CONNECT Sep 05 13:12:55.217 [11]: Connect (file descriptor 5): 172.20.0.3 CONNECT Sep 05 13:12:55.218 [11]: Request (file descriptor 5): CONNECT en.wikipedia.org:443 HTTP/1.1 CONNECT Sep 05 13:12:55.266 [11]: Established connection to host "en.wikipedia.org" using file descriptor 6. CONNECT Sep 05 13:12:55.412 [11]: Connect (file descriptor 5): 172.20.0.3 CONNECT Sep 05 13:12:55.414 [11]: Request (file descriptor 5): CONNECT en.wikipedia.org:443 HTTP/1.1 CONNECT Sep 05 13:12:55.462 [11]: Established connection to host "en.wikipedia.org" using file descriptor 6. CONNECT Sep 05 13:12:55.556 [11]: Connect (file descriptor 5): 172.20.0.3 CONNECT Sep 05 13:12:55.558 [11]: Request (file descriptor 5): CONNECT en.wikipedia.org:443 HTTP/1.1 CONNECT Sep 05 13:12:55.602 [11]: Established connection to host "en.wikipedia.org" using file descriptor 6. CONNECT Sep 05 13:12:55.794 [11]: Connect (file descriptor 5): 172.20.0.3 CONNECT Sep 05 13:12:55.795 [11]: Request (file descriptor 5): CONNECT foundation.wikimedia.org:443 HTTP/1.1 CONNECT Sep 05 13:12:55.839 [11]: Established connection to host "foundation.wikimedia.org" using file descriptor 6. CONNECT Sep 05 13:12:56.042 [11]: Connect (file descriptor 5): 172.20.0.3 CONNECT Sep 05 13:12:56.044 [11]: Request (file descriptor 5): CONNECT wikitech.wikimedia.org:443 HTTP/1.1 CONNECT Sep 05 13:12:56.085 [11]: Established connection to host "wikitech.wikimedia.org" using file descriptor 6. CONNECT Sep 05 13:12:56.323 [11]: Connect (file descriptor 5): 172.20.0.3 CONNECT Sep 05 13:12:56.324 [11]: Request (file descriptor 5): CONNECT www.mediawiki.org:443 HTTP/1.1 CONNECT Sep 05 13:12:56.367 [11]: Established connection to host "www.mediawiki.org" using file descriptor 6. CONNECT Sep 05 13:12:56.613 [11]: Connect (file descriptor 5): 172.20.0.3 CONNECT Sep 05 13:12:56.614 [11]: Request (file descriptor 5): CONNECT www.mediawiki.org:443 HTTP/1.1 CONNECT Sep 05 13:12:56.656 [11]: Established connection to host "www.mediawiki.org" using file descriptor 6. CONNECT Sep 05 13:12:57.103 [11]: Connect (file descriptor 5): 172.20.0.3 CONNECT Sep 05 13:12:57.104 [11]: Request (file descriptor 5): CONNECT example.com:443 HTTP/1.1 NOTICE Sep 05 13:12:57.104 [11]: Proxying refused on filtered domain "example.com" ``` **Blocked attempts: 1, and it was mine.** `CONNECT example.com:443` → refused, client `curl: (7) CONNECT tunnel failed, response 403`. **Target-caused blocked egress attempts: 0.** The response carries `report-to`/`nel` headers naming `intake-logging.wikimedia.org`; that is a browser reporting endpoint, never contacted by curl, and is not a redirect. --- ## 7. Safety observations | Check | Result | |---|---| | Prompt injection / hidden text | None. `display:none` hits (63 in API:Etiquette, 7 in Access policy, 1 in UA policy) are all MediaWiki skin CSS (`.mw-parser-output .hlist .mw-empty-li{display:none}`) and the `` wrappers MediaWiki emits around `Special:MyLanguage` links; comments are `` and ``. No model-addressed imperative anywhere. Zero occurrences of `llm`/`assistant`/`ai agent` in API responses. | | Key / seed-phrase request | None. | | Unbounded approval | N/A. | | Env probe | None. | | Overcharge | N/A — $0. | | Malicious payload | None. API responses `application/json`; policy pages `text/html`. | | TLS | HTTP/2 over TLS on every request; HSTS `max-age=106384710; includeSubDomains; preload`; strict CSP on API responses. | | Secrets in URLs | None exist on the read path. | | PII requested | None. | | Cookies on a JSON read | **Observation, not a finding.** Five `Set-Cookie` headers on the reference response, including `WMF-Uniq` (unique token, one-year expiry, `Domain=.wikipedia.org`) and `GeoIP` (coarse location derived from the client IP). None is required for any later request; the Robot policy itself tells read clients "do not store cookies". Considered for a `session-hygiene` minor penalty and not applied: the behaviour is documented under the Privacy Policy the spec points to, and an agent that drops cookies is unaffected. | | `x-client-ip` echo | The response echoes the client's own egress IP. Not another party's data; redacted above as operator PII. | | `security.txt` | Present with a real contact. | | Rate-limit headers | None (`RateLimit-*`, `X-RateLimit-*`, `Retry-After` absent). Limits are policy text, not headers. | **Findings: none.** `safety.penalty_total: 0`. --- ## 8. Scoring rationale | Dimension | Rung | Why | |---|---|---| | `access` | **25** | Nothing beyond HTTP. The only requirement is a User-Agent string, which every HTTP client can set. OAuth exists solely to raise limits. | | `payment` | **25** | Free, no instrument. | | `interface` | **18** | REST with a published OpenAPI 3.0.1 document that describes the endpoint used, its stability marker, and its responses. No MCP. | | `completion` | **20** | One request, no human, no out-of-band knowledge — the spec named the endpoint and the rules; the UA format is on a linked policy page. | | `docs` | **7** | Versioned OpenAPI with stability markers; rate limits documented (twice, inconsistently); the 404 body contradicts the spec's description; no llms.txt. "Most of the above." | | `permissive-tos` | **awarded** | Published bot policy that explicitly permits robots on this endpoint with stated limits. | | `security-posture` | **awarded** | `security.txt` with a real contact and policy URL; no credential or secret in any URL; read path needs no standing authority. | | `permission.status` | `granted` | See §0; robots.txt counter-signal recorded. | Dimension vector emitted: `access 25, payment 25, interface 18, completion 20, docs 7`; bonuses `permissive-tos`, `security-posture`; penalties none. **Rubric ceiling observation:** dimension sum 95 + 10 bonus = 105, clamped to 100. As with frankfurter, the `docs: 7` deduction is invisible in the published number; this entry would score 100 with either bonus alone. --- ## 9. Sandbox feedback 1. `/out` writable; `collect` worked. 2. The transcript needed manual redaction of a per-client cookie and an IP echo. A `collect --redact` pass (Set-Cookie values, `x-client-ip`, `x-forwarded-for`) would remove a class of accidental operator-PII leaks from published evidence. 3. No problems.