mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
feat: Experimental Sandbox Support (#101)
* feat: Sandbox implementation with seatbelt * refactor: Remove concept of PM_CACHE * fix: Misc fixes * refactor: Sandbox for separation of boundaries * fix: Apply API * fix: Add support for sandbox cleanup * test: Add variable interpolation test * fix: Misc cleanup fixes * chore: Cleanup sandbox registry * chore: Cleanup sandbox policy * chore: Cleanup sandbox * fix: Misc cleanup fixes * fix: Remove violation mode * fix: Update config template * chore: Go mod cleanup * fix: Handle the case when package manager policy is explicitly disabled * fix: Sandbox executor * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Abhisek Datta <abhisek.datta@gmail.com> * test: Remove unused var * test: Add test for seatbelt sandbox driver * fix: Sandbox profile loader from file should use path for caching * test: Add policy test * feat: Add support for config templates * fix: Seatbelt translator handle glob * fix: Merge conflicts * fix: Fix sandbox policy generator for MacOS min permissions * fix: Sandbox path handling bugs * fix: Deny read to dangerous directories * fix: Deny read to dangerous directories * add sandbox e2e (#112) * fix: Sandbox E2E test * fix: Code review fixes * fix: Code review fixes * doc: Add sandbox debugging guide * doc: Update sandbox doc * docs: Add sandbox usage doc * fix: Use better error for sandbox without policy * fix: Add sandbox for npx * fix: Enable PTY for npm --------- Signed-off-by: Abhisek Datta <abhisek.datta@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Sahil Bansal <bansalsahil315@gmail.com>
This commit is contained in:
co-authored by
Copilot
Sahil Bansal
parent
c0122898ca
commit
9693428171
@@ -0,0 +1,94 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GlobToRegex converts a glob pattern to a Seatbelt-compatible regular expression.
|
||||
//
|
||||
// This implements gitignore-style pattern matching to match the behavior used
|
||||
// in filesystem permission systems.
|
||||
//
|
||||
// Supported patterns:
|
||||
// - * matches any characters except / (e.g., *.ts matches foo.ts but not foo/bar.ts)
|
||||
// - ** matches any characters including / (e.g., src/**/*.ts matches all .ts files in src/)
|
||||
// - ? matches any single character except / (e.g., file?.txt matches file1.txt)
|
||||
// - [abc] matches any character in the set (e.g., file[0-9].txt matches file3.txt)
|
||||
//
|
||||
// Note: This is designed for macOS sandbox (regex ...) syntax. The resulting regex
|
||||
// will be used in sandbox profiles like: (deny file-write* (regex "pattern"))
|
||||
//
|
||||
// Examples:
|
||||
// - "/path/to/*.txt" -> "^/path/to/[^/]*\\.txt$"
|
||||
// - "/path/**/file" -> "^/path/(.*/)?file$"
|
||||
// - "/tmp/file?.log" -> "^/tmp/file[^/]\\.log$"
|
||||
func GlobToRegex(globPattern string) string {
|
||||
result := normalizeGlobPathSeparator(globPattern)
|
||||
|
||||
// Escape regex special characters (except glob chars * ? [ ])
|
||||
// We need to escape: . ^ $ + { } ( ) | \
|
||||
result = escapeRegexChars(result)
|
||||
|
||||
// Escape unclosed brackets (no matching ])
|
||||
// This handles edge cases like "[abc" which should be treated literally
|
||||
result = escapeUnclosedBrackets(result)
|
||||
|
||||
// Convert glob patterns to regex (order matters - ** before *)
|
||||
// Use placeholders to avoid double-conversion
|
||||
|
||||
// 1. Handle **/ (globstar with slash)
|
||||
result = strings.ReplaceAll(result, "**/", "__GLOBSTAR_SLASH__")
|
||||
|
||||
// 2. Handle ** (globstar standalone)
|
||||
result = strings.ReplaceAll(result, "**", "__GLOBSTAR__")
|
||||
|
||||
// 3. Handle * (wildcard)
|
||||
result = strings.ReplaceAll(result, "*", "[^/]*")
|
||||
|
||||
// 4. Handle ? (single char wildcard)
|
||||
result = strings.ReplaceAll(result, "?", "[^/]")
|
||||
|
||||
// 5. Restore placeholders
|
||||
result = strings.ReplaceAll(result, "__GLOBSTAR_SLASH__", "(.*/)?")
|
||||
result = strings.ReplaceAll(result, "__GLOBSTAR__", ".*")
|
||||
|
||||
// Add anchors for exact matching
|
||||
return "^" + result + "$"
|
||||
}
|
||||
|
||||
// escapeRegexChars escapes regex special characters except glob wildcards.
|
||||
// Escapes: . ^ $ + { } ( ) |
|
||||
// Preserves: * ? [ ] \
|
||||
// Note: We don't escape backslash because it shouldn't appear in file path glob patterns
|
||||
func escapeRegexChars(s string) string {
|
||||
// Characters that need escaping in regex (excluding glob chars)
|
||||
// We don't include backslash here because:
|
||||
// 1. File paths on Unix don't contain backslashes
|
||||
// 2. We use backslash to escape regex chars, so escaping backslash would double them
|
||||
specialChars := []string{".", "^", "$", "+", "{", "}", "(", ")", "|"}
|
||||
|
||||
result := s
|
||||
for _, char := range specialChars {
|
||||
result = strings.ReplaceAll(result, char, "\\"+char)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// normalizeGlobPathSeparator normalizes the path separator for a glob pattern.
|
||||
// This is to keep options open to normalize the path separator when we support Windows.
|
||||
// Particularly for Windows, the path separator is '\\' instead of '/'. We will normalize
|
||||
// the path separator to '/' for consistency.
|
||||
func normalizeGlobPathSeparator(s string) string {
|
||||
return s
|
||||
}
|
||||
|
||||
var escapeUnclosedBracketsRegex = regexp.MustCompile(`\[([^\]]*?)$`)
|
||||
|
||||
// escapeUnclosedBrackets escapes bracket expressions that don't have a closing bracket.
|
||||
// Example: "[abc" -> "\[abc"
|
||||
func escapeUnclosedBrackets(s string) string {
|
||||
// Find all opening brackets that don't have a closing bracket
|
||||
return escapeUnclosedBracketsRegex.ReplaceAllString(s, `\[$1`)
|
||||
}
|
||||
Reference in New Issue
Block a user