feat: file-access confinement for clet md (security boundary)#96
Merged
feat: file-access confinement for clet md (security boundary)#96
clet md (security boundary)#96Conversation
12 tasks
- Add FileAccessPolicy with extension allowlist, cwd confinement, size caps, binary rejection - Add --allow-file and --allow-binary CLI flags - Integrate policy into AliasDispatcher.ResolveViewerContent and MarkdownClet.ExpandFiles - Document --root as starting-only (not sandbox) for pick-file/pick-directory - Add D-030 decisions entry - Update docs/threat-model.md "File access scope" section - Add unit tests (FileAccessPolicyTests) and smoke tests (FileAccessPolicySmokeTests) Agent-Logs-Url: https://github.com/gui-cs/clet/sessions/02d84ff1-fcf6-4d66-989b-67fecf6fd033 Co-authored-by: tig <585482+tig@users.noreply.github.com>
…move duplicate check Agent-Logs-Url: https://github.com/gui-cs/clet/sessions/02d84ff1-fcf6-4d66-989b-67fecf6fd033 Co-authored-by: tig <585482+tig@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix security issue with clet md file access
feat: file-access confinement for May 6, 2026
clet md (security boundary)
tig
approved these changes
May 6, 2026
…ariable' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
…ariable' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
…ariable' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
…ariable' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
…ariable' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
…ariable' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
…ne' may silently drop its earlier arguments' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
…ne' may silently drop its earlier arguments' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
tig
approved these changes
May 6, 2026
| // Create a .md file and run from its directory | ||
| string tmpDir = Path.Join (Path.GetTempPath (), $"clet-test-{Guid.NewGuid ()}"); | ||
| Directory.CreateDirectory (tmpDir); | ||
| string mdFile = Path.Combine (tmpDir, "test.md"); |
| public void AllowedExtension_InWorkingDirectory_Passes () | ||
| { | ||
| string cwd = Path.GetTempPath (); | ||
| string file = Path.Combine (cwd, "readme.md"); |
| [Fact] | ||
| public void AllowFile_BypassesExtensionAndCwdChecks () | ||
| { | ||
| string cwd = Path.Combine (Path.GetTempPath (), "clet-test-cwd2"); |
Member
|
@copilot tests are failing |
…CS0103 build error Agent-Logs-Url: https://github.com/gui-cs/clet/sessions/7731e404-c52b-4351-ba8b-c7560fb94836 Co-authored-by: tig <585482+tig@users.noreply.github.com>
Contributor
Author
Member
|
@copilot resolve the merge conflicts in this pull request |
…d-file-access-issue # Conflicts: # specs/decisions.md Co-authored-by: tig <585482+tig@users.noreply.github.com>
Contributor
Author
Member
|
@copilot resolve the merge conflicts in this pull request |
5 tasks
…d-file-access-issue # Conflicts: # specs/decisions.md Co-authored-by: tig <585482+tig@users.noreply.github.com>
Contributor
Author
Clicking a relative .md link in the viewer navigates to that file in-place, subject to the same FileAccessPolicy confinement as file loading (CWD sandbox, extension allowlist, size/binary checks). Links outside the sandbox or to non-markdown files remain SurfaceOnly (shown in status bar). HTTP/HTTPS/mailto links are always SurfaceOnly. Also fix integration test that used .tmp extension in temp dir, now creates .md file in CWD to satisfy FileAccessPolicy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
tig
approved these changes
May 6, 2026
--allow-file now accepts directories in addition to files. When a directory is given, any file under that tree bypasses the extension and CWD confinement checks (size/binary checks still apply). This makes the common case natural: clet md ../Terminal.Gui/README.md --allow-file ../Terminal.Gui Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the plain-text status shortcut with a Link CommandView. When the user hovers a hyperlink in the markdown, the URL appears in the status bar as a clickable link — clicking it opens in the default browser. When viewing a file, the link shows the filename with no URL (not clickable). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Toggle MouseHighlightStates between In (when a clickable URL is shown) and None (when showing a filename or status text). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
tig
added a commit
that referenced
this pull request
May 6, 2026
Clicking an http:// or https:// link in clet md now opens it in the default browser via Link.OpenUrl. These are safe — worst case the user sees a webpage. The URL is still shown in the status bar. Local .md file navigation (within CWD sandbox) will come when PR #96 merges. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
tig
added a commit
that referenced
this pull request
May 6, 2026
Merge develop which includes PR #96 (FileAccessPolicy, local .md link navigation, --allow-file directory support). MarkdownClet LinkClicked now: 1. Navigates local .md files within the sandbox (from #96) 2. Opens http/https links in the default browser (safe) 3. Shows the URL in the status bar as a clickable link Resolve decisions.md conflict: linear-range is D-032, file-access confinement is D-033. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
clet md FILEis an arbitrary file-read primitive. In agent contexts, positional args may be attacker-influenced via indirect prompt injection (e.g.clet md ~/.aws/credentials), exfiltrating content through rendered ANSI or--catstdout.Changes
FileAccessPolicy(new,src/Clet/Hosting/FileAccessPolicy.cs)Default-deny policy enforced on both the
--catpath (AliasDispatcher.ResolveViewerContent) and TUI path (MarkdownClet.ExpandFiles):.md,.markdown,.txtEscape hatches (
CommandLineRootparsing)--allow-file <path>(repeatable) — bypasses extension + cwd checks--allow-binary— disables NUL detectionSurface 2:
pick-file/pick-directory--rootDocumented honestly as starting directory, not a sandbox. Help text updated to: "Starting directory (not a sandbox — user can navigate freely)."
Documentation
docs/threat-model.md"File access scope" rewritten with full confinement modelspecs/decisions.mdD-032 appended (renumbered from D-030 → D-031 → D-032 to avoid conflicts with terminal escape sanitization and link policy entries)Tests
FileAccessPolicyTests— extension/cwd/binary/size/glob unit coverageFileAccessPolicySmokeTests— process-level refusal and bypass verification