{"record":{"id":"b2bf161e7d7e803d","repo":"xai-org/grok-build","slug":"deny-glob-glob-empty-path-segment-a-doubled","errorCode":null,"errorMessage":"deny glob {glob:?}: empty path segment (a doubled '//' or trailing '/'); remove the extra slash in sandbox.toml","messagePattern":"deny glob (.+?): empty path segment \\(a doubled '//' or trailing '/'\\); remove the extra slash in sandbox\\.toml","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-sandbox/src/deny/glob.rs","lineNumber":92,"sourceCode":"/// 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\n        // Linux while the macOS regex stays dead; reject on both platforms.\n        if segment == \".\" || segment == \"..\" {\n            anyhow::bail!(\n                \"deny glob {glob:?}: `.` and `..` segments are not supported; \\\n                 write the path without them (use an absolute path to deny \\\n                 files outside the workspace)\"\n            );\n        }\n        if segment.contains(\"**\") && segment != \"**\" {\n            anyhow::bail!(\n                \"deny glob {glob:?}: `**` must be its own path segment (got {segment:?}); \\\n                 write it as `**/` or `/**`, e.g. `a/**/b`\"\n            );","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-sandbox/src/deny/glob.rs#L74-L110","documentation":"validate_deny_glob rejects deny globs containing empty path segments — doubled slashes (`a//b`) or trailing slashes (`a/`) — because globset keeps `//` literal while the macOS regex collapses it, causing cross-platform divergence. Only a single leading `/` (absolute-path anchor) is permitted to be an 'empty' segment.","triggerScenarios":"A deny glob in sandbox.toml such as `/tmp//x`, `foo/bar/`, or any string where glob.split('/') yields an empty segment that is not the leading absolute-path position.","commonSituations":"Concatenating path strings in config generation (prefix + `/` + path where path already starts with `/`); hand-edited globs with trailing slashes; template rendering producing doubled separators.","solutions":["Remove the doubled or trailing slash from the glob in sandbox.toml.","If generating globs programmatically, join path components with a normalizing joiner that collapses separators.","Keep an optional single leading `/` for absolute globs — that is the only allowed empty segment."],"exampleFix":"// before (sandbox.toml)\ndeny = [\"/tmp//secrets/**\", \"var/log/\"]\n// after\ndeny = [\"/tmp/secrets/**\", \"var/log\"]","handlingStrategy":"validation","validationCode":"fn deny_glob_segments_ok(glob: &str) -> bool {\n    glob.split('/').enumerate().all(|(i, seg)| {\n        !seg.is_empty() || (i == 0 && glob.starts_with('/'))\n    })\n}\nfor g in &deny_globs {\n    assert!(deny_glob_segments_ok(g), \"empty path segment in deny glob: {g}\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Normalize generated paths before writing them into sandbox.toml (collapse `//`, strip trailing `/`).","Keep a single leading `/` only for absolute-path globs.","Lint sandbox.toml deny entries for doubled/trailing slashes in CI."],"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"}