Files
werkator/docs/prs/2026-10-17-PR#164-artifact-links-private-repos.md
claude-code 6badbcee7a
werkator build succeeded after 02:26
werkator/deploy build succeeded after 00:09
werkator/mutation build succeeded after 25:56
A link between two HTML artifacts of a private repository opens for the operator (v1.43.4) (#164)
Co-authored-by: claude-code <claude-code@javagil.de>
2026-10-17 16:36:39 +02:00

5.1 KiB

PR#164: A link between two HTML artifacts of a private repository opens for the operator

WARNING: This document describes only the change applied in this PR. It may already be outdated once the next PR is merged. Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation.

Problem

On vm4006 the scenario report of hs.hsadmin.ng opens, but each link on it answers 404 "no repository named 'hs.hsadmin.ng'". The same URL typed into the address bar answers 200. All relative links between HTML artifacts of a private repository fail the same way, e.g. the sub-pages of the Gradle test report.

Since PR#55 every artifact carries Content-Security-Policy: sandbox allow-scripts, so the artifact document has an opaque origin. A link clicked in it is a cross-site navigation for the browser. werkator.js writes the control-token cookie with SameSite=Strict, so the browser does not send it on that navigation. Without the cookie the private repository is hidden, and its routes answer 404 (PR#43).

Non-Goals

  • No change to the sandbox: artifacts keep sandbox allow-scripts, never with allow-same-origin.
  • No artifact cookie or signed artifact URLs.
  • No change to what the token permits: acting still needs the header X-werkator-Token.

Specification

… so that the operator can read a whole test report of a private repository.

  • Given an operator who has entered the control token in this browser
  • And a test report of a private repository whose index links to a sub-page
  • When the operator clicks that link on the index
  • Then the sub-page opens
Verified by

Scenario#164.02: The token entered before the update stays enough!

… so that no operator has to enter the token again.

  • Given an operator who entered the control token before version 1.43.4
  • And who has opened a Werkator page since the update
  • When the operator clicks a link on a report page of a private repository
  • Then the linked report page opens
Verified by

Scenario#164.03: A script in a report cannot read the token!

… so that a build cannot steal the operator's token through its report.

  • Given an operator who has entered the control token in this browser
  • And a report page whose script tries to read the token
  • When the operator opens that page
  • Then the script gets no token
Verified by

Solution

  • werkator.js writes and clears the cookie with SameSite=Lax. Lax sends it on a top-level GET navigation, also from an opaque origin, and on no cross-site subresource request or POST.
  • Why Lax is safe here:
    • The cookie gives visibility only. Restart, cancel and delete are POST and DELETE and read the token from the header X-werkator-Token alone; no GET route changes state.
    • A foreign page can now open a private page in the operator's browser by a link. It cannot read the answer, because the page is cross-origin to it.
    • A script in a sandboxed artifact has an opaque origin: it cannot read document.cookie or localStorage of Werkator, and its fetch or iframe requests to Werkator are cross-site subresource requests, which do not carry a Lax cookie.
  • Residual risk, new with Lax: a foreign page can open a private page in the operator's browser and time it, or count its frames, to tell a 200 from a 404. That way it can guess whether a private repository of a given name exists; with Strict it could not. The name is content (RFC 0003 D8), so this weakens D8 for an operator who visits such a page. The alternatives, a path-scoped artifact cookie or signed artifact URLs, cost a server-side token per artifact.
  • Checked in Chromium, on a local instance with a private repository and two linked HTML artifacts:
    • With the cookie written SameSite=Strict, the index opens from the address bar and its link answers 404.
    • With the token stored and the home page loaded once, the cookie is rewritten, and the link opens the sub-page.
    • A script in the artifact gets a SecurityError when it reads document.cookie.
  • The existing mirror on load rewrites every stored token, so a Strict cookie becomes Lax on the next page view.
  • Werkbaum: a node under #security.
  • Version 1.43.4, with an entry in the release notes.

Open Questions

None.