Skip to content

fix: confine Cache file lookups to the configured directories (SLT-18)#74

Merged
vt128 merged 1 commit into
masterfrom
fix/slt-18-path-containment
Jun 13, 2026
Merged

fix: confine Cache file lookups to the configured directories (SLT-18)#74
vt128 merged 1 commit into
masterfrom
fix/slt-18-path-containment

Conversation

@vt128

@vt128 vt128 commented Jun 13, 2026

Copy link
Copy Markdown
Member

What

Cache.readFile joined a script-controlled name to each configured directory with no post-join containment check. filepath.Join cleans embedded .. segments, so a name like ../secret.star resolved above the configured directory and was read and executed. Both entry points reach this function: Cache.Run and, more importantly, load() — whose module strings are fully script-controlled, so an untrusted script could read any .star-parseable file the host process can reach.

(The absolute-path vector does not apply — filepath.Join neutralizes a leading /; only .. traversal escapes.)

Fix

withinDir rejects a candidate that climbs out of a directory via ... A name that escapes one configured dir but lands inside another configured dir is still served from that one; only a name escaping every dir falls through to not-found. In-tree and subdirectory access are unchanged.

Confinement is not a promised guarantee of New() (real sandboxing belongs to the host layer), so this is defense in depth rather than a fix to a stated invariant — but the directory search should not silently reach outside the directories it was given.

Test-first

TestCachePathContainment (Run + load() escape both rejected; in-tree + subdir access preserved) and TestCacheMultiDirSiblingAccess (the escape-one-dir-but-within-another case) fail before the fix.

Verification

go test -race -count=2 ./..., go vet, gofmt -l clean, Docker golang:1.19 race run green.

Backlog: SLT-18

Cache.readFile joined a script-controlled name to each configured dir
with no post-join check. filepath.Join cleans embedded ".." segments,
so a name like "../secret.star" — supplied to Run or, more importantly,
chosen by an untrusted script via load() — resolved above the configured
directory and read (and executed) a sibling or parent .star file.

Add a containment check (withinDir): a candidate that escapes a dir via
".." is skipped. A name that stays within a different configured dir is
still served from that one; only a name that escapes every configured
dir falls through to not-found. In-tree and subdirectory access are
unaffected.

Confinement is not a promised guarantee of New() (real sandboxing is the
host layer's job), so this is defense in depth, not a fix to a stated
invariant — but the directory search should not silently reach outside
the directories it was given.

Test-first: TestCachePathContainment (Run + load() escape both rejected,
in-tree/subdir access preserved) and TestCacheMultiDirSiblingAccess.
Backlog: SLT-18.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@codacy-production

codacy-production Bot commented Jun 13, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 22 complexity · 0 duplication

Metric Results
Complexity 22
Duplication 0

View in Codacy

🟢 Coverage 89.47% diff coverage · +0.31% coverage variation

Metric Results
Coverage variation +0.31% coverage variation (-1.00%)
Diff coverage 89.47% diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (bde646d) 2139 1932 90.32%
Head commit (8198ead) 2157 (+18) 1955 (+23) 90.64% (+0.31%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#74) 19 17 89.47%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@codecov

codecov Bot commented Jun 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 77.77778% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.67%. Comparing base (bde646d) to head (8198ead).

Files with missing lines Patch % Lines
starlight.go 77.77% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master      #74      +/-   ##
==========================================
+ Coverage   87.32%   87.67%   +0.35%     
==========================================
  Files           8        8              
  Lines        1672     1680       +8     
==========================================
+ Hits         1460     1473      +13     
+ Misses        130      127       -3     
+ Partials       82       80       -2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@vt128 vt128 merged commit 0b852e8 into master Jun 13, 2026
13 of 14 checks passed
@vt128 vt128 deleted the fix/slt-18-path-containment branch June 13, 2026 06:53
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