package host import ( "errors" "os" "path/filepath" "testing" "github.com/carlosframework/platform/internal/release" ) func TestPlan14PointerHistoryRootAndAgentTampering(t *testing.T) { for _, attack := range []string{"delete", "rename", "empty", "directory"} { t.Run(attack, func(t *testing.T) { opt, data := t.TempDir(), t.TempDir() p := &release.ChannelPointer{App: "console", Channel: "stable", Version: "v1", Digest: release.ManifestDigest([]byte("manifest"))} if err := pointerRatchet(true, opt, data, func(string) string { return "" }).Admit("bab", p); err != nil { t.Fatal(err) } root, agent := release.RootRatchetDir(opt), release.EdgeRatchetDir(data) if err := release.NewDigestRatchet(agent, []string{root}, false).Admit("bab", p); err != nil { t.Fatal(err) } mark := filepath.Join(agent, "bab", "console", "stable.digests") switch attack { case "delete": if err := os.Remove(mark); err != nil { t.Fatal(err) } case "rename": if err := os.Rename(mark, mark+".old"); err != nil { t.Fatal(err) } case "empty": if err := os.WriteFile(mark, nil, 0600); err != nil { t.Fatal(err) } case "directory": if err := os.Remove(mark); err != nil { t.Fatal(err) } if err := os.Mkdir(mark, 0700); err != nil { t.Fatal(err) } } legacy := &release.ChannelPointer{App: p.App, Channel: p.Channel, Version: p.Version} for _, reader := range []*release.DigestRatchet{release.NewDigestRatchet(root, []string{agent}, false), release.NewDigestRatchet(agent, []string{root}, false)} { if err := reader.Admit("bab", legacy); !errors.Is(err, release.ErrPointerWithoutDigests) { t.Fatalf("tampering admitted digestless pointer: %v", err) } } if err := release.NewDigestRatchet(root, []string{agent}, false).Admit("bab", p); err != nil { t.Fatalf("signed digest pointer refused: %v", err) } }) } root, agent := t.TempDir(), t.TempDir() mark := filepath.Join(agent, "bab", "console", "stable.digests") if err := os.MkdirAll(mark, 0700); err != nil { t.Fatal(err) } if err := release.NewDigestRatchet(root, []string{agent}, false).Admit("bab", &release.ChannelPointer{App: "console", Channel: "stable", Version: "v1"}); !errors.Is(err, release.ErrPointerWithoutDigests) { t.Fatalf("malformed additional deny failed open: %v", err) } }