Split out of issue #115 — part 1 of 3. #115 was scoped too large to finish in one sitting and died three times to infrastructure kills before producing anything. Do only the work below. The sibling parts (assertLinterIsContainerised operator-splitting, and the Dockerfile.lint citation) are tracked separately and are out of scope here — do not touch assertLinterIsContainerised.
The defect
In cmd/vaultik/lintdocker_test.go on next (d257f8f), heredocTerminator treats any<< on a joined code line as a here-document opener. shellCode then discards every following line until one equals that terminator word exactly. So a << that is not a here-document opener yields a word that never appears, and scanning of everything below it in that file stops, permanently and silently.
Three forms, all real:
<< inside a quoted string.
<< inside an inline comment (only whole-line # comments are stripped).
cat <<-\EOF — a normal way to quote a terminator — yields the word \EOF, which never matches the real EOF line.
Demonstrated by appending to the realscript/lint, after main "$@":
echo"bitmask note: 1<<3"
golangci-lint run --config .golangci.yml ./...
make test stays green: ok sneak.berlin/go/vaultik/cmd/vaultik 1.312s. An unconditional host lint invocation in the gate script itself is invisible.
This is the worse half of the parent issue because it needs no adversary. An ordinary later edit adding a shift, a quoted <<, or a <<-\EOF anywhere in a script disarms the guard for everything below it, with the suite still green.
Implementation requirements
In shellCode, fail loudly when a here-document is still open at end of file (terminate != "" after the loop). shellCode must report the error to its caller rather than swallow it — signature becomes something like func shellCode(contents string) ([]string, error). The error should name the line number and text of the opening line.
TestNoHostLintPathRemains wraps it so the failure names the offending script.
Extend TestShellCodeSeesCodeAndNotProse to cover an unterminated here-document and a << that is not one.
Tightening the opener test to an actual redirection is a bonus, not a substitute for requirement 1. Leaving the opener conservative is fine and is what the parent issue's plan chose: every non-opener << then reaches EOF unterminated and fails loudly rather than being silently skipped.
Do not re-litigate the containerised gate itself; it is verified and out of scope.
Definition of done
Each of these three mutations inserted into the realscript/lint, shown failingmake test with a message naming the offending script, then reverted. Output recorded verbatim in a comment on the PR:
the 1<<3 echo plus the host lint call shown above,
a cat <<-\EOF form,
a quoted-<< form.
The existing 17 scripts still scan clean (no false positives introduced).
make check green, evidence on the PR. script/cibuild is not required — this touches test code only.
Branch off next. PR based on next, notmain.
Commit title ends with a bare (closes #N) naming this issue's number — a bare #N, never a markdown link, or Gitea will not auto-close it.
Split out of [issue #115](https://git.eeqj.de/sneak/vaultik/issues/115) — **part 1 of 3**. #115 was scoped too large to finish in one sitting and died three times to infrastructure kills before producing anything. Do **only** the work below. The sibling parts (`assertLinterIsContainerised` operator-splitting, and the `Dockerfile.lint` citation) are tracked separately and are **out of scope here** — do not touch `assertLinterIsContainerised`.
## The defect
In `cmd/vaultik/lintdocker_test.go` on `next` (`d257f8f`), `heredocTerminator` treats **any** `<<` on a joined code line as a here-document opener. `shellCode` then discards every following line until one equals that terminator word exactly. So a `<<` that is not a here-document opener yields a word that never appears, and scanning of everything below it **in that file stops, permanently and silently**.
Three forms, all real:
* `<<` inside a quoted string.
* `<<` inside an inline comment (only whole-line `#` comments are stripped).
* `cat <<-\EOF` — a normal way to quote a terminator — yields the word `\EOF`, which never matches the real `EOF` line.
Demonstrated by appending to the **real** `script/lint`, after `main "$@"`:
```sh
echo "bitmask note: 1<<3"
golangci-lint run --config .golangci.yml ./...
```
`make test` stays green: `ok sneak.berlin/go/vaultik/cmd/vaultik 1.312s`. An unconditional host lint invocation in the gate script itself is invisible.
This is the worse half of the parent issue because **it needs no adversary**. An ordinary later edit adding a shift, a quoted `<<`, or a `<<-\EOF` anywhere in a script disarms the guard for everything below it, with the suite still green.
## Implementation requirements
1. In `shellCode`, **fail loudly when a here-document is still open at end of file** (`terminate != ""` after the loop). `shellCode` must report the error to its caller rather than swallow it — signature becomes something like `func shellCode(contents string) ([]string, error)`. The error should name the line number and text of the opening line.
2. `TestNoHostLintPathRemains` wraps it so the failure **names the offending script**.
3. Extend `TestShellCodeSeesCodeAndNotProse` to cover an unterminated here-document and a `<<` that is not one.
Tightening the opener test to an actual redirection is a **bonus, not a substitute** for requirement 1. Leaving the opener conservative is fine and is what the parent issue's plan chose: every non-opener `<<` then reaches EOF unterminated and fails loudly rather than being silently skipped.
Do **not** re-litigate the containerised gate itself; it is verified and out of scope.
## Definition of done
- Each of these three mutations inserted into the **real** `script/lint`, shown **failing** `make test` with a message naming the offending script, then reverted. Output recorded **verbatim** in a comment on the PR:
- the `1<<3` echo plus the host lint call shown above,
- a `cat <<-\EOF` form,
- a quoted-`<<` form.
- The existing 17 scripts still scan clean (no false positives introduced).
- `make check` green, evidence on the PR. `script/cibuild` is **not** required — this touches test code only.
- Branch off `next`. PR based on `next`, **not** `main`.
- Commit title ends with a bare ` (closes #N)` naming **this** issue's number — a bare `#N`, never a markdown link, or Gitea will not auto-close it.
clawbot
added this to the 1.0.0 milestone 2026-09-03 23:54:56 +02:00
clawbot
self-assigned this 2026-09-03 23:54:56 +02:00
Closed at sneak's instruction, 2026-09-05: this was opened by an agent running on another machine outside the managed fleet, under superseded rules. Reopen if the content is wanted.
Model: fable-5-1
Closed at sneak's instruction, 2026-09-05: this was opened by an agent running on another machine outside the managed fleet, under superseded rules. Reopen if the content is wanted.
Model: fable-5-1
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Split out of issue #115 — part 1 of 3. #115 was scoped too large to finish in one sitting and died three times to infrastructure kills before producing anything. Do only the work below. The sibling parts (
assertLinterIsContainerisedoperator-splitting, and theDockerfile.lintcitation) are tracked separately and are out of scope here — do not touchassertLinterIsContainerised.The defect
In
cmd/vaultik/lintdocker_test.goonnext(d257f8f),heredocTerminatortreats any<<on a joined code line as a here-document opener.shellCodethen discards every following line until one equals that terminator word exactly. So a<<that is not a here-document opener yields a word that never appears, and scanning of everything below it in that file stops, permanently and silently.Three forms, all real:
<<inside a quoted string.<<inside an inline comment (only whole-line#comments are stripped).cat <<-\EOF— a normal way to quote a terminator — yields the word\EOF, which never matches the realEOFline.Demonstrated by appending to the real
script/lint, aftermain "$@":make teststays green:ok sneak.berlin/go/vaultik/cmd/vaultik 1.312s. An unconditional host lint invocation in the gate script itself is invisible.This is the worse half of the parent issue because it needs no adversary. An ordinary later edit adding a shift, a quoted
<<, or a<<-\EOFanywhere in a script disarms the guard for everything below it, with the suite still green.Implementation requirements
shellCode, fail loudly when a here-document is still open at end of file (terminate != ""after the loop).shellCodemust report the error to its caller rather than swallow it — signature becomes something likefunc shellCode(contents string) ([]string, error). The error should name the line number and text of the opening line.TestNoHostLintPathRemainswraps it so the failure names the offending script.TestShellCodeSeesCodeAndNotProseto cover an unterminated here-document and a<<that is not one.Tightening the opener test to an actual redirection is a bonus, not a substitute for requirement 1. Leaving the opener conservative is fine and is what the parent issue's plan chose: every non-opener
<<then reaches EOF unterminated and fails loudly rather than being silently skipped.Do not re-litigate the containerised gate itself; it is verified and out of scope.
Definition of done
script/lint, shown failingmake testwith a message naming the offending script, then reverted. Output recorded verbatim in a comment on the PR:1<<3echo plus the host lint call shown above,cat <<-\EOFform,<<form.make checkgreen, evidence on the PR.script/cibuildis not required — this touches test code only.next. PR based onnext, notmain.(closes #N)naming this issue's number — a bare#N, never a markdown link, or Gitea will not auto-close it.clawbot referenced this issue2026-09-03 23:56:35 +02:00
clawbot referenced this issue2026-09-03 23:56:49 +02:00
Closed at sneak's instruction, 2026-09-05: this was opened by an agent running on another machine outside the managed fleet, under superseded rules. Reopen if the content is wanted.
Model: fable-5-1