Files
Devika Verma bd04516e17 fix(permissions): the secrets floor knows programs that publish, what git push sends and what a script does (OPE-236)
Point 4 of the review: "sends data out" was read from the command text alone,
so a .env leaving through git push, npm publish, twine upload, docker push,
gh gist create, rclone, mail or a script run (python upload.py) reached the
reviewer instead of a person. A live test of another agent's auto mode on
this machine showed the same blind spot with a pre-existing script that
builds its URL at run time.

4a. Known senders. review_facts.shell_sends_data: a program that sends or
    publishes, in any part of a compound command, counts as sending: git
    push / send-email; npm, yarn, pnpm publish; twine upload; cargo publish;
    gem push; docker and podman push; gh release upload, gh gist create, gh
    api with -f/-F/--input; aws s3 cp/sync/mv; az storage blob upload;
    gsutil cp/rsync/mv; rclone copy/sync/move; mail, mailx, sendmail, mutt;
    ngrok, cloudflared and ssh -R (they expose a port). sent_files learns the
    files these take: cloud-copy sources before the first remote, gh release
    upload / gh gist create / twine upload / gem push arguments, a mail
    client's attachment. npm/yarn/pnpm publish is judged by the folder it
    packs: a secret-named file in it (not .npmrc, .git, node_modules or the
    ignore files, which npm never packs) needs a person.

4b. git push checks what it would send. pushed_files asks git (no shell,
    GIT_OPTIONAL_LOCKS=0, 5 s timeout) for the files in @{u}..HEAD, else
    refs/remotes/<remote>/<branch>..HEAD from the arguments, else the whole
    branch for a first push; honours git -C and a cd earlier in the command.
    A secret-named file, or a blob whose contents carry a secret-looking
    value (first hundred files, size cap), needs a person. Outside a
    repository, or when git can't say, the reviewer decides as before. git
    add -A / . / -u names the untracked files it would stage, so the OPE-235
    secret fact (sentence unchanged) reaches the reviewer for a new .env
    going into the index; staging is local and is not a card.

4c. Scripts that are run are read. script_runs finds python/node/ruby/perl/
    php/bash/sh/pwsh/powershell script files, ./x.sh, pwsh -File, and -c /
    -e / -Command inline code (read off the whole command line, since the
    textual split would cut it at ';'). A script inside the session's
    folders, up to 256 KB, that uses the network (a URL; requests, urllib,
    httpx, aiohttp, socket, smtplib, boto3; node http/https/net/axios/fetch;
    Net::HTTP, LWP; Invoke-WebRequest; curl/wget/scp inside) makes the
    command "send": a secret-looking value in the script, a sensitive-named
    file it mentions, or a plainly named file it mentions whose contents
    carry a secret, needs a person. A script with no network use, or with
    network use and no secret, stays with the reviewer. Pre-existing scripts
    and scripts the agent wrote are read alike.

4d. The limit is written into the floor's docstring and the PR text: a
    module the script imports, a compiled program, a URL assembled from data
    at run time, or a push git can't describe, is not seen; the sandbox's
    network allowlist covers those, and OPE-242 (per-command outbound host
    report) would close the gap.

Shell dialect: tokens are split as the session's shell would (shlex for
bash, whitespace for PowerShell), so .\upload.py keeps its backslash. The
two strict expected failures from the previous commit now pass as ordinary
tests. SECRET_INVOLVED and SECRET_EGRESS_REASON unchanged.

Corpora: two gate rows appended (gate-141 gh gist create .env -> human_only;
gate-142 git push origin main -> reviewer_eligible, since the hermetic corpus
has no repository to ask). Dry run over every corpus: the same 12 legacy
rows as before plus four new human_only rows, no benign row.

Tests: tests/test_secrets_floor.py 155 -> 229 (push with a committed .env,
a committed key value, a first push, push from a subfolder, a clean push;
python upload.py building its URL from parts, a key in a script, a network
script naming a plain file with a key, node/bash/ps1/ruby scripts, inline
-c/-e/-Command code; scripts with no network use, no secrets, outside the
folders, missing or over the cap stay with the reviewer; npm publish with
and without a secret file; git add -A naming an untracked .env).
2026-10-29 11:24:13 +05:30
..