Skip to content

Confine the broker socket to the user's cache (SonarCloud #41–#44) - #48

Open
devin-ai-integration[bot] wants to merge 2 commits into
developfrom
devin/1794421873-server-path-confinement
Open

devin-ai-integration[bot] wants to merge 2 commits into
developfrom
devin/1794421873-server-path-confinement

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Summary

python -m tig_cli.broker <container> <home> passes both arguments straight to server.Broker, which used socket_path(home, container) (os.path.join(home, ".cache", "tig", container, ...)) for os.makedirs, bind, unlink of a stale socket, and a connect probe. A container like ../../x or /tmp/x would steer all of these outside the cache.

Broker.__init__ now gets its address from the new server.broker_address(container, home), which is the single trust-boundary check:

if not CONTAINER_NAME.fullmatch(container):   # [A-Za-z0-9][A-Za-z0-9_.-]* (Docker/Podman name rule)
    raise OSError(EINVAL)
home = os.path.abspath(home)
if not os.path.isdir(home): raise OSError(ENOTDIR)
root = <home>/.cache/tig
address = os.path.abspath(socket_path(home, container))
require address.startswith(root + os.sep) and dirname(dirname(address)) == root

Errors are raised as OSError, so broker.main already maps them to exit 69 (unavailable), and the client simply falls back to the slow path like any other broker failure. Real names (tig-vicar-<12 hex>) and real homes are unaffected; broker.py is untouched.

Alert Location Fix
#43 S8707 server.py:86 os.makedirs(dirname(self.address)) in Broker() Address comes from broker_address, confined to <home>/.cache/tig/<container>/
#44 S8707 server.py:700 server.bind(address) in _listen_unix Same: only a validated address reaches _listen_unix
#42 S8707 server.py:704 os.unlink(address) in _listen_unix Same
#41 S8703 server.py:713 probe.connect(address) in _answering Same; the "request" is a local AF_UNIX connect to the confined path

Tests (tests/test_broker.py): rejects traversing, absolute, dot-leading, empty, space and NUL container names with nothing created under home; rejects a missing or non-directory home; normalizes relative / .. homes; broker.main(["../../escaped", home]) returns 69. Full suite: pytest tests/ --no-cov -m "not integration" → 432 passed.

Link to Devin session: https://nasa-jpl-demo.devinenterprise.com/sessions/7a159dce623f4472ac339e1a75590320
Open in Devin Desktop: https://nasa-jpl-demo.devinenterprise.com/desktop/session/7a159dce623f4472ac339e1a75590320?variant=devin
Requested by: @HuiJun


🟢 Devin Review found nothing to fix · View findings · Follow Devin's work

Devin Review

The broker's container and home arrive as command-line arguments; validate
the container as a runtime container name and keep the socket, its
directory and any stale socket removed in its place under
<home>/.cache/tig/<container>.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@github-actions

github-actions Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

Project Requirements: PASS

PR #48 passes all three requirements. It adds input checks to the internal broker entry point (server.py broker_address) so the socket cannot be placed outside ~/.cache/tig//. The change is not user-facing, so no doc updates are needed. It is portable, using only the standard library and Docker/Podman-compatible naming. It comes with regression tests that run in CI.

Requirement Verdict Notes
1. Documentation parity Pass Not user-facing. server.py now checks the container and home arguments of the internal python -m tig_cli.broker <container> <home> entry point. The new broker_address() rejects names that do not match Docker/Podman naming (r"[A-Za-z0-9][A-Za-z0-9_.-]*"), turns a relative home into an absolute path, and rejects a home that is not a directory. The tig CLI starts the broker itself (broker.py:269) with names from spec.container_name(), which are always 'tig-vicar-<12 hex>' and always pass the check. Nothing a user does changes: no CLI option, config key, env var or socket location is touched. The README 'macOS broker' section ('unix socket in ~/.cache/tig/') is still accurate. Exit code 69 on a broker start failure already existed and is only reached through the internal entry point, which falls back to the API socket as documented. The pre-check hint is a false positive.
2. Broad deployability Pass Uses only the standard library (re, os). The name pattern matches the naming rules Docker and Podman share. No site-specific paths, hosts or credentials were added. The socket stays under the user's own ~/.cache/tig, as before, and behaves the same on Linux and macOS and on Python 3.9-3.12.
3. Test coverage Pass This is a hardening fix against path traversal through the broker's command-line arguments, and it has targeted regression tests in tig-cli/tests/test_broker.py. A parametrized test covers '', '.', '..', '../escaped', 'a/../../escaped', '/tmp/escaped', '.hidden', '-flag', a name with a space and a name with a NUL; each is refused and nothing is created under home. Other tests cover a home that is missing or is not a directory, a home path containing '..', a relative home made absolute, and exit code 69 from broker.main for a traversing name. They run in CI through test.yml (tig-cli/** paths, -m "not integration", Linux and macOS, Python 3.9-3.12). All 44 tests in test_broker.py passed locally.
Automated pre-check hints
  • tig-cli/src/ changed but neither tig-cli/README.md nor docs/ changed (requirement 1).

Evaluated at ed31328 · Devin session · workflow run

Criteria: .github/project-requirements/criteria.md. A fail blocks the merge; a maintainer can waive it by adding the requirements-waived label.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

…solves

Co-Authored-By: jason.han <hanhuijun@gmail.com>

This branch has not been deployed

No deployments
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