Refuse a page that sets a cookie, reaches storage or carries a handler [#50] - #165
Merged
Conversation
#50] The privacy page promised that no cookie is set, that nothing is written into either browser storage area, and that no page needs scripting to be read. Nothing refused a page breaking any of the three, and the page said so on itself: the promise about scripting named the gap in its own sentence, that what was refused was a page fetching a script and a handler written into the page was refused by nothing. Two rows over every produced page close the readable half of that. The first refuses a meta element that sets a cookie and refuses any name a page would have to spell to reach a cookie, either browser storage area or a reporting call. The two halves are separated in the refusal because the repair is not the same. A meta element is a header this site chose to write into the document, which a host serves verbatim and a browser acts on with nothing running at all; a name is code that would have to run, and a refusal naming only one of the two sends the next person looking in the wrong half of the page. The second refuses an event handler attribute on an element and an address whose scheme is a script. That is the near miss the older row does not catch: it reads a script element's src attribute, so a page with no source anywhere and one handler on one button runs code in a reader's browser and passes every row this gate had. The fixture for it is a script element carrying its code inside the page, which is the shape that arrives without anybody thinking they have added a request. The privacy page now carries two of its promises as checked statements naming these rows, and the register keeps the shape it had. What is not covered stays written down and gets sharper rather than quieter: a script element with its code inside the page is still refused by nothing, and both rows read the names a page would have to spell rather than what it does, so a page reaching the same interface through a value none of those spellings finds is refused by nothing here. Both are promises on the page with the issue that would turn them into properties. Each row is shown to bite. With either one made to refuse nothing, three cases go red; with both in place the suite passes. Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was wrong
The privacy page made three promises about what a page here does to a reader's
browser and nothing refused a page breaking any of them. The page said so
itself, which is that register working as intended and is also the state this
change is about:
Both run 2026-08-16 against
72e7f2d.One of the three named the gap in its own sentence: what was refused was a page
fetching a script, and a handler written into the page was refused by nothing.
That is a real hole rather than a tidy one. The row about a script element reads
its
srcattribute, so a page with no source anywhere and one handler on onebutton runs code in a reader's browser and passes every row this gate had.
What this does
Two rows over every produced page, which is the readable half of #50.
page-touches-no-browser-storagerefuses a meta element that sets a cookie, andrefuses any name a page would have to spell to reach a cookie, either browser
storage area or a reporting call. The two halves are separated in the refusal
because the repair is not the same. A meta element is a header this site chose
to write into the document, which a host serves verbatim and a browser acts on
with nothing running at all. A name is code that would have to run. A refusal
naming only one of the two sends the next person looking in the wrong half of
the page.
page-carries-no-inline-handlerrefuses an event handler attribute on anelement, and an address whose scheme is a script. An address of that shape
carries no attribute name a handler pattern would find, and the row that reads
what a page references reads a host, which such an address does not have, so it
is refused here rather than by either of its neighbours.
The privacy page now carries two of its promises as checked statements naming
these rows. What is still not covered stays written down and gets sharper rather
than quieter. A script element carrying its code inside the page is refused by
nothing, and both rows read the names a page would have to spell rather than
what it does, so a page reaching the same interface through a value none of
those spellings finds is refused by nothing here. Both are promises on the page
with the issue that would turn them into properties, and the second is a bound
the rows print in their own comments as well.
Closes
Nothing. It does not close #50, and the reason is the other leg that issue asks
for rather than an omission here.
#50 asks for two legs and this is one of them. The other loads every produced
page in a headless browser, asserts that after load there is no cookie, nothing
in either storage area and no request that left the origin, and reds when the
browser cannot start. There is no browser in this tree to run it with:
Run 2026-08-16 against
72e7f2d. Pinning that browser is #63. So the clauseabout a page with a beacon redding the browser leg, the clause about zero
cross-origin requests after load and the clause about a browser that fails to
start are all untouched by this change, and the issue stays open on them.
What was run
The
needs-networkset was not asked for, which the gate prints above ratherthan this body leaving it out. Nothing in this change opens a window, needs a
display, binds anything, reaches the network or asks for elevation, and no test
here is skipped for any reason.
What the two rows report over the pages this build writes:
And what the privacy page says now, which is two statements moved out of the
promised register into the checked one:
All three run 2026-08-16 against
72e7f2d.Each row is shown to bite by switching it off and watching the suite go red.
With
decideBrowserStoragemade to refuse nothing:With
decideInlineHandlermade to refuse nothing:With both in place:
All three run 2026-08-16 against
72e7f2dwith the stated edit applied andreverted.
The near miss for the second row is the one somebody actually writes rather than
one that could not have failed. Its fixture is a script element carrying its
code inside the page, so the older row about a script source passes it and the
case asserts that it does:
Both run 2026-08-16 against
72e7f2d.The means
Go, as two rows in the table the invariant verb already reads, and no language,
runtime or dependency the tree does not carry. It fits for the reason that table
exists: a rule written as a shell block in a workflow has no suite that can
prove it bites and no way to run it on the machine where the mistake was made,
and both rows here are proved by deletion above. Adding a row is adding a row,
so the case that requires one violation fixture per row picked both of these up
without being asked.
The alternative was the browser, and it is not an alternative for these two. A
browser decides what a page does; these read what the build wrote, which is the
half that can be decided with no network and no browser and therefore the half
that belongs in the gate rather than behind a pin that does not exist yet.
Who read it
Nobody but me. This board has no second reader tonight and the ruleset requires
no approving review, so the evidence above stands in place of one rather than a
merge being read as a review.