You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@magpie.apache.org by "potiuk (via GitHub)" <gi...@apache.org> on 2026/10/24 22:08:45 UTC

[PR] fix(sandbox): give sandboxed prek its own home [magpie]

potiuk opened a new pull request, #1792:
URL: https://github.com/apache/magpie/pull/1792

   A commit made in a terminal runs prek's git hooks outside the sandbox, from their environments under `~/.cache/prek`, which the `~/.cache/` grant made sandbox-writable. A sandboxed command could plant code there that ran unsandboxed on the next terminal commit.
   
   Nothing excluded from the sandbox runs prek, so the settings `env`, which only Claude Code's own commands see, does the split:
   - `"PREK_HOME": "~/.cache/prek-sandbox"` gives sandboxed prek its own home (prek expands `~`).
   - `Edit(~/.cache/prek/**)` keeps sandboxed commands out of the terminal's home.
   - sandbox-lint requires both; verify check 19d, install Step U, the update drift item and the docs cover it. The first sandboxed `prek run` after the switch rebuilds its hook environments once.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@magpie.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] fix(sandbox): give sandboxed prek its own home [magpie]

Posted by "potiuk (via GitHub)" <gi...@apache.org>.
potiuk merged PR #1792:
URL: https://github.com/apache/magpie/pull/1792


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@magpie.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] fix(sandbox): give sandboxed prek its own home [magpie]

Posted by "github-advanced-security[bot] (via GitHub)" <gi...@apache.org>.
github-advanced-security[bot] commented on code in PR #1792:
URL: https://github.com/apache/magpie/pull/1792#discussion_r4368870184


##########
plugins/magpie-setup/skills/setup/setup_preflight/isolated.py:
##########
@@ -403,6 +404,192 @@
     ]
 
 
+def _git_config(home: Path, *args: str) -> str | None:
+    """`git config <args>` for the user's own global config, run from $HOME.
+
+    Only `--global` reads go through here; a repository's config is parsed
+    directly (`_rewrite_repo_config`), never handed to git.
+    """
+    env = {
+        k: v
+        for k, v in os.environ.items()
+        if k not in ("GIT_DIR", "GIT_WORK_TREE", "GIT_INDEX_FILE", "GIT_CONFIG")
+    }
+    try:
+        done = subprocess.run(
+            ["git", "config", *args],
+            cwd=home,
+            env=env,
+            capture_output=True,
+            text=True,
+            check=False,
+            timeout=5,
+        )
+    except (OSError, subprocess.SubprocessError):
+        return None
+    return done.stdout.strip() if done.returncode == 0 else None
+
+
+def _resolved(path: str, base: Path, home: Path) -> Path:
+    text = str(home) + path[1:] if path == "~" or path.startswith("~/") else path
+    candidate = Path(text) if text.startswith("/") else base / text
+    return Path(os.path.realpath(candidate))
+
+
+_SECTION_RE = re.compile(r'^\s*\[\s*([A-Za-z0-9.-]+)\s*(?:"([^"]*)")?\s*\](.*)$')
+_HOOKS_PATH_RE = re.compile(r"^\s*hookspath\s*=\s*(.*?)\s*$", re.I)
+
+
+def _shown(value: str) -> str:
+    """A config value fit for a message the model reads: quoted, short, no control characters."""
+    cleaned = "".join(ch for ch in value if ch.isprintable())[:120]
+    return repr(cleaned)
+
+
+def _core_hooks_path_lines(text: str) -> tuple[list[int], list[str]] | None:
+    """Indices and values of `[core] hooksPath` lines, or None when the file is not plain enough.
+
+    Only a plain file is rewritten: an `include` directive, a continued or
+    unparsable line means the value may come from elsewhere, so the caller only
+    reports.
+    """
+    indices: list[int] = []
+    values: list[str] = []
+    section = ""
+    for number, line in enumerate(text.splitlines()):
+        stripped = line.strip()
+        if not stripped or stripped[0] in "#;":
+            continue
+        header = _SECTION_RE.match(line)
+        if header:
+            rest = header.group(3).strip()
+            # Git allows a key after the header on the same line; anything but a
+            # comment there is not plain enough to rewrite.
+            if rest and rest[0] not in "#;":
+                return None
+            name = header.group(1).lower()
+            if name in ("include", "includeif"):
+                return None
+            section = name if header.group(2) is None else f"{name}.{header.group(2)}"
+            continue
+        if stripped.startswith("["):
+            return None  # a header this parser does not understand
+        if line.rstrip().endswith("\\"):
+            return None
+        match = _HOOKS_PATH_RE.match(line)
+        if section == "core" and not line.lstrip().startswith("[") and match:
+            value = match.group(1)
+            if len(value) >= 2 and value[0] == value[-1] == '"':
+                value = value[1:-1]
+            indices.append(number)
+            values.append(value)
+    return indices, values
+
+
+def _rewrite_repo_config(checkout: Path, home: Path, own_hooks: Path) -> list[str]:
+    """Drop `core.hooksPath` from `<checkout>/.git/config` when it names `own_hooks`.
+
+    The checkout is sandbox-writable and this runs outside the sandbox, so no
+    git command touches it: `.git` and `config` are opened without following a
+    symlink through one directory descriptor, and the rewrite goes to a fresh
+    temporary file renamed inside that directory.
+    """
+    try:
+        cfd = os.open(checkout, os.O_RDONLY | _DIRECTORY)
+    except OSError:
+        return []
+    try:
+        try:
+            gfd = os.open(".git", os.O_RDONLY | _DIRECTORY | _NOFOLLOW, dir_fd=cfd)
+        except OSError:
+            return []  # a linked worktree's .git file, a symlink, or none
+        try:
+            try:
+                fd = os.open("config", os.O_RDONLY | _NOFOLLOW, dir_fd=gfd)
+            except OSError:
+                return []
+            with os.fdopen(fd, encoding="utf-8", errors="strict") as handle:
+                try:
+                    text = handle.read()
+                except UnicodeDecodeError:
+                    text = None
+            config = checkout / ".git" / "config"
+            if text is None:
+                return [
+                    f"{config} could not be read as text; check that its core.hooksPath skips no hooks you need"
+                ]
+            parsed = _core_hooks_path_lines(text)
+            if parsed is None:
+                return [
+                    f"{config} may set core.hooksPath (it uses includes); check it skips no hooks you need"
+                ]
+            indices, values = parsed
+            if not values:
+                return []
+            if len(values) == 1 and _resolved(values[0], checkout, home) == own_hooks:
+                lines = text.splitlines(keepends=True)
+                kept = "".join(line for number, line in enumerate(lines) if number != indices[0])
+                # The result must read back plain and without the key, or nothing is written.
+                if _core_hooks_path_lines(kept) != ([], []):
+                    return [f"{config} sets core.hooksPath={_shown(values[0])}; unset it by hand"]
+                tmp_name = f".config.{secrets.token_hex(8)}.tmp"
+                try:
+                    tfd = os.open(
+                        tmp_name, os.O_WRONLY | os.O_CREAT | os.O_EXCL | _NOFOLLOW, 0o644, dir_fd=gfd
+                    )

Review Comment:
   ## CodeQL / Overly permissive file permissions
   
   Overly permissive mask in open sets file to world readable.
   
   [Show more details](https://github.com/apache/magpie/security/code-scanning/159)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@magpie.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org