Skip to content

feat(web): add --auth-file so credentials don't pass through argv - #11

Open
TbusOS wants to merge 1 commit into
mainfrom
fix/web-auth-file
Open

feat(web): add --auth-file so credentials don't pass through argv#11
TbusOS wants to merge 1 commit into
mainfrom
fix/web-auth-file

Conversation

@TbusOS

@TbusOS TbusOS commented Aug 21, 2026

Copy link
Copy Markdown
Owner

Implements option (1) from #10--auth-file.

What changed

cli/engram/commands/web.py:

  • --auth-file PATH — reads USER:PASS from the first non-empty line. The
    secret sits behind filesystem permissions instead of being published through
    argv.
  • Permission warning — if the file is group- or other-readable, serve prints
    a warning naming the mode and the chmod 600 fix. A world-readable credential
    file would give back exactly what this route was meant to gain, so it should not
    fail silently.
  • Mutual exclusion — passing both --auth and --auth-file is an error rather
    than a silent precedence rule.
  • _parse_auth_pair(raw, source) — the USER:PASS split is factored out so
    both routes reject the same malformed input with the same wording, with the
    error naming which route it came from.
  • --auth help text now states that it is visible to other accounts via ps
    on a shared host, so the trade-off shows up at the point of use.

The hard refusal at web/server.py:101 is untouched — a non-loopback bind still
requires auth, with no bypass. This only adds a safe way to satisfy it.

Verification

$ engram web serve --help
  --auth USER:PASS  Enable HTTP Basic auth. Required for a non-loopback --host.
                    Visible to other accounts via ps on a shared host — prefer
                    --auth-file there.
  --auth-file PATH  Read USER:PASS from the first non-empty line of PATH. Use
                    this instead of --auth on any multi-user machine.

Exercised end to end against a real store: a 600-mode credential file, a
non-loopback bind, and a browser session over the LAN.

Not in this change

  • --auth-prompt (option 2 in web serve: --auth is the only credential route, and it leaks the password via the process list #10) — interactive entry, no argv/env/disk at all.
  • Environment-variable route (option 3) — weaker than the file, and worth a
    separate discussion about whether it earns its place.
  • Unit tests. The three paths worth covering are: a well-formed file, the
    permission warning, and the --auth / --auth-file conflict. Happy to add them
    in this PR if preferred over a follow-up.

serve refuses a non-loopback bind without auth, which is right — binding 0.0.0.0
exposes the store to the local network. But --auth USER:PASS was the only way to
satisfy that refusal, and on a shared host argv is world-readable: `ps -eo args`
prints every process's full command line to every account unless /proc carries
hidepid. So the control and the practice contradicted each other, and a user
following the error message verbatim published the secret to the whole box.

--auth-file reads USER:PASS from the first non-empty line of a path, putting the
secret behind filesystem permissions instead. It warns when the file is group- or
other-readable, since a world-readable credential file gives back exactly what the
route was meant to gain. --auth and --auth-file are mutually exclusive; --auth
stays for single-user machines and its help text now names the exposure.

The USER:PASS parse is factored into _parse_auth_pair() so both routes reject the
same malformed input with the same message.

Refs #10. --auth-prompt (option 2 in the issue) is not in this change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant