From bd77d2e3a0ce5f9d572fde14aeed13ccd6a34dac Mon Sep 17 00:00:00 2001 From: dinosaursrarr Date: Tue, 7 May 2024 19:47:50 +0100 Subject: [PATCH] Validate appID before encrypting We've all done it. It's too easy to use the wrong key to encrypt with, whether you use the app name, the folder name, or get the hyphens wrong. Cropped up again recently with https://github.com/tidbyt/pixlet/issues/1071. If you're running pixlet encrypt from within the community repo, this will add a check that the provided key matches the ID field from some existing manifest. If not, you get an error. Thought about @jmanske's suggestions but I don't think pixlet can assume there'll be exactly one manifest in the commit to check against. You might be updating multiple apps, in which case, which should you check? Or you might be fixing a bad encryption, and not have any local edits. App names are generally unique enough that I think this works. --- cmd/encrypt.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/cmd/encrypt.go b/cmd/encrypt.go index 1b88a4e84d..c4284648ff 100644 --- a/cmd/encrypt.go +++ b/cmd/encrypt.go @@ -3,11 +3,15 @@ package cmd import ( "fmt" "log" + "os" + "path/filepath" "github.com/spf13/cobra" "go.starlark.net/starlark" + "tidbyt.dev/pixlet/manifest" "tidbyt.dev/pixlet/runtime" + "tidbyt.dev/pixlet/tools/repo" ) const PublicKeysetJSON = `{ @@ -40,6 +44,10 @@ func encrypt(cmd *cobra.Command, args []string) { } appID := args[0] + if err := validateAppID(args[0]); err != nil { + log.Fatalf("Cannot encrypt with appID '%s': %v", appID, err) + } + encrypted := make([]string, len(args)-1) for i, val := range args[1:] { @@ -54,3 +62,40 @@ func encrypt(cmd *cobra.Command, args []string) { fmt.Println(starlark.String(val).String()) } } + +func validateAppID(appID string) error { + cwd, err := os.Getwd() + if err != nil { + return fmt.Errorf("something went wrong with your local filesystem: %v", err) + } + if !repo.IsInRepo(cwd, "community") { + log.Printf("Skipping validation of appID since command is not being run from inside the community repo.") + return nil // Can only apply check if running from the community repo + } + root, err := repo.RepoRoot(cwd) + if err != nil { + return fmt.Errorf("something went wrong with your community repo: %v", err) + } + entries, err := os.ReadDir(filepath.Join(root, "apps")) + if err != nil { + return fmt.Errorf("something went wrong listing existing apps: %v", err) + } + for _, e := range entries { + if !e.IsDir() { + continue + } + f, err := os.Open(filepath.Join(root, "apps", e.Name(), manifest.ManifestFileName)) + if err != nil { + log.Printf("Skipping %s/%s/%s/%s: %v", root, "apps", e.Name(), manifest.ManifestFileName, err) + continue + } + m, err := manifest.LoadManifest(f) + if err != nil { + return fmt.Errorf("something went wrong loading manifest for %s: %v", e.Name(), err) + } + if m.ID == appID { + return nil + } + } + return fmt.Errorf("does not match manifest ID for any app in the community repo") +}