{"record":{"id":"6105c6d3bf7ad752","repo":"puppetlabs/puppet","slug":"invalid-context-to-parse-context","errorCode":null,"errorMessage":"Invalid context to parse: %{context}","messagePattern":"Invalid context to parse: %(.+?)","errorType":"exception","errorClass":"Puppet::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/util/selinux.rb","lineNumber":94,"sourceCode":"    # If the file exists we should pass the mode to selabel_lookup for the most specific\n    # matching.  If not, we can pass a mode of 0.\n    mode = file_mode(file, resource_ensure)\n\n    retval = Selinux.selabel_lookup(handle, file, mode)\n    retval == -1 ? nil : retval[1]\n  end\n\n  # Take the full SELinux context returned from the tools and parse it\n  # out to the three (or four) component parts.  Supports :seluser, :selrole,\n  # :seltype, and on systems with range support, :selrange.\n  def parse_selinux_context(component, context)\n    if context.nil? or context == \"unlabeled\"\n      return nil\n    end\n\n    components = /^([^\\s:]+):([^\\s:]+):([^\\s:]+)(?::([\\sa-zA-Z0-9:,._-]+))?$/.match(context)\n    unless components\n      raise Puppet::Error, _(\"Invalid context to parse: %{context}\") % { context: context }\n    end\n\n    case component\n    when :seluser\n      components[1]\n    when :selrole\n      components[2]\n    when :seltype\n      components[3]\n    when :selrange\n      components[4]\n    else\n      raise Puppet::Error, _(\"Invalid SELinux parameter type\")\n    end\n  end\n\n  # This updates the actual SELinux label on the file.  You can update\n  # only a single component or update the entire context.","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/util/selinux.rb#L76-L112","documentation":"Puppet::Util::SELinuxUtil-class method parse_selinux_context (selinux.rb:94) splits an SELinux context into seluser/selrole/seltype/selrange using the regex /^([^\\s:]+):([^\\s:]+):([^\\s:]+)(?::([\\sa-zA-Z0-9:,._-]+))?$/ on a single line. nil and the literal string 'unlabeled' short-circuit to nil (line 91); anything else that lacks at least three non-empty, colon-separated, whitespace-free fields raises Puppet::Error 'Invalid context to parse: <context>'.","triggerScenarios":"parse_selinux_context(:selrange, 'unconfined_u:unconfined_r') (only two fields); a context with embedded spaces 'system_u : system_r'; a lone placeholder like '?' or '-' returned by tools; a multiline string passed as the context. Note the pattern is per-line: use the first line of `ls -Z`/lgetfilecon output only.","commonSituations":"File resources on filesystems without SELinux labeling that return odd sentinel strings instead of 'unlabeled'; parsing `ls -Z` or `matchpathcon` output where columns are blank; custom ranges containing unexpected characters not in [a-zA-Z0-9:,._ -].","solutions":["Handle the documented empty cases yourself first: return early when context.nil? || context == 'unlabeled'.","Take only the context field from tool output (e.g., split and select the token matching user:role:type) rather than the whole line.","Pre-validate with the same regex the library uses: ctx =~ /^([^\\s:]+):([^\\s:]+):([^\\s:]+)(?::([\\sa-zA-Z0-9:,._-]+))?$/ before calling.","Rescue Puppet::Error around parse calls and log the raw string to identify which tool produced the malformed context."],"exampleFix":"// before\nrange = parse_selinux_context(:selrange, raw_ls_z_output) # whole line 'unconfined_u:object_r:user_home_t:s0 file.txt'\n\n// after\nline = raw.to_s.lines.first.to_s\nctx = line.split.find { |t| t.count(':') >= 2 && t =~ /\\A[^\\s:]+:[^\\s:]+:[^\\s:]+/ }\nrange = ctx.nil? ? nil : parse_selinux_context(:selrange, ctx)","handlingStrategy":"validation","validationCode":"CTX_RX = /\\A([^\\s:]+):([^\\s:]+):([^\\s:]+)(?::([\\sa-zA-Z0-9:,._-]+))?\\z/\ndef selinux_context_str?(ctx)\n  !ctx.nil? && ctx != 'unlabeled' && ctx.match?(CTX_RX)\nend","typeGuard":null,"tryCatchPattern":"begin\n  parse_selinux_context(component, ctx)\nrescue Puppet::Error => e\n  Puppet.debug(\"unparseable selinux context #{ctx.inspect}: #{e.message}\")\n  nil\nend","preventionTips":["Early-return on nil and 'unlabeled' before calling the parser.","Extract just the context token (>=2 colons) from ls -Z / matchpathcon output."],"tags":["selinux","linux","puppet","security-context","regex","validation"],"backgroundTag":"selinux-context-invalid","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}