aboutsummaryrefslogtreecommitdiff
path: root/internal/apply/apply.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-09-17 14:02:24 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-09-17 14:02:24 +0200
commita65e8a0587d3e5c971bef3062dd0d8a3b5cb53b7 (patch)
tree82c606411fd814cb5003633cfa592393abcbe057 /internal/apply/apply.go
parentb44222fc2b061382dc601014cde287cc41b857ca (diff)
downloadkrino-a65e8a0587d3e5c971bef3062dd0d8a3b5cb53b7.tar.gz
krino-a65e8a0587d3e5c971bef3062dd0d8a3b5cb53b7.zip
a symlink in the sorted directory no longer redirects a step
Placeholders were already stopped from sending a file out of the directory a rule named. A symlink is a name too, and the directory krino sorts is by the threat model's own premise a place the internet writes into: a link named after a rule's destination sent moves and copies anywhere, and under (on-conflict overwrite) trashed a file OUTSIDE the sorted directory - while the plan showed the in-tree text and the run reported success. A step whose destination passes through a symlink at or below the directory being sorted now fails. A destination the configuration names outside it - ~/docs on another disk - is the user's own arrangement and is followed as before; both cases have a test. End to end, the review's scenario (Out -> ~/secret, overwrite): before: 1 applied, the user's file replaced and trashed after: 0 applied 1 failed, the file untouched, nothing trashed Two bookkeeping bugs in MkdirAllTracked went with it: a dangling symlink read as a missing directory and was then recorded as one krino had created - undo would have unlinked a link krino never made - and a directory created by someone else between the check and the mkdir was recorded the same way.
Diffstat (limited to 'internal/apply/apply.go')
-rw-r--r--internal/apply/apply.go6
1 files changed, 6 insertions, 0 deletions
diff --git a/internal/apply/apply.go b/internal/apply/apply.go
index b36035b..fdeed57 100644
--- a/internal/apply/apply.go
+++ b/internal/apply/apply.go
@@ -86,6 +86,12 @@ func ChainLogged(ctx context.Context, c plan.Chain, done func(i int, sr StepResu
stopWhy = "an earlier step in this chain failed"
break
}
+ if at := UnderSymlink(filepath.Dir(step.Dst), c.Root); at != "" {
+ results[i] = StepResult{Step: step, Status: "failed",
+ Detail: "a symlink inside the sorted directory redirects this step: " + at}
+ stopWhy = "an earlier step in this chain failed"
+ break
+ }
res := runStep(step, func(entry string) error {
if displaced == nil {
return nil