From be8e8d698c547ede6dff093719b2017e4f415eb2 Mon Sep 17 00:00:00 2001 From: Dominik Schulz Date: Sun, 3 May 2020 19:11:58 +0200 Subject: [PATCH] Always copy passwords to clipboard is autoclip is set (#1316) Fixes #1255 Fixes #1317 RELEASE_NOTES=[BUGFIX] Simplify autoclip behavior Signed-off-by: Dominik Schulz --- go.mod | 1 + go.sum | 2 + pkg/action/commands.go | 5 +- pkg/action/copy_test.go | 1 + pkg/action/find.go | 2 +- pkg/action/find_test.go | 10 +- pkg/action/generate.go | 17 +--- pkg/action/history.go | 2 +- pkg/action/insert_test.go | 1 + pkg/action/show.go | 142 ++++++++++++++++----------- pkg/action/show_test.go | 12 ++- pkg/backend/rcs/noop/backend.go | 2 +- pkg/backend/rcs/noop/backend_test.go | 2 +- pkg/config/config.go | 2 +- pkg/config/config_test.go | 2 +- pkg/store/root/git.go | 5 +- pkg/store/sub/git_test.go | 2 +- tests/find_test.go | 11 ++- tests/show_test.go | 6 +- tests/tester.go | 2 +- 20 files changed, 125 insertions(+), 104 deletions(-) diff --git a/go.mod b/go.mod index eb4f8c184e..b83353bfb3 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/godbus/dbus v0.0.0-20190623212516-8a1682060722 github.com/gokyle/twofactor v1.0.1 github.com/golang/protobuf v1.4.0 + github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf // indirect github.com/hashicorp/go-multierror v1.1.0 github.com/hashicorp/golang-lru v0.5.4 github.com/jsimonetti/pwscheme v0.0.0-20160922125227-76804708ecad diff --git a/go.sum b/go.sum index 4558c47ac2..948dbf2c1d 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,8 @@ github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf h1:vc7Dmrk4JwS0ZPS6WZvWlwDflgDTA26jItmbSj83nug= +github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= diff --git a/pkg/action/commands.go b/pkg/action/commands.go index 195b06c3dd..4006ac4763 100644 --- a/pkg/action/commands.go +++ b/pkg/action/commands.go @@ -741,8 +741,9 @@ func (s *Action) GetCommands() []*cli.Command { Usage: "Copy the first line of the secret into the clipboard", }, &cli.BoolFlag{ - Name: "alsoclip, C", - Usage: "Copy the first line of the secret and show everything", + Name: "alsoclip", + Aliases: []string{"C"}, + Usage: "Copy the first line of the secret and show everything", }, &cli.BoolFlag{ Name: "qr", diff --git a/pkg/action/copy_test.go b/pkg/action/copy_test.go index acfa92d215..cb77bc1910 100644 --- a/pkg/action/copy_test.go +++ b/pkg/action/copy_test.go @@ -23,6 +23,7 @@ func TestCopy(t *testing.T) { ctx := context.Background() ctx = ctxutil.WithAlwaysYes(ctx, true) + ctx = ctxutil.WithAutoClip(ctx, false) act, err := newMock(ctx, u) require.NoError(t, err) require.NotNil(t, act) diff --git a/pkg/action/find.go b/pkg/action/find.go index 366b85dc76..c56622fbf3 100644 --- a/pkg/action/find.go +++ b/pkg/action/find.go @@ -24,9 +24,9 @@ func (s *Action) FindNoFuzzy(c *cli.Context) error { func (s *Action) Find(c *cli.Context) error { ctx := ctxutil.WithGlobalFlags(c) if c.IsSet("clip") { + ctx = WithOnlyClip(ctx, c.Bool("clip")) ctx = WithClip(ctx, c.Bool("clip")) } - if c.IsSet("force") { ctx = WithForce(ctx, c.Bool("force")) } diff --git a/pkg/action/find_test.go b/pkg/action/find_test.go index e279edfe33..d642404179 100644 --- a/pkg/action/find_test.go +++ b/pkg/action/find_test.go @@ -27,6 +27,7 @@ func TestFind(t *testing.T) { ctx := context.Background() ctx = ctxutil.WithTerminal(ctx, false) + ctx = ctxutil.WithAutoClip(ctx, false) act, err := newMock(ctx, u) require.NoError(t, err) require.NotNil(t, act) @@ -68,12 +69,7 @@ func TestFind(t *testing.T) { // testing the safecontent case ctx = ctxutil.WithShowSafeContent(ctx, true) c.Context = ctx - assert.NoError(t, act.Find(c)) - - out := strings.TrimSpace(buf.String()) - assert.Contains(t, out, "Found exact match in 'foo'") - assert.Contains(t, out, "with -f") - assert.Contains(t, out, "Copying password instead.") + assert.Error(t, act.Find(c)) buf.Reset() // testing with the clip flag set @@ -87,7 +83,7 @@ func TestFind(t *testing.T) { c.Context = ctx assert.NoError(t, act.Find(c)) - out = strings.TrimSpace(buf.String()) + out := strings.TrimSpace(buf.String()) assert.Contains(t, out, "Found exact match in 'foo'") buf.Reset() diff --git a/pkg/action/generate.go b/pkg/action/generate.go index d87a83251e..6989d44d4a 100644 --- a/pkg/action/generate.go +++ b/pkg/action/generate.go @@ -35,6 +35,7 @@ var ( // Generate and save a password func (s *Action) Generate(c *cli.Context) error { ctx := ctxutil.WithGlobalFlags(c) + ctx = WithClip(ctx, c.Bool("clip")) force := c.Bool("force") edit := c.Bool("edit") @@ -116,13 +117,13 @@ func (s *Action) generateCopyOrPrint(ctx context.Context, c *cli.Context, name, ) } - if ctxutil.IsAutoClip(ctx) || c.Bool("clip") { + if ctxutil.IsAutoClip(ctx) || IsClip(ctx) { if err := clipboard.CopyTo(ctx, name, []byte(password)); err != nil { return ExitError(ctx, ExitIO, err, "failed to copy to clipboard: %s", err) } } - if c.Bool("print") || c.Bool("clip") { + if c.Bool("print") || IsClip(ctx) { return nil } @@ -166,17 +167,7 @@ func (s *Action) generatePassword(ctx context.Context, c *cli.Context, length st return "", ExitError(ctx, ExitUsage, nil, "password length must not be zero") } - var corp bool - if c.IsSet("strict") || c.Bool("force") { - corp = c.Bool("strict") - } else { - var err error - corp, err = termio.AskForBool(ctx, "Do you have strict rules to include different character classes?", false) - if err != nil { - return "", err - } - } - if corp { + if c.Bool("strict") { return pwgen.GeneratePasswordWithAllClasses(pwlen) } diff --git a/pkg/action/history.go b/pkg/action/history.go index 4972e623aa..170a567376 100644 --- a/pkg/action/history.go +++ b/pkg/action/history.go @@ -31,7 +31,7 @@ func (s *Action) History(c *cli.Context) error { for _, rev := range revs { pw := "" if showPassword { - sec, err := s.Store.GetRevision(ctx, name, rev.Hash) + ctx, sec, err := s.Store.GetRevision(ctx, name, rev.Hash) if err != nil { out.Debug(ctx, "Failed to get revision '%s' of '%s': %s", rev.Hash, name, err) } diff --git a/pkg/action/insert_test.go b/pkg/action/insert_test.go index 38309f0ee3..7a1ff5a76b 100644 --- a/pkg/action/insert_test.go +++ b/pkg/action/insert_test.go @@ -24,6 +24,7 @@ func TestInsert(t *testing.T) { ctx := context.Background() ctx = ctxutil.WithAlwaysYes(ctx, true) ctx = ctxutil.WithTerminal(ctx, false) + ctx = ctxutil.WithAutoClip(ctx, false) act, err := newMock(ctx, u) require.NoError(t, err) require.NotNil(t, act) diff --git a/pkg/action/show.go b/pkg/action/show.go index fb67e5f0cf..6f8e486f05 100644 --- a/pkg/action/show.go +++ b/pkg/action/show.go @@ -22,18 +22,33 @@ const ( BinarySuffix = ".b64" ) +func showParseArgs(c *cli.Context) context.Context { + ctx := ctxutil.WithGlobalFlags(c) + if c.IsSet("clip") { + ctx = WithOnlyClip(ctx, c.Bool("clip")) + } + if c.IsSet("force") { + ctx = WithForce(ctx, c.Bool("force")) + } + if c.IsSet("qr") { + ctx = WithPrintQR(ctx, c.Bool("qr")) + } + if c.IsSet("password") { + ctx = WithPasswordOnly(ctx, c.Bool("password")) + } + if c.IsSet("revision") { + ctx = WithRevision(ctx, c.String("revision")) + } + ctx = WithClip(ctx, IsOnlyClip(ctx) || c.Bool("alsoclip")) + return ctx +} + // Show the content of a secret file func (s *Action) Show(c *cli.Context) error { - ctx := ctxutil.WithGlobalFlags(c) name := c.Args().First() - ctx = s.Store.WithConfig(ctx, name) - ctx = WithOnlyClip(ctx, c.Bool("clip")) - ctx = WithClip(ctx, c.Bool("alsoclip")) - ctx = WithForce(ctx, c.Bool("force")) - ctx = WithPrintQR(ctx, c.Bool("qr")) - ctx = WithPasswordOnly(ctx, c.Bool("password")) - ctx = WithRevision(ctx, c.String("revision")) + ctx := showParseArgs(c) + if key := c.Args().Get(1); key != "" { ctx = WithKey(ctx, key) } @@ -82,7 +97,7 @@ func (s *Action) show(ctx context.Context, c *cli.Context, name string, recurse // showHandleRevision displays a single revision func (s *Action) showHandleRevision(ctx context.Context, c *cli.Context, name, revision string) error { - sec, err := s.Store.GetRevision(ctx, name, revision) + ctx, sec, err := s.Store.GetRevision(ctx, name, revision) if err != nil { return s.showHandleError(ctx, c, name, false, err) } @@ -92,65 +107,74 @@ func (s *Action) showHandleRevision(ctx context.Context, c *cli.Context, name, r // showHandleOutput displays a secret func (s *Action) showHandleOutput(ctx context.Context, name string, sec store.Secret) error { - var content string - var key string - if HasKey(ctx) { - key = GetKey(ctx) + pw, body, err := s.showGetContent(ctx, name, sec) + if err != nil { + return err } - switch { - case key != "": - val, err := sec.Value(key) - if err != nil { - return s.showHandleYAMLError(ctx, name, key, err) - } - if IsClip(ctx) { - if err := clipboard.CopyTo(ctx, name, []byte(val)); err != nil { - return err - } - if IsOnlyClip(ctx) { - return nil - } - } - content = val - case IsPrintQR(ctx): - return s.showPrintQR(ctx, name, sec.Password()) - case IsClip(ctx): - if err := clipboard.CopyTo(ctx, name, []byte(sec.Password())); err != nil { + // we need to set AutoClip here because it's a per store config option + if ctxutil.IsAutoClip(ctx) { + ctx = WithClip(ctx, true) + } + + if pw == "" && body == "" { + return ExitError(ctx, ExitNotFound, store.ErrNoBody, store.ErrNoBody.Error()) + } + + if IsPrintQR(ctx) && pw != "" { + return s.showPrintQR(ctx, name, pw) + } + + if IsClip(ctx) && pw != "" { + if err := clipboard.CopyTo(ctx, name, []byte(pw)); err != nil { return err } - if IsOnlyClip(ctx) { - return nil - } - fallthrough - default: - switch { - case IsPasswordOnly(ctx): - content = sec.Password() - case ctxutil.IsShowSafeContent(ctx) && !IsForce(ctx): - content = sec.Body() - if content == "" { - if ctxutil.IsAutoClip(ctx) { - out.Yellow(ctx, "Info: %s.", store.ErrNoBody.Error()) - out.Yellow(ctx, "Copying password instead.") - return clipboard.CopyTo(ctx, name, []byte(sec.Password())) - } - return ExitError(ctx, ExitNotFound, store.ErrNoBody, store.ErrNoBody.Error()) - } - default: - buf, err := sec.Bytes() - if err != nil { - return ExitError(ctx, ExitUnknown, err, "failed to encode secret: %s", err) - } - content = string(buf) - } } - ctx = out.WithNewline(ctx, ctxutil.IsTerminal(ctx) && !strings.HasSuffix(content, "\n")) - out.Yellow(ctx, content) + if body == "" { + return nil + } + + ctx = out.WithNewline(ctx, ctxutil.IsTerminal(ctx) && !strings.HasSuffix(body, "\n")) + out.Yellow(ctx, body) return nil } +func (s *Action) showGetContent(ctx context.Context, name string, sec store.Secret) (string, string, error) { + // YAML key + if HasKey(ctx) { + key := GetKey(ctx) + val, err := sec.Value(key) + if err != nil { + return "", "", s.showHandleYAMLError(ctx, name, key, err) + } + return val, val, nil + } + + // first line of the secret only + if IsPrintQR(ctx) || IsOnlyClip(ctx) { + return sec.Password(), "", nil + } + if IsPasswordOnly(ctx) { + return sec.Password(), sec.Password(), nil + } + if ctxutil.IsAutoClip(ctx) && !IsForce(ctx) { + return sec.Password(), "", nil + } + + // everything but the first line + if ctxutil.IsShowSafeContent(ctx) && !IsForce(ctx) { + return "", sec.Body(), nil + } + + // everything (default) + buf, err := sec.Bytes() + if err != nil { + return "", "", ExitError(ctx, ExitUnknown, err, "failed to encode secret: %s", err) + } + return sec.Password(), string(buf), nil +} + // showHandleError handles errors retrieving secrets func (s *Action) showHandleError(ctx context.Context, c *cli.Context, name string, recurse bool, err error) error { if err != store.ErrNotFound || !recurse || !ctxutil.IsTerminal(ctx) { diff --git a/pkg/action/show_test.go b/pkg/action/show_test.go index 781b811e31..f093347ae2 100644 --- a/pkg/action/show_test.go +++ b/pkg/action/show_test.go @@ -26,6 +26,7 @@ func TestShow(t *testing.T) { ctx := context.Background() ctx = ctxutil.WithAlwaysYes(ctx, true) ctx = ctxutil.WithTerminal(ctx, false) + ctx = ctxutil.WithAutoClip(ctx, false) act, err := newMock(ctx, u) require.NoError(t, err) require.NotNil(t, act) @@ -90,14 +91,13 @@ func TestShow(t *testing.T) { assert.Equal(t, "---\nbar: zab", buf.String()) buf.Reset() - // show foo with safecontent enabled, should warn and copy the stuff + // show foo with safecontent enabled, should error out fs = flag.NewFlagSet("default", flag.ContinueOnError) assert.NoError(t, fs.Parse([]string{"foo"})) c = cli.NewContext(app, fs, nil) c.Context = ctx - assert.NoError(t, act.Show(c)) - assert.Contains(t, buf.String(), "no safe content to display, you can force display with -f.") + assert.Error(t, act.Show(c)) buf.Reset() // show foo with safecontent enabled, with the force flag @@ -139,6 +139,7 @@ func TestShowHandleRevision(t *testing.T) { ctx := context.Background() ctx = ctxutil.WithAlwaysYes(ctx, true) ctx = ctxutil.WithTerminal(ctx, false) + ctx = ctxutil.WithAutoClip(ctx, false) act, err := newMock(ctx, u) require.NoError(t, err) require.NotNil(t, act) @@ -159,7 +160,7 @@ func TestShowHandleRevision(t *testing.T) { c := cli.NewContext(app, fs, nil) c.Context = ctx - assert.NoError(t, act.showHandleRevision(ctx, c, "foo", "baz")) + assert.NoError(t, act.showHandleRevision(ctx, c, "foo", "HEAD")) buf.Reset() } @@ -170,6 +171,7 @@ func TestShowHandleError(t *testing.T) { ctx := context.Background() ctx = ctxutil.WithAlwaysYes(ctx, true) ctx = ctxutil.WithTerminal(ctx, false) + ctx = ctxutil.WithAutoClip(ctx, false) act, err := newMock(ctx, u) require.NoError(t, err) require.NotNil(t, act) @@ -201,6 +203,7 @@ func TestShowHandleYAMLError(t *testing.T) { ctx := context.Background() ctx = ctxutil.WithAlwaysYes(ctx, true) ctx = ctxutil.WithTerminal(ctx, false) + ctx = ctxutil.WithAutoClip(ctx, false) act, err := newMock(ctx, u) require.NoError(t, err) require.NotNil(t, act) @@ -225,6 +228,7 @@ func TestShowPrintQR(t *testing.T) { ctx := context.Background() ctx = ctxutil.WithAlwaysYes(ctx, true) ctx = ctxutil.WithTerminal(ctx, false) + ctx = ctxutil.WithAutoClip(ctx, false) act, err := newMock(ctx, u) require.NoError(t, err) require.NotNil(t, act) diff --git a/pkg/backend/rcs/noop/backend.go b/pkg/backend/rcs/noop/backend.go index 212fac4feb..05f04b69a8 100644 --- a/pkg/backend/rcs/noop/backend.go +++ b/pkg/backend/rcs/noop/backend.go @@ -79,7 +79,7 @@ func (g *Noop) Revisions(context.Context, string) ([]backend.Revision, error) { // GetRevision is not implemented func (g *Noop) GetRevision(context.Context, string, string) ([]byte, error) { - return []byte(""), nil + return []byte("foo\nbar"), nil } // Status is not implemented diff --git a/pkg/backend/rcs/noop/backend_test.go b/pkg/backend/rcs/noop/backend_test.go index d6bd941d0b..ce5732b418 100644 --- a/pkg/backend/rcs/noop/backend_test.go +++ b/pkg/backend/rcs/noop/backend_test.go @@ -27,6 +27,6 @@ func TestNoop(t *testing.T) { assert.Error(t, err) body, err := g.GetRevision(ctx, "foo", "bar") require.NoError(t, err) - assert.Equal(t, "", string(body)) + assert.Equal(t, "foo\nbar", string(body)) assert.NoError(t, g.RemoveRemote(ctx, "foo")) } diff --git a/pkg/config/config.go b/pkg/config/config.go index 42efe185a5..2a92174184 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -40,7 +40,7 @@ func New() *Config { Path: configLocation(), Root: &StoreConfig{ AskForMore: false, - AutoClip: true, + AutoClip: false, AutoImport: true, AutoSync: true, ClipTimeout: 45, diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index cae78cba84..754421ef7b 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -27,7 +27,7 @@ func TestNewConfig(t *testing.T) { assert.Equal(t, backend.GPGCLI, cfg.Root.Path.Crypto) assert.Equal(t, backend.GitCLI, cfg.Root.Path.RCS) assert.Equal(t, backend.FS, cfg.Root.Path.Storage) - assert.Equal(t, "Config[Root:StoreConfig[AskForMore:false,AutoClip:true,AutoImport:true,AutoSync:true,ClipTimeout:45,Concurrency:1,EditRecipients:false,NoColor:false,NoConfirm:false,NoPager:false,Notifications:true,Path:gpgcli-gitcli-fs+file:,SafeContent:false,UseSymbols:false],Mounts()]", cfg.String()) + assert.Equal(t, "Config[Root:StoreConfig[AskForMore:false,AutoClip:false,AutoImport:true,AutoSync:true,ClipTimeout:45,Concurrency:1,EditRecipients:false,NoColor:false,NoConfirm:false,NoPager:false,Notifications:true,Path:gpgcli-gitcli-fs+file:,SafeContent:false,UseSymbols:false],Mounts()]", cfg.String()) cfg = nil assert.Error(t, cfg.checkDefaults()) diff --git a/pkg/store/root/git.go b/pkg/store/root/git.go index f1e778af48..cb3281eba2 100644 --- a/pkg/store/root/git.go +++ b/pkg/store/root/git.go @@ -67,9 +67,10 @@ func (r *Store) ListRevisions(ctx context.Context, name string) ([]backend.Revis } // GetRevision will try to retrieve the given revision from the sync backend -func (r *Store) GetRevision(ctx context.Context, name, revision string) (store.Secret, error) { +func (r *Store) GetRevision(ctx context.Context, name, revision string) (context.Context, store.Secret, error) { ctx, store, name := r.getStore(ctx, name) - return store.GetRevision(ctx, name, revision) + sec, err := store.GetRevision(ctx, name, revision) + return ctx, sec, err } // GitStatus show the git status diff --git a/pkg/store/sub/git_test.go b/pkg/store/sub/git_test.go index b05a073d6e..b0027fb74a 100644 --- a/pkg/store/sub/git_test.go +++ b/pkg/store/sub/git_test.go @@ -63,5 +63,5 @@ func TestGitRevisions(t *testing.T) { sec, err := s.GetRevision(ctx, "foo", "bar") require.NoError(t, err) - assert.Equal(t, "", sec.Password()) + assert.Equal(t, "foo", sec.Password()) } diff --git a/tests/find_test.go b/tests/find_test.go index a6ec98b0bf..0ad49b61dc 100644 --- a/tests/find_test.go +++ b/tests/find_test.go @@ -30,24 +30,25 @@ func TestFind(t *testing.T) { out, err = ts.run("find bar") assert.NoError(t, err) - assert.Equal(t, "Found exact match in 'foo/bar'\nbaz", out) + assert.Contains(t, "Found exact match in 'foo/bar'\nbaz", out) out, err = ts.run("find Bar") assert.NoError(t, err) - assert.Equal(t, "Found exact match in 'foo/bar'\nbaz", out) + assert.Contains(t, "Found exact match in 'foo/bar'\nbaz", out) out, err = ts.run("find b") assert.NoError(t, err) - assert.Equal(t, "Found exact match in 'foo/bar'\nbaz", out) + assert.Contains(t, "Found exact match in 'foo/bar'\nbaz", out) _, err = ts.run("config safecontent true") require.NoError(t, err) out, err = ts.run("find bar") - assert.NoError(t, err) + assert.Error(t, err) assert.Contains(t, out, "no safe content to display") out, err = ts.run("find -f bar") assert.NoError(t, err) - assert.Contains(t, "Found exact match in 'foo/bar'\nbaz", out) + assert.Contains(t, out, "Found exact match in 'foo/bar'") + assert.Contains(t, out, "baz") } diff --git a/tests/show_test.go b/tests/show_test.go index a48d025742..359794e9cf 100644 --- a/tests/show_test.go +++ b/tests/show_test.go @@ -33,10 +33,8 @@ func TestShow(t *testing.T) { _, err = ts.run("show foo -force") assert.NoError(t, err) - out, err = ts.run("show fixed/secret") - assert.NoError(t, err) - assert.Contains(t, out, "safe content to display, you can force display with -f.") - assert.Contains(t, out, "Copying password instead.") + _, err = ts.run("show fixed/secret") + assert.Error(t, err) _, err = ts.run("config autoclip false") assert.NoError(t, err) diff --git a/tests/tester.go b/tests/tester.go index 5eb0323308..ced4eae83d 100644 --- a/tests/tester.go +++ b/tests/tester.go @@ -20,7 +20,7 @@ import ( const ( gopassConfig = `root: askformore: false - autoclip: true + autoclip: false autoimport: true autosync: false cliptimeout: 45