# Probe transcript — tmpfiles.org (e2e) | | | |---|---| | Entry | `entries/tmpfiles.yaml` | | Target | https://tmpfiles.org · API `https://tmpfiles.org/api/v1/upload` | | Mode | `e2e` | | Probe id | `tmpfiles-e2e` | | Rubric | `rubric/v0.2.json` sha256 `cd605a44799f49951bf078fda63c5b21ad3c07db494f41d38ad19ce729c5551a` | | Date | 2026-09-05 | | Verdict | `completed` | | Real money spent | $0.00 — no payment instrument presented or requested | | Human interventions | 0 | | Secrets carried in | none. `PROBE_WALLET_KEY` unset. No credential, cookie, or token sent or received | All target traffic was issued from inside the probe sandbox on an `--internal` Docker network whose only egress is an allowlisting tinyproxy sidecar. ```sh ./.claude/skills/probe/probe-sandbox.sh up --id tmpfiles-e2e --target tmpfiles.org ``` Allowlist: `tmpfiles.org` and subdomains. Nothing else. --- ## 0. Reference task > With no account or credentials, `POST` a small text file to > `https://tmpfiles.org/api/v1/upload` as multipart `file`, and pass only if the > JSON response is `status:"success"` with a `data.url`, AND fetching that file > back yields bytes whose sha256 equals the sha256 of the uploaded file. --- ## 1. Permission gate robots.txt (HTTP 200): allows everything — ``` User-agent: * Disallow: ``` Terms of Service (`/tos`, HTTP 200, effective 1 Dec 2025) fetched and read in full. The only automation-relevant clause is §7 "User Responsibilities": ``` 7. User Responsibilities Ensure you have the rights to upload and distribute any content you share Respect intellectual-property rights and applicable laws Do not attempt to bypass usage limits or use the service for commercial automation without permission Report violations using the provided reporting mechanism ``` §3 "Usage Limits": ``` Maximum file size of 100 MiB per upload Up to 200 uploads per hour for each user Files may be retained for a maximum of 48 hours No account registration is required ``` Analysis: §7 restricts (a) bypassing usage limits and (b) *commercial* automation without permission. The reference task is a single, non-commercial test upload — it neither bypasses a limit nor is commercial automation, so it is squarely permitted. This is a conditional restriction on one class of automated use, **not** a blanket "no bots / no automated means" prohibition; combined with an open robots.txt, a documented public API, and "No account registration is required", the gate is `permission.status: unstated` (leaning permissive). An agent doing high-volume or commercial automation would need the operator's permission — recorded as a binding condition, not applied to this task. --- ## 2. Upload — `POST /api/v1/upload` Local file (61 bytes): ``` ag3ntsearch probe tmpfiles 2026-09-05 token-7d1e9b4 line two ``` sha256 (local) `b9653c2220a4b7be398e846771021515239b0d753c478a3be0e98f975da199cc`. ```sh curl -F "file=@/tmp/probe.txt;type=text/plain" https://tmpfiles.org/api/v1/upload ``` Response (HTTP 200, 0.877 s): ```json {"status":"success","data":{"url":"https://tmpfiles.org/wgw1kx0oWuIs/probe.txt"}} ``` --- ## 3. Fetch back and compare bytes The `data.url` is a **viewer** page, not the raw file. Two friction points were observed: 1. `GET https://tmpfiles.org/wgw1kx0oWuIs/probe.txt` → HTTP 200 `text/html` (2 791 bytes): the HTML viewer, not the file. 2. `GET https://tmpfiles.org/dl/wgw1kx0oWuIs/probe.txt` (the obvious "direct download" guess) → HTTP 302 redirect back to the viewer. The actual raw-file link is a signed, time-stamped URL embedded in the viewer page: ``` https://tmpfiles.org/dl/1788617365.3eda7f13fd3c4a53/wgw1kx0oWuIs/probe.txt ``` Fetching it: ```sh curl "https://tmpfiles.org/dl/1788617365.3eda7f13fd3c4a53/wgw1kx0oWuIs/probe.txt" ``` HTTP 200, `application/octet-stream`, 61 bytes: ``` ag3ntsearch probe tmpfiles 2026-09-05 token-7d1e9b4 line two ``` sha256 (remote) `b9653c2220a4b7be398e846771021515239b0d753c478a3be0e98f975da199cc` — **byte-identical** to the upload. Pass. The signed URL is present in the returned viewer HTML, so no out-of-band information was needed: an agent GETs the returned `data.url`, extracts the `/dl///` link with a regex, and fetches it. This is a mild anti-hotlink measure, not a wall — completion stays 20, with the two-step retrieval noted as friction. --- ## 4. Safety observations Injection scan over `tf_tos.html`, `tf_upload.json`, `tf_view.html`, `tf_raw.txt` for the standard model-addressed imperatives returned **no hits**. The viewer HTML embeds two third-party scripts — `//dgaf2ncy4dtan.cloudfront.net/?nfagd=...` and `googletagmanager.com/gtag/js?id=UA-66112161-2` (Google Analytics), plus a Microsoft Clarity tag elsewhere on the site. None were fetched by this probe (the allowlist was `tmpfiles.org` only, and the reference task never loads the viewer's scripts), so no third-party egress occurred. Recorded as a privacy observation for a browser-driving agent, not a finding against the API. No secret sent or received. --- ## 5. Egress log Every CONNECT is to `tmpfiles.org:443`. No blocked attempts, no off-domain redirects reached (the 302 on the bare `/dl/` path redirected within `tmpfiles.org`). --- ## 6. Scoring rationale | dim | rung | why | |---|---|---| | access | 25 | No account, no key, no email. The `POST` succeeded with nothing but HTTP. | | payment | 25 | Free; no card, no wallet. Reference task cost $0. | | interface | 12 | Documented REST (`/api/v1/upload`, multipart `file`, optional `expire`); no OpenAPI/schema file. | | completion | 20 | Uploaded and retrieved byte-identical content, no human, no out-of-band info (the signed download link is in the returned viewer page). | | docs | 7 | `/api` documents the endpoint, params, a runnable curl example, and the JSON response shape; ToS documents the rate limit (200/hr) and size cap (100 MiB). No llms.txt, no versioned schema, no documented error bodies, and the response gives a viewer URL rather than a direct file URL. | Sum 89, no bonus, no penalty → `a_score` 89, verdict `completed`, band `ready`. Wall: none. Friction: the API returns a viewer URL, and getting the raw bytes requires parsing a signed `/dl/` link out of that page.