fix: stabilization pass — fail-closed auth, ai flag validation, lint/config/security hardening, regression tests
gates / consistency-and-conventions (push) Successful in 26s
gates / consistency-and-conventions (push) Successful in 26s
17-point code-level audit executed via Explorer->Architect->Builder->Tester->Reviewer;
Reviewer accepted (APPROVE_WITH_NOTES; 3 block-list items resolved):
- security: telegram sender-owner AND-gate + TELEGRAM_OWNER_ID, matrix
MATRIX_ROOM_ID fail-closed, gpg --passphrase-fd 3 (no argv secret),
/dev/tcp positional-arg form (checkport/smb-client/share-lib/NET_PROBE),
eval deny-by-default + --no-command-execution carried by both chat bridges,
tty-gated --trust; config/{telegram,matrix}.env reference templates
- ai: all ExecStart flags validated against installed llama.cpp
(requested->error, default->omit+warn, CONFIG_REQUESTED_FLAGS); single-file
hf download failure rc=1 + no .hf-meta; LLAMACPP_HOST coherent;
POS_SUBCMDS + metadata gaps closed
- tooling: lint-conventions Bash-native rewrite (~24-30x faster, rules and
output byte-identical, :num restored); pos system uninstall covers all 12
libs + scale-tail + flags dir + systemd user units (|| true) + plugin
markers; anchored .bash_completion/.bashrc removal replaces sed -i '/pos/d'
- config: canonical load_env_file in lib/config-ui.sh (CRLF strip, env-wins,
XDG, LOADED_ENV_KEYS); 9 tools migrated; entertainment-lib collapsed to
wrappers; docker-compose deliberately unmigrated (source semantics)
- tests: first committed regression suite — tests/run-tests.sh zero-dep
runner + make test; 12 files / 179 checks / 0 skip / ~52s; hard skip
contract; systemd-analyze verify on generated unit PASS
Verified: make gen idempotent; make check green; make lint 0 FAIL, 0 WARN;
make test green; bash -n clean; git diff --check clean. Audit deliverables +
agent reports + AGENT_TODO Done entry included.
This commit is contained in:
@@ -25,6 +25,9 @@ attaches the latest pos command output or captured output (tail, max 4096 chars)
|
||||
to the question and notes on stderr which source was attached, its age, and a
|
||||
staleness warning once it is older than an hour (`ask` only; stdout stays pure
|
||||
answer). Use `capture` to save output from any command for `--last`.
|
||||
`--trust` and `--no-command-execution` control how (if at all) agent-detected
|
||||
command blocks run — see [Command execution posture](#command-execution-posture)
|
||||
below.
|
||||
|
||||
Backward compatibility: `pos ai gemini`, `pos ai openrouter`, and
|
||||
`pos ai llamacpp` still work as shorthand for `pos ai --provider gemini`,
|
||||
@@ -245,6 +248,31 @@ truncated). To disable: `unset __POS_CAPTURE_ACTIVE`.
|
||||
- On a non-2xx response the API's `error.message` is shown and the exit code is
|
||||
non-zero — so scripts can rely on `ask` failing loudly.
|
||||
|
||||
## Command execution posture
|
||||
|
||||
When a model's answer contains a ```sh/shell fenced code block, `ask`/`chat`
|
||||
offer to **run** it as a shell command on your machine. Because that code is
|
||||
untrusted, AI-generated external authority, the default is to **deny**:
|
||||
|
||||
- On an interactive terminal, `ask`/`chat` print the detected command and prompt
|
||||
`Run this command? [y/N]` — you must type **`y`** (or `Y`) to execute it.
|
||||
Enter or any other key **declines**: the command is added to your shell
|
||||
history (press ↑ to recall and edit it) but never run.
|
||||
- Without an interactive controlling tty (pipes, scripts, cron, the Telegram /
|
||||
Matrix bridges) commands are **never** executed — the code block is neither
|
||||
printed nor run.
|
||||
|
||||
`--trust` auto-executes detected commands **without** the confirmation prompt —
|
||||
but only on an interactive terminal. It is meant for trusted alias wrappers;
|
||||
do not pass it unless you fully trust the agent's output. It has no effect in a
|
||||
non-tty/chat-bridge context, which never executes commands anyway.
|
||||
|
||||
`--no-command-execution` disables execution entirely: the detected command is
|
||||
neither printed nor run and no confirmation prompt appears. It is the
|
||||
structural guard used by the chat bridges so that a future refactor cannot
|
||||
accidentally auto-execute model output. When both `--trust` and
|
||||
`--no-command-execution` are given, the last one on the command line wins.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- `ask` errors "No Gemini API key — run 'pos config ai'" → the key isn't set
|
||||
|
||||
@@ -24,14 +24,23 @@ health digests, backup alerts, firewall changes — and can be used directly.
|
||||
|
||||
```bash
|
||||
pos config telegram
|
||||
# edit TELEGRAM_BOT_TOKEN and TELEGRAM_CHAT_ID (masked input), then test:
|
||||
# edit TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID and TELEGRAM_OWNER_ID (masked input), then test:
|
||||
pos communication telegram sender test
|
||||
# config lives in ~/.config/linux_post_install/telegram.env (chmod 600)
|
||||
```
|
||||
|
||||
The bot token comes from @BotFather, the chat ID from @userinfobot (or by
|
||||
starting a chat and reading it). `pos config telegram` shows the current values
|
||||
(token masked).
|
||||
The bot token comes from @BotFather; the chat ID **and your numeric user ID
|
||||
(`TELEGRAM_OWNER_ID`)** from @userinfobot (or by starting a chat and reading
|
||||
it). `pos config telegram` shows the current values (token masked). The
|
||||
listener only executes commands when both the chat id and your owner id match
|
||||
— with `TELEGRAM_OWNER_ID` unset it runs but ignores every command
|
||||
(fail-closed, see below).
|
||||
|
||||
> **Token in the process list:** the Telegram Bot API embeds the bot token in
|
||||
> every API URL (`https://api.telegram.org/bot<TOKEN>/…`), so while a send or
|
||||
> poll runs the token is visible in `ps` output. This is inherent to the Bot
|
||||
> API — keep the token scoped to a single-purpose bot and revoke it in
|
||||
> BotFather if it ever leaks.
|
||||
|
||||
### Send
|
||||
|
||||
@@ -92,8 +101,13 @@ pos communication telegram listener --disable # remove it
|
||||
falls back to the bash command. Telegram only registers lowercase `[a-z0-9_]`
|
||||
names (1–32 chars); `/Status` or `/my-cmd` are skipped from the menu but still
|
||||
work when typed. An empty map clears the menu.
|
||||
- **Owner-only:** the bot only reacts to `TELEGRAM_CHAT_ID` (your own chat);
|
||||
others are ignored. `/help` lists mapped commands; unknown → "Unknown command".
|
||||
- **Owner-only (chat + account):** the bot executes only messages sent to
|
||||
`TELEGRAM_CHAT_ID` (your chat) **BY** `TELEGRAM_OWNER_ID` (your account) —
|
||||
both must match, so a forwarded message or an impersonator can't trigger
|
||||
commands. With `TELEGRAM_OWNER_ID` unset the daemon runs but ignores every
|
||||
command (fail-closed; `systemctl --user status pos-telegram-listener.service`
|
||||
shows the message-time log lines). `/help` lists mapped commands; unknown →
|
||||
"Unknown command".
|
||||
- **Runs as you:** mapped commands execute as your user with a 60s timeout,
|
||||
stdout + stderr are replied to the chat (truncated ~3800 chars; empty → `OK`).
|
||||
`sudo` inside a command needs a NOPASSWD rule.
|
||||
@@ -220,8 +234,10 @@ pos communication matrix listener --disable # remove it
|
||||
```
|
||||
- **Self-messaging:** the listener reacts to messages **from your own user id**
|
||||
(`MATRIX_USER_ID`) — in practice that means a second device (or another
|
||||
account) sending the commands. If `MATRIX_ROOM_ID` is set it only watches
|
||||
that room, otherwise every room you've joined. `/` and `!` both work
|
||||
account) sending the commands. It only watches the room set by
|
||||
`MATRIX_ROOM_ID`; with `MATRIX_ROOM_ID` unset the daemon runs but refuses to
|
||||
execute any command (fail-closed), so a bot account that has joined many
|
||||
rooms can't be tricked into running commands. `/` and `!` both work
|
||||
(`!status` = `/status`). `/help` lists mapped commands; unknown → "Unknown
|
||||
command".
|
||||
- **Runs as you:** mapped commands execute as your user with a 60s timeout,
|
||||
|
||||
Reference in New Issue
Block a user