{"record":{"id":"4186a38b24c34245","repo":"xai-org/grok-build","slug":"deny-glob-glob-uses-unsupported-metacharacter","errorCode":null,"errorMessage":"deny glob {glob:?} uses unsupported metacharacter '{c}' (brace alternation and backslash-escapes are not supported; use separate deny entries)","messagePattern":"deny glob (.+?) uses unsupported metacharacter '(.+?)' \\(brace alternation and backslash-escapes are not supported; use separate deny entries\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-sandbox/src/deny/glob.rs","lineNumber":79,"sourceCode":"}\n\n/// Validate a deny glob on BOTH platforms so a given pattern is interpreted\n/// IDENTICALLY everywhere or rejected everywhere (never silently under-enforced\n/// on macOS). Two checks, run before the macOS regex translation and the Linux\n/// globset expansion alike:\n///\n/// 1. Reject `{`/`}`/`\\`: globset honors brace alternation and backslash-escapes,\n///    but Seatbelt's runtime regex (sourced from globset's own `.regex()` mis-\n///    enforces `**/` for root-level paths, so we hand-roll the regex instead and\n///    cannot faithfully reproduce those forms — rejecting them on both platforms\n///    keeps the two backends in agreement. A user wanting alternation writes\n///    separate deny entries.\n/// 2. Compile through `globset` (the Linux matcher) so a malformed glob (`a**b`,\n///    unterminated `[`) fails closed identically on both platforms.\n#[cfg(all(feature = \"enforce\", unix))]\npub(crate) fn validate_deny_glob(glob: &str) -> anyhow::Result<()> {\n    if let Some(c) = glob.chars().find(|&c| matches!(c, '{' | '}' | '\\\\')) {\n        anyhow::bail!(\n            \"deny glob {glob:?} uses unsupported metacharacter '{c}' \\\n             (brace alternation and backslash-escapes are not supported; \\\n             use separate deny entries)\"\n        );\n    }\n    // `**` must be a whole path component (gitignore semantics). A non-component\n    // `**` (e.g. `a**b`) would translate to `.*` on macOS but collapse to `*` in\n    // globset — reject it on both platforms so they never diverge. Empty\n    // segments (`a//*`) drift the same way: globset keeps `//` literally while\n    // the macOS regex collapses it.\n    for (index, segment) in glob.split('/').enumerate() {\n        if segment.is_empty() && !(index == 0 && glob.starts_with('/')) {\n            anyhow::bail!(\n                \"deny glob {glob:?}: empty path segment (a doubled '//' or \\\n                 trailing '/'); remove the extra slash in sandbox.toml\"\n            );\n        }\n        // `.`/`..` would let a relative glob scan outside the workspace on","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-sandbox/src/deny/glob.rs#L61-L97","documentation":"validate_deny_glob rejects deny globs in sandbox.toml that contain `{`, `}`, or `\\`. Brace alternation and backslash escapes behave differently between the Linux globset matcher and the macOS regex matcher, so the library fails closed on both platforms to guarantee identical enforcement semantics.","triggerScenarios":"Adding a deny glob entry in sandbox.toml containing brace alternation like `/usr/{bin,sbin}/x` or a backslash escape like `/usr/bin/foo\\ bar`, then applying deny globs (apply_deny_globs_to_capability_set / expand_deny_globs).","commonSituations":"Porting shell-style or gitignore-brace patterns into sandbox.toml; escaping spaces in paths with backslashes; copying deny rules from other tooling that supports braces.","solutions":["Rewrite the glob without braces: use separate deny entries for each alternative.","Remove backslash escapes; express spaces/special chars without `\\` (quote the TOML string normally, escape nothing in the glob itself).","Re-run the command — the glob compiles through globset identically on both platforms once sanitized."],"exampleFix":"// before (sandbox.toml)\ndeny = [\"/usr/{bin,sbin}/tool\"]\n// after\ndeny = [\"/usr/bin/tool\", \"/usr/sbin/tool\"]","handlingStrategy":"validation","validationCode":"fn deny_glob_valid(glob: &str) -> bool {\n    !glob.chars().any(|c| matches!(c, '{' | '}' | '\\\\'))\n}\nfor g in &deny_globs {\n    assert!(deny_glob_valid(g), \"unsupported metacharacter in deny glob: {g}\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never use `{a,b}` alternation in sandbox.toml deny globs — write one entry per alternative.","Never backslash-escape characters in deny globs.","Lint sandbox.toml deny entries in CI with the same metacharacter check."],"tags":["glob","sandbox","configuration"],"backgroundTag":"unsupported-glob-pattern","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}