Skip to content

Commit 052b54c

Browse files
committed
feat!: forbid newlines in entry names
This simplifies parsing the output of, for example, `pago find`.
1 parent 897421c commit 052b54c

File tree

2 files changed

+39
-16
lines changed

2 files changed

+39
-16
lines changed

main.go

+21-16
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,17 @@ type Config struct {
7272
}
7373

7474
const (
75-
ageExt = ".age"
76-
agentSocketPath = "socket"
77-
defaultLength = "20"
78-
defaultPattern = "[A-Za-z0-9]"
79-
dirPerms = 0o700
80-
filePerms = 0o600
81-
maxStepsPerChar = 1000
82-
storePath = "store"
83-
version = "0.9.0"
84-
waitForSocket = 3 * time.Second
75+
ageExt = ".age"
76+
agentSocketPath = "socket"
77+
defaultLength = "20"
78+
defaultPattern = "[A-Za-z0-9]"
79+
dirPerms = 0o700
80+
filePerms = 0o600
81+
maxStepsPerChar = 1000
82+
nameInvalidChars = `[\n]`
83+
storePath = "store"
84+
version = "0.9.0"
85+
waitForSocket = 3 * time.Second
8586

8687
clipEnv = "PAGO_CLIP"
8788
confirmEnv = "PAGO_CONFIRM"
@@ -124,12 +125,16 @@ func (cmd *AddCmd) Run(config *Config) error {
124125
printRepr(cmd)
125126
}
126127

128+
file, err := entryFile(config.Store, cmd.Name)
129+
if err != nil {
130+
return err
131+
}
132+
127133
if !cmd.Force && entryExists(config.Store, cmd.Name) {
128134
return fmt.Errorf("entry already exists: %v", cmd.Name)
129135
}
130136

131137
var password string
132-
var err error
133138

134139
if cmd.Multiline {
135140
fmt.Fprintln(os.Stderr, "Reading password from stdin until EOF:")
@@ -167,11 +172,6 @@ func (cmd *AddCmd) Run(config *Config) error {
167172
return err
168173
}
169174

170-
file, err := entryFile(config.Store, cmd.Name)
171-
if err != nil {
172-
return nil
173-
}
174-
175175
if config.Git {
176176
if err := commit(
177177
config.Store,
@@ -840,6 +840,11 @@ func generatePassword(pattern string, length int) (string, error) {
840840

841841
// Map an entry's name to its file path.
842842
func entryFile(passwordStore, name string) (string, error) {
843+
re := regexp.MustCompile(nameInvalidChars)
844+
if re.MatchString(name) {
845+
return "", fmt.Errorf("entry name contains invalid characters matching %s", nameInvalidChars)
846+
}
847+
843848
file := filepath.Join(passwordStore, name+ageExt)
844849

845850
for path := file; path != "/"; path = filepath.Dir(path) {

main_test.go

+18
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,24 @@ func TestAddMultiline(t *testing.T) {
175175
}
176176
}
177177

178+
func TestAddNewline(t *testing.T) {
179+
output, err := withPagoDir(func(dataDir string) (string, error) {
180+
stdout, stderr, err := runCommandEnv(
181+
[]string{"PAGO_DIR=" + dataDir},
182+
"add", "ab\ncd", "--random",
183+
)
184+
return stdout + "\n" + stderr, err
185+
})
186+
if err == nil {
187+
t.Errorf("Command `add` should fail")
188+
}
189+
190+
re := "entry name contains invalid characters"
191+
if matched, _ := regexp.MatchString(re, output); !matched {
192+
t.Errorf("Expected %q in stdout", re)
193+
}
194+
}
195+
178196
func TestClip(t *testing.T) {
179197
_, err := withPagoDir(func(dataDir string) (string, error) {
180198
stdout, stderr, err := runCommandEnv(

0 commit comments

Comments
 (0)