fix: guard project IDs before path joins#527
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because no GitHub Actions runner was available. Make sure your repository has a runner available to run Copilot's review, or add a copilot-setup-steps.yml file specifying one with the runs-on attribute. See the docs for more details.
This PR centralizes and strengthens project ID validation to prevent path traversal when constructing filesystem paths, and documents the security learning.
Changes:
- Added a shared
is_valid_project_idguard and applied it beforebase_root.join(project_id)and inparse_request_payload. - Added Rust unit tests covering
./..,/,\, and benign interior-dot identifiers. - Updated Sentinel security notes to reflect the corrected threat model and prevention steps.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| apps/desktop/src-tauri/src/main.rs | Centralizes project ID validation before path joins and adds unit tests for traversal-related cases. |
| .jules/sentinel.md | Records the security note and prevention guidance for project ID path traversal. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current head20e0405814f72a91ff995dda72a30fe2fa558d3e. -
Head SHA:
20e0405814f72a91ff995dda72a30fe2fa558d3e -
Workflow run: 28570935323
-
Workflow attempt: 1
Coverage evidence
Coverage Evidence
- Head SHA:
20e0405814f72a91ff995dda72a30fe2fa558d3e - Required test evidence: supported repository test suites must pass.
- Required docstring evidence: repository-owned docstring gates must pass when configured; otherwise docstring coverage is advisory.
Rust coverage tooling (cargo-llvm-cov)
Updating crates.io index
Downloading crates ...
Downloaded cargo-llvm-cov v0.8.7
Installing cargo-llvm-cov v0.8.7
Updating crates.io index
Updating crates.io index
Downloading crates ...
Downloaded autocfg v1.5.0
Downloaded anyhow v1.0.102
Downloaded errno v0.3.14
Downloaded bitflags v2.11.1
Downloaded itoa v1.0.18
Downloaded shared_thread v0.2.0
Downloaded serde_spanned v1.1.1
Downloaded os_pipe v1.2.3
Downloaded xattr v1.6.1
Downloaded same-file v1.0.6
Downloaded shared_child v1.1.1
Downloaded cfg-if v1.0.4
Downloaded shell-escape v0.1.5
Downloaded lcov2cobertura v1.0.9
Downloaded lexopt v0.3.2
Downloaded toml_datetime v1.1.1+spec-1.1.0
Downloaded quote v1.0.45
Downloaded zmij v1.0.21
Downloaded termcolor v1.4.1
Downloaded walkdir v2.5.0
Downloaded rustc-demangle v0.1.27
Downloaded opener v0.8.4
Downloaded filetime v0.2.29
Downloaded camino v1.2.2
Downloaded glob v0.3.3
Downloaded fs-err v3.3.0
Downloaded toml_parser v1.1.2+spec-1.1.0
Downloaded duct v1.1.1
Downloaded unicode-ident v1.0.24
Downloaded serde_core v1.0.228
Downloaded tar v0.4.45
Downloaded serde_derive v1.0.228
Downloaded toml v1.1.2+spec-1.1.0
Downloaded ruzstd v0.8.3
Downloaded memchr v2.8.0
Downloaded cargo-config2 v0.1.44
Downloaded serde_json v1.0.149
Downloaded regex v1.12.3
Downloaded winnow v1.0.2
Downloaded aho-corasick v1.1.4
Downloaded quick-xml v0.39.4
Downloaded serde v1.0.228
Downloaded proc-macro2 v1.0.106
Downloaded bstr v1.12.1
Downloaded syn v2.0.117
Downloaded regex-syntax v0.8.10
Downloaded rustix v1.1.4
Downloaded regex-automata v0.4.14
Downloaded libc v0.2.186
Downloaded linux-raw-sys v0.12.1
Compiling memchr v2.8.0
Compiling serde_core v1.0.228
Compiling libc v0.2.186
Compiling proc-macro2 v1.0.106
Compiling aho-corasick v1.1.4
Compiling regex-syntax v0.8.10
Compiling quote v1.0.45
Compiling unicode-ident v1.0.24
Compiling rustix v1.1.4
Compiling regex-automata v0.4.14
Compiling bitflags v2.11.1
Compiling winnow v1.0.2
Compiling anyhow v1.0.102
Compiling zmij v1.0.21
Compiling linux-raw-sys v0.12.1
Compiling serde v1.0.228
Compiling autocfg v1.5.0
Compiling fs-err v3.3.0
Compiling toml_parser v1.1.2+spec-1.1.0
Compiling toml_datetime v1.1.1+spec-1.1.0
Compiling serde_spanned v1.1.1
Compiling syn v2.0.117
Compiling camino v1.2.2
Compiling cfg-if v1.0.4
Compiling serde_json v1.0.149
Compiling filetime v0.2.29
Compiling regex v1.12.3
Compiling bstr v1.12.1
Compiling toml v1.1.2+spec-1.1.0
Compiling xattr v1.6.1
Compiling serde_derive v1.0.228
Compiling os_pipe v1.2.3
Compiling shared_child v1.1.1
Compiling quick-xml v0.39.4
Compiling same-file v1.0.6
Compiling itoa v1.0.18
Compiling shared_thread v0.2.0
Compiling rustc-demangle v0.1.27
Compiling lcov2cobertura v1.0.9
Compiling duct v1.1.1
Compiling cargo-config2 v0.1.44
Compiling walkdir v2.5.0
Compiling tar v0.4.45
Compiling opener v0.8.4
Compiling lexopt v0.3.2
Compiling shell-escape v0.1.5
Compiling ruzstd v0.8.3
Compiling termcolor v1.4.1
Compiling glob v0.3.3
Compiling cargo-llvm-cov v0.8.7
Finished `release` profile [optimized] target(s) in 1m 03s
Installing /home/runner/.cargo/bin/cargo-llvm-cov
Installed package `cargo-llvm-cov v0.8.7` (executable `cargo-llvm-cov`)
- Result: PASS
Rust test coverage
- Result: FAIL
- Reason: Rust files changed, but no root Cargo.toml was found.
- Fix: add or point to the Cargo workspace manifest and run cargo coverage from that workspace.
Coverage Decision
- Result: FAIL
- Test evidence: not proven passing
- Docstring evidence: not proven passing when configured
- Failure count: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file (2 files)"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file (2 files)"]
R1 --> V1["required checks"]
OpenCode Review Overview
Pull request overviewOpenCode cannot approve yet because required coverage evidence did not pass. Review outcome1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
Coverage evidenceCoverage Evidence
Rust coverage tooling (cargo-llvm-cov)
Rust test coverage
Coverage Decision
Changed-File Evidence Mapflowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file (2 files)"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file (2 files)"]
R1 --> V1["required checks"]
|
|
Current-head fix verification for project-id path traversal PR:
Local verification on head
Decision: keep #527 as the canonical project-id path traversal PR pending current required checks. |
|
Security refresh applied from #525 to clear the shared cargo-audit blocker. Evidence:
Security Notes:
|
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current head43075cbbe0a9b32ef632a67d5b6103a55b1b7dd5. -
Head SHA:
43075cbbe0a9b32ef632a67d5b6103a55b1b7dd5 -
Workflow run: 28587462684
-
Workflow attempt: 1
Coverage evidence
Coverage Evidence
- Head SHA:
43075cbbe0a9b32ef632a67d5b6103a55b1b7dd5 - Required test evidence: supported repository test suites must pass.
- Required docstring evidence: repository-owned docstring gates must pass when configured; otherwise docstring coverage is advisory.
Rust coverage tooling (cargo-llvm-cov)
Updating crates.io index
Downloading crates ...
Downloaded cargo-llvm-cov v0.8.7
Installing cargo-llvm-cov v0.8.7
Updating crates.io index
Updating crates.io index
Downloading crates ...
Downloaded anyhow v1.0.102
Downloaded shared_child v1.1.1
Downloaded xattr v1.6.1
Downloaded shell-escape v0.1.5
Downloaded os_pipe v1.2.3
Downloaded walkdir v2.5.0
Downloaded shared_thread v0.2.0
Downloaded toml_datetime v1.1.1+spec-1.1.0
Downloaded itoa v1.0.18
Downloaded lexopt v0.3.2
Downloaded serde_derive v1.0.228
Downloaded termcolor v1.4.1
Downloaded unicode-ident v1.0.24
Downloaded quote v1.0.45
Downloaded zmij v1.0.21
Downloaded toml_parser v1.1.2+spec-1.1.0
Downloaded toml v1.1.2+spec-1.1.0
Downloaded bitflags v2.11.1
Downloaded serde v1.0.228
Downloaded ruzstd v0.8.3
Downloaded cargo-config2 v0.1.44
Downloaded winnow v1.0.2
Downloaded serde_json v1.0.149
Downloaded regex v1.12.3
Downloaded quick-xml v0.39.4
Downloaded aho-corasick v1.1.4
Downloaded bstr v1.12.1
Downloaded memchr v2.8.0
Downloaded tar v0.4.45
Downloaded syn v2.0.117
Downloaded serde_core v1.0.228
Downloaded rustc-demangle v0.1.27
Downloaded regex-syntax v0.8.10
Downloaded rustix v1.1.4
Downloaded glob v0.3.3
Downloaded proc-macro2 v1.0.106
Downloaded fs-err v3.3.0
Downloaded same-file v1.0.6
Downloaded camino v1.2.2
Downloaded duct v1.1.1
Downloaded autocfg v1.5.0
Downloaded filetime v0.2.29
Downloaded lcov2cobertura v1.0.9
Downloaded cfg-if v1.0.4
Downloaded regex-automata v0.4.14
Downloaded opener v0.8.4
Downloaded serde_spanned v1.1.1
Downloaded errno v0.3.14
Downloaded libc v0.2.186
Downloaded linux-raw-sys v0.12.1
Compiling memchr v2.8.0
Compiling serde_core v1.0.228
Compiling libc v0.2.186
Compiling proc-macro2 v1.0.106
Compiling aho-corasick v1.1.4
Compiling unicode-ident v1.0.24
Compiling regex-syntax v0.8.10
Compiling quote v1.0.45
Compiling regex-automata v0.4.14
Compiling rustix v1.1.4
Compiling autocfg v1.5.0
Compiling linux-raw-sys v0.12.1
Compiling anyhow v1.0.102
Compiling bitflags v2.11.1
Compiling serde v1.0.228
Compiling winnow v1.0.2
Compiling zmij v1.0.21
Compiling toml_parser v1.1.2+spec-1.1.0
Compiling fs-err v3.3.0
Compiling syn v2.0.117
Compiling toml_datetime v1.1.1+spec-1.1.0
Compiling serde_spanned v1.1.1
Compiling serde_json v1.0.149
Compiling camino v1.2.2
Compiling cfg-if v1.0.4
Compiling filetime v0.2.29
Compiling xattr v1.6.1
Compiling toml v1.1.2+spec-1.1.0
Compiling bstr v1.12.1
Compiling regex v1.12.3
Compiling serde_derive v1.0.228
Compiling os_pipe v1.2.3
Compiling shared_child v1.1.1
Compiling quick-xml v0.39.4
Compiling rustc-demangle v0.1.27
Compiling itoa v1.0.18
Compiling shared_thread v0.2.0
Compiling same-file v1.0.6
Compiling walkdir v2.5.0
Compiling duct v1.1.1
Compiling cargo-config2 v0.1.44
Compiling lcov2cobertura v1.0.9
Compiling opener v0.8.4
Compiling tar v0.4.45
Compiling shell-escape v0.1.5
Compiling glob v0.3.3
Compiling termcolor v1.4.1
Compiling lexopt v0.3.2
Compiling ruzstd v0.8.3
Compiling cargo-llvm-cov v0.8.7
Finished `release` profile [optimized] target(s) in 1m 05s
Installing /home/runner/.cargo/bin/cargo-llvm-cov
Installed package `cargo-llvm-cov v0.8.7` (executable `cargo-llvm-cov`)
- Result: PASS
Rust test coverage
- Result: FAIL
- Reason: Rust files changed, but no root Cargo.toml was found.
- Fix: add or point to the Cargo workspace manifest and run cargo coverage from that workspace.
Coverage Decision
- Result: FAIL
- Test evidence: not proven passing
- Docstring evidence: not proven passing when configured
- Failure count: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file (5 files)"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file (5 files)"]
R1 --> V1["required checks"]
Evidence --> S2["Docs: dependency-policy.md"]
S2 --> I2["operator or user guidance"]
I2 --> R2["Review risk: Docs: dependency-policy.md"]
R2 --> V2["docs review"]
…id-path-traversal
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current headc4cba319dd2fd8381c846d87b0d4c69f378a21d7. -
Head SHA:
c4cba319dd2fd8381c846d87b0d4c69f378a21d7 -
Workflow run: 28626245498
-
Workflow attempt: 1
Coverage evidence
Coverage Evidence
- Head SHA:
c4cba319dd2fd8381c846d87b0d4c69f378a21d7 - Required test evidence: supported repository test suites must pass.
- Required docstring evidence: repository-owned docstring gates must pass when configured; otherwise docstring coverage is advisory.
Rust coverage tooling (cargo-llvm-cov)
Updating crates.io index
Downloading crates ...
Downloaded cargo-llvm-cov v0.8.7
Installing cargo-llvm-cov v0.8.7
Updating crates.io index
Updating crates.io index
Downloading crates ...
Downloaded anyhow v1.0.102
Downloaded autocfg v1.5.0
Downloaded same-file v1.0.6
Downloaded lcov2cobertura v1.0.9
Downloaded itoa v1.0.18
Downloaded cfg-if v1.0.4
Downloaded serde_spanned v1.1.1
Downloaded shared_thread v0.2.0
Downloaded os_pipe v1.2.3
Downloaded xattr v1.6.1
Downloaded errno v0.3.14
Downloaded shell-escape v0.1.5
Downloaded glob v0.3.3
Downloaded shared_child v1.1.1
Downloaded rustc-demangle v0.1.27
Downloaded lexopt v0.3.2
Downloaded toml_datetime v1.1.1+spec-1.1.0
Downloaded termcolor v1.4.1
Downloaded opener v0.8.4
Downloaded walkdir v2.5.0
Downloaded quote v1.0.45
Downloaded fs-err v3.3.0
Downloaded duct v1.1.1
Downloaded filetime v0.2.29
Downloaded zmij v1.0.21
Downloaded serde_core v1.0.228
Downloaded aho-corasick v1.1.4
Downloaded tar v0.4.45
Downloaded serde v1.0.228
Downloaded ruzstd v0.8.3
Downloaded memchr v2.8.0
Downloaded serde_json v1.0.149
Downloaded cargo-config2 v0.1.44
Downloaded unicode-ident v1.0.24
Downloaded winnow v1.0.2
Downloaded regex v1.12.3
Downloaded quick-xml v0.39.4
Downloaded toml_parser v1.1.2+spec-1.1.0
Downloaded toml v1.1.2+spec-1.1.0
Downloaded bstr v1.12.1
Downloaded serde_derive v1.0.228
Downloaded syn v2.0.117
Downloaded proc-macro2 v1.0.106
Downloaded camino v1.2.2
Downloaded regex-syntax v0.8.10
Downloaded rustix v1.1.4
Downloaded bitflags v2.11.1
Downloaded regex-automata v0.4.14
Downloaded libc v0.2.186
Downloaded linux-raw-sys v0.12.1
Compiling memchr v2.8.0
Compiling serde_core v1.0.228
Compiling libc v0.2.186
Compiling proc-macro2 v1.0.106
Compiling aho-corasick v1.1.4
Compiling quote v1.0.45
Compiling unicode-ident v1.0.24
Compiling regex-syntax v0.8.10
Compiling rustix v1.1.4
Compiling winnow v1.0.2
Compiling anyhow v1.0.102
Compiling linux-raw-sys v0.12.1
Compiling zmij v1.0.21
Compiling serde v1.0.228
Compiling autocfg v1.5.0
Compiling bitflags v2.11.1
Compiling regex-automata v0.4.14
Compiling fs-err v3.3.0
Compiling serde_spanned v1.1.1
Compiling toml_datetime v1.1.1+spec-1.1.0
Compiling toml_parser v1.1.2+spec-1.1.0
Compiling syn v2.0.117
Compiling cfg-if v1.0.4
Compiling serde_json v1.0.149
Compiling camino v1.2.2
Compiling filetime v0.2.29
Compiling xattr v1.6.1
Compiling toml v1.1.2+spec-1.1.0
Compiling regex v1.12.3
Compiling bstr v1.12.1
Compiling serde_derive v1.0.228
Compiling shared_child v1.1.1
Compiling os_pipe v1.2.3
Compiling quick-xml v0.39.4
Compiling same-file v1.0.6
Compiling shared_thread v0.2.0
Compiling itoa v1.0.18
Compiling rustc-demangle v0.1.27
Compiling cargo-config2 v0.1.44
Compiling lcov2cobertura v1.0.9
Compiling duct v1.1.1
Compiling walkdir v2.5.0
Compiling opener v0.8.4
Compiling tar v0.4.45
Compiling lexopt v0.3.2
Compiling ruzstd v0.8.3
Compiling glob v0.3.3
Compiling shell-escape v0.1.5
Compiling termcolor v1.4.1
Compiling cargo-llvm-cov v0.8.7
Finished `release` profile [optimized] target(s) in 1m 05s
Installing /home/runner/.cargo/bin/cargo-llvm-cov
Installed package `cargo-llvm-cov v0.8.7` (executable `cargo-llvm-cov`)
- Result: PASS
Rust test coverage
- Result: FAIL
- Reason: Rust files changed, but no root Cargo.toml was found.
- Fix: add or point to the Cargo workspace manifest and run cargo coverage from that workspace.
Coverage Decision
- Result: FAIL
- Test evidence: not proven passing
- Docstring evidence: not proven passing when configured
- Failure count: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file (2 files)"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file (2 files)"]
R1 --> V1["required checks"]
Summary
base_root.join(project_id)path construction../..path components,/, and\, while preserving benign identifiers such asmy..id.projectIddirectly reachesapp_owned_root.Verification
cargo fmt --manifest-path apps/desktop/src-tauri/Cargo.toml --checknpm ci(local Node v24.16.0 emits repo engine warning; install succeeds)npm --workspace apps/desktop run buildcargo test --manifest-path apps/desktop/src-tauri/Cargo.toml project_id -- --nocapturepython3 scripts/checks/verify_security_notes.pypython3 scripts/checks/verify_supply_chain.pypython3 scripts/checks/security_gates.pygit diff --checkSupersedes the security intent of #494, whose branch currently contains broad unrelated workflow/design/package churn and remains merge-dirty.