lightninglabs / lightninglabs/loop
Add Secret type for reading database password from file
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 595
- Forks
- 135
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 12
Description
Background
This issue tracks a follow-up suggestion from PR #1078: staticaddr: various fixes
Original Comment: https://github.com/lightninglabs/loop/pull/1078#discussion_r2894023390
Author: @starius
Nit for a follow-up PR if you like it.
I wish flags' parsing libraries provided a convenient way to pass password as files. Like:
Password string `long:"password" description:"Database user's password." from:"file"`Unfortunately it is not supported, but we can make a custom field type:
type Secret string func (s *Secret) UnmarshalFlag(v string) error { // Example convention: @/path/to/file => read from file, else raw value if strings.HasPrefix(v, "@") { b, err := os.ReadFile(strings.TrimPrefix(v, "@")) if err != nil { return err } *s = Secret(strings.TrimRight(string(b), "\r\n")) return nil } *s = Secret(v) return nil } type Opts struct { Password Secret `long:"password" description:"Database user's password or @file to read the password from it."` }
Context
PR #1078 added a //nolint:gosec comment to suppress a linter warning about the Password field in PostgresConfig. The comment suggests a better long-term solution: instead of just suppressing the lint warning, introduce a custom Secret type that supports reading passwords from files, avoiding plaintext passwords in CLI arguments or config files.
Proposed Change
Introduce a Secret string type that implements UnmarshalFlag with a convention where values prefixed with @ are treated as file paths. This allows users to pass --password @/path/to/secret to read the password from a file, while still supporting raw string values for backward compatibility.
This is a security improvement — passing secrets via files avoids leaking them through process listings (ps aux) and shell history.
Implementation Approach
- Add a
Secrettype in an appropriate package (e.g.,loopdbor a sharedconfigpackage). - Implement
UnmarshalFlag(string) erroron*Secretsogo-flagscalls it automatically. - If value starts with
@, read the file at the remaining path and trim trailing newlines. - Otherwise, use the raw value directly.
- Change
PostgresConfig.PasswordfromstringtoSecretinloopdb/postgres.go. - Update
DSN()and any other callers to castSecretback tostringwhere needed. - Update the field description to document the
@fileconvention. - The
//nolint:gosecannotation can likely be removed since the field type is no longer a rawstringnamedPassword.
Related
- PR #1078
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading loopdb/postgres.go and tracing PostgresConfig.Password through DSN() and its other callers. Check how go-flags invokes UnmarshalFlag, then implement the Secret behavior described in the issue and update the password field description. Done means @file values read and trim trailing newlines, raw values remain compatible, and the obsolete lint suppression is addressed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- databases, security
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100