TestNoHostLintPathRemains in cmd/vaultik/lintdocker_test.go (on next, commit d257f8f) asserts that no script invokes golangci-lint except through docker. It does not hold that property. Two evasions, each demonstrated on the third review of pull request #114 by mutating the real script/lint with the suite left green.
(a) Phantom here-document silently blinds the rest of the file.heredocTerminator treats any << on a joined code line as a here-document opener, and shellCode then discards every following line until one equals that word. So a << in a quoted string or an inline comment (only whole-line # comments are stripped), or a cat <<-\EOF whose terminator word becomes \EOF, yields a word that never appears — and scanning of everything below it in that file stops, permanently and silently. Appending to the real script/lint:
echo"bitmask note: 1<<3"
golangci-lint run --config .golangci.yml ./...
leaves make test green. This needs no adversary: an ordinary later edit disarms the guard.
(b) assertLinterIsContainerised accepts any line where docker appears anywhere before the linter, so a one-line native fallback passes. Inserted into script/lint's main():
command -v docker >/dev/null 2>&1||{ golangci-lint run --config .golangci.yml ./...;return;}
Same run, same green — the escape hatch in its most natural spelling.
Not a live false green on the tree as it stands: all 17 current scripts were confirmed reachable by the scanner. This is a guard asserting a property it does not hold, which is what a later reader trusts instead of re-deriving the invariant.
Implementation requirements
In shellCode, fail loudly when a here-document is still open at end of file (terminate != "" after the loop). That alone converts all three forms in (a) from silent blindness into a named failure. shellCode will need to report the error to its caller rather than swallow it. Tightening the opener test to an actual redirection is a bonus, not a substitute for this.
In assertLinterIsContainerised, split the joined line on ;, &&, || and |, and require the command containing the linter to begin with docker.script/lint-fix's continuation-joined docker run … golangci-lint run … is a single command and must still pass.
Extend TestShellCodeSeesCodeAndNotProse to cover an unterminated here-document and a << that is not one.
Fix the citation at Dockerfile.lint:73-76: it says the PR records script/lint "exits 1 naming the lll finding", but that evidence block names a revive finding and says why. One word.
Do not re-litigate the containerised gate itself; it is verified and out of scope here.
Definition of done
Both mutations above — the 1<<3 echo plus host lint call, and the command -v docker || { …; return; } fallback — inserted into the real script/lint, each shown failingmake test with a message naming the offending script and line, then reverted. Output recorded verbatim on the PR.
The <<-\EOF and quoted-<< forms likewise shown to produce a named failure rather than silence.
script/lint-fix still passes the tightened assertion, and the existing 17 scripts still scan clean.
make check green, evidence on the PR. script/cibuild not required — this touches test code only.
Commit title ends (closes #N) with this issue's number; branch off next, PR based on next.
`TestNoHostLintPathRemains` in `cmd/vaultik/lintdocker_test.go` (on `next`, commit `d257f8f`) asserts that no script invokes `golangci-lint` except through `docker`. It does not hold that property. Two evasions, each demonstrated on the third review of [pull request #114](https://git.eeqj.de/sneak/vaultik/pulls/114) by mutating the real `script/lint` with the suite left green.
**(a) Phantom here-document silently blinds the rest of the file.** `heredocTerminator` treats any `<<` on a joined code line as a here-document opener, and `shellCode` then discards every following line until one equals that word. So a `<<` in a quoted string or an inline comment (only whole-line `#` comments are stripped), or a `cat <<-\EOF` whose terminator word becomes `\EOF`, yields a word that never appears — and scanning of everything below it in that file stops, permanently and silently. Appending to the real `script/lint`:
```sh
echo "bitmask note: 1<<3"
golangci-lint run --config .golangci.yml ./...
```
leaves `make test` green. This needs no adversary: an ordinary later edit disarms the guard.
**(b) `assertLinterIsContainerised` accepts any line where `docker` appears anywhere before the linter**, so a one-line native fallback passes. Inserted into `script/lint`'s `main()`:
```sh
command -v docker >/dev/null 2>&1 || { golangci-lint run --config .golangci.yml ./...; return; }
```
Same run, same green — the escape hatch in its most natural spelling.
Not a live false green on the tree as it stands: all 17 current scripts were confirmed reachable by the scanner. This is a guard asserting a property it does not hold, which is what a later reader trusts instead of re-deriving the invariant.
## Implementation requirements
1. In `shellCode`, **fail loudly when a here-document is still open at end of file** (`terminate != ""` after the loop). That alone converts all three forms in (a) from silent blindness into a named failure. `shellCode` will need to report the error to its caller rather than swallow it. Tightening the opener test to an actual redirection is a bonus, not a substitute for this.
2. In `assertLinterIsContainerised`, **split the joined line on `;`, `&&`, `||` and `|`, and require the command containing the linter to _begin_ with `docker`.** `script/lint-fix`'s continuation-joined `docker run … golangci-lint run …` is a single command and must still pass.
3. Extend `TestShellCodeSeesCodeAndNotProse` to cover an unterminated here-document and a `<<` that is not one.
4. Fix the citation at `Dockerfile.lint:73-76`: it says the PR records `script/lint` "exits 1 naming the `lll` finding", but that evidence block names a `revive` finding and says why. One word.
Do not re-litigate the containerised gate itself; it is verified and out of scope here.
## Definition of done
- Both mutations above — the `1<<3` echo plus host lint call, and the `command -v docker || { …; return; }` fallback — inserted into the real `script/lint`, each shown **failing** `make test` with a message naming the offending script and line, then reverted. Output recorded verbatim on the PR.
- The `<<-\EOF` and quoted-`<<` forms likewise shown to produce a named failure rather than silence.
- `script/lint-fix` still passes the tightened assertion, and the existing 17 scripts still scan clean.
- `make check` green, evidence on the PR. `script/cibuild` not required — this touches test code only.
- Commit title ends ` (closes #N)` with this issue's number; branch off `next`, PR based on `next`.
clawbot
added this to the 1.0.0 milestone 2026-08-11 13:54:29 +02:00
clawbot
self-assigned this 2026-08-11 13:54:29 +02:00
Branch fix-115-lint-scanner off next. All changes in cmd/vaultik/lintdocker_test.go plus one word in Dockerfile.lint.
shellCode becomes func shellCode(contents string) ([]string, error).
After the loop, a non-empty terminate is an error naming the line
number and text of the opening line. TestNoHostLintPathRemains wraps
it with require.NoError so the failure names the script. The opener
test in heredocTerminator is deliberately left conservative: any << still opens a here-document, so a quoted <<, an
inline-comment << and <<-\EOF all reach end of file
unterminated and fail loudly rather than being silently skipped.
assertLinterIsContainerised splits the joined line on &&, ||, ; and |, then requires the segment containing the linter to begin with docker (after stripping leading {/(). script/lint-fix's
continuation-joined docker run … golangci-lint run … contains none of
those operators, so it is one segment beginning with docker and still
passes on its merits; no exemption is added. The predicate is extracted
as a pure function so it gets its own table test covering the ||
fallback spelling.
TestShellCodeSeesCodeAndNotProse gains cases for an unterminated
here-document and for a << that is not one.
Dockerfile.lint:75 — the cited evidence names a revive finding, not lll. One word.
Evidence for the PR: both mutations from the third review plus the <<-\EOF and quoted-<< forms inserted into the real script/lint, each shown failing make test verbatim and reverted; all 17
current scripts confirmed still scanning clean; make check green.
## Plan
Branch `fix-115-lint-scanner` off `next`. All changes in
`cmd/vaultik/lintdocker_test.go` plus one word in `Dockerfile.lint`.
1. `shellCode` becomes `func shellCode(contents string) ([]string, error)`.
After the loop, a non-empty `terminate` is an error naming the line
number and text of the opening line. `TestNoHostLintPathRemains` wraps
it with `require.NoError` so the failure names the script. The opener
test in `heredocTerminator` is deliberately left conservative: any
`<<` still opens a here-document, so a quoted `<<`, an
inline-comment `<<` and `<<-\EOF` all reach end of file
unterminated and fail loudly rather than being silently skipped.
2. `assertLinterIsContainerised` splits the joined line on `&&`,
`||`, `;` and `|`, then requires the segment containing the linter to
*begin* with `docker` (after stripping leading `{`/`(`). `script/lint-fix`'s
continuation-joined `docker run … golangci-lint run …` contains none of
those operators, so it is one segment beginning with `docker` and still
passes on its merits; no exemption is added. The predicate is extracted
as a pure function so it gets its own table test covering the `||`
fallback spelling.
3. `TestShellCodeSeesCodeAndNotProse` gains cases for an unterminated
here-document and for a `<<` that is not one.
4. `Dockerfile.lint:75` — the cited evidence names a `revive` finding, not
`lll`. One word.
Evidence for the PR: both mutations from the third review plus the
`<<-\EOF` and quoted-`<<` forms inserted into the real
`script/lint`, each shown failing `make test` verbatim and reverted; all 17
current scripts confirmed still scanning clean; `make check` green.
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.
TestNoHostLintPathRemainsincmd/vaultik/lintdocker_test.go(onnext, commitd257f8f) asserts that no script invokesgolangci-lintexcept throughdocker. It does not hold that property. Two evasions, each demonstrated on the third review of pull request #114 by mutating the realscript/lintwith the suite left green.(a) Phantom here-document silently blinds the rest of the file.
heredocTerminatortreats any<<on a joined code line as a here-document opener, andshellCodethen discards every following line until one equals that word. So a<<in a quoted string or an inline comment (only whole-line#comments are stripped), or acat <<-\EOFwhose terminator word becomes\EOF, yields a word that never appears — and scanning of everything below it in that file stops, permanently and silently. Appending to the realscript/lint:leaves
make testgreen. This needs no adversary: an ordinary later edit disarms the guard.(b)
assertLinterIsContainerisedaccepts any line wheredockerappears anywhere before the linter, so a one-line native fallback passes. Inserted intoscript/lint'smain():Same run, same green — the escape hatch in its most natural spelling.
Not a live false green on the tree as it stands: all 17 current scripts were confirmed reachable by the scanner. This is a guard asserting a property it does not hold, which is what a later reader trusts instead of re-deriving the invariant.
Implementation requirements
shellCode, fail loudly when a here-document is still open at end of file (terminate != ""after the loop). That alone converts all three forms in (a) from silent blindness into a named failure.shellCodewill need to report the error to its caller rather than swallow it. Tightening the opener test to an actual redirection is a bonus, not a substitute for this.assertLinterIsContainerised, split the joined line on;,&&,||and|, and require the command containing the linter to begin withdocker.script/lint-fix's continuation-joineddocker run … golangci-lint run …is a single command and must still pass.TestShellCodeSeesCodeAndNotProseto cover an unterminated here-document and a<<that is not one.Dockerfile.lint:73-76: it says the PR recordsscript/lint"exits 1 naming thelllfinding", but that evidence block names arevivefinding and says why. One word.Do not re-litigate the containerised gate itself; it is verified and out of scope here.
Definition of done
1<<3echo plus host lint call, and thecommand -v docker || { …; return; }fallback — inserted into the realscript/lint, each shown failingmake testwith a message naming the offending script and line, then reverted. Output recorded verbatim on the PR.<<-\EOFand quoted-<<forms likewise shown to produce a named failure rather than silence.script/lint-fixstill passes the tightened assertion, and the existing 17 scripts still scan clean.make checkgreen, evidence on the PR.script/cibuildnot required — this touches test code only.(closes #N)with this issue's number; branch offnext, PR based onnext.Plan
Branch
fix-115-lint-scanneroffnext. All changes incmd/vaultik/lintdocker_test.goplus one word inDockerfile.lint.shellCodebecomesfunc shellCode(contents string) ([]string, error).After the loop, a non-empty
terminateis an error naming the linenumber and text of the opening line.
TestNoHostLintPathRemainswrapsit with
require.NoErrorso the failure names the script. The openertest in
heredocTerminatoris deliberately left conservative: any<<still opens a here-document, so a quoted<<, aninline-comment
<<and<<-\EOFall reach end of fileunterminated and fail loudly rather than being silently skipped.
assertLinterIsContainerisedsplits the joined line on&&,||,;and|, then requires the segment containing the linter tobegin with
docker(after stripping leading{/().script/lint-fix'scontinuation-joined
docker run … golangci-lint run …contains none ofthose operators, so it is one segment beginning with
dockerand stillpasses on its merits; no exemption is added. The predicate is extracted
as a pure function so it gets its own table test covering the
||fallback spelling.
TestShellCodeSeesCodeAndNotProsegains cases for an unterminatedhere-document and for a
<<that is not one.Dockerfile.lint:75— the cited evidence names arevivefinding, notlll. One word.Evidence for the PR: both mutations from the third review plus the
<<-\EOFand quoted-<<forms inserted into the realscript/lint, each shown failingmake testverbatim and reverted; all 17current scripts confirmed still scanning clean;
make checkgreen.clawbot referenced this issue2026-09-03 23:56:49 +02:00