proctree

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 9, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

README

Security Engineering Commons Proctree

Bounded process-tree execution, cancellation and cleanup for Go

Proctree executes a trusted local command and returns after its owned process tree terminates or cleanup fails. It is not a privilege boundary or hostile-code sandbox

Commands use an absolute executable path and an argument vector without shell interpretation. Input, output, environment material and execution time are bounded

Summary

Install

go get github.com/secengcommons/proctree@v1.1.0

Requires Go 1.26 or newer

Use

package main

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/secengcommons/proctree"
)

func main() {
	if handled, code := proctree.DispatchWatchdog(os.Args); handled {
		os.Exit(code)
	}

	result, err := proctree.Run(context.Background(), proctree.Command{
		Executable:  "/usr/bin/git",
		Arguments:   []string{"status", "--short"},
		Environment: []string{"PATH=/usr/bin"},
		StdoutLimit: 64 << 10,
		StderrLimit: 64 << 10,
		Timeout:     10 * time.Second,
	})
	if err != nil {
		panic(err)
	}
	fmt.Print(string(result.Stdout))
}

Unix executables must call DispatchWatchdog(os.Args) before ordinary command dispatch. Windows uses a kill-on-close Job Object and suspended process creation

Result reports whether execution started, the exit code, bounded output and a typed outcome. Errors preserve Proctree sentinel errors and native causes

Bounds

Material Maximum
Arguments 256
Argument bytes 64 KiB
Environment entries 128
Environment bytes 64 KiB
Input 1 MiB
Standard output 16 MiB
Standard error 16 MiB
Execution timeout 30 minutes
Cleanup timeout 30 seconds
Path 4 KiB

Nil or empty environment means no environment variables. Zero execution timeout leaves timing to the context. Zero cleanup timeout selects the one-second default

An output stream may reach its exact limit. The next byte terminates the tree and returns the bounded output prefixes

Outcomes

Outcome Meaning
invalid Invalid command or context
completed Zero exit with complete cleanup
exit_failure Non-zero exit
cancelled Caller cancellation
deadline Caller or command deadline
output_limit Output exceeded its bound
start_failure Process creation failed
ownership_failure Process-tree ownership failed
cleanup_failure Termination, wait or close failed
unsupported No qualified platform owner

Cleanup failure takes precedence over an earlier execution outcome. Native owner creation and process startup cannot be interrupted while an operating-system call is blocked

Platforms

Platform Qualified execution
Windows Server 2022 and 2025 AMD64; Windows 11 ARM64
Linux Ubuntu 22.04 and 24.04 on AMD64 and ARM64
macOS Versions 15 and 26 on AMD64 and ARM64
FreeBSD Versions 13.5, 14.4 and 15.1 on AMD64
OpenBSD Versions 7.7, 7.8 and 7.9 on AMD64
NetBSD Versions 9.4, 10.1 and 11.0 on AMD64
DragonFly BSD Version 6.4.2 on AMD64
illumos OmniOS r151058 on AMD64
Solaris Version 11.4 on AMD64

AIX and other Go ports are compile-only or unsupported. Unsupported targets refuse execution rather than falling back to immediate-process-only termination

Windows requires Windows 10 or Windows Server 2016 and later. A parent Job must permit nested Job ownership

Performance

Command admission is measured independently from operating-system process creation

Benchmark method

(9 September 2026) - The measurements use:

  • Linux AMD64
  • 13th Gen Intel Core i5-13400F
  • Go 1.27.1
  • five 500 ms samples per operation
  • the median of each five-sample set

Benchmark results

Operation Time Bytes Allocations
Admit one command with three arguments and three environment entries 225.5 ns 96 2

The benchmark includes two output limits and one timeout. It does not start a process. Run the complete set with:

go test -run '^$' -bench . -benchmem -benchtime=500ms -count=5 ./...

Boundary

Unix ownership covers descendants which remain in the inherited process group. Container ownership is limited to the caller's PID namespace. Deliberate process-group, session or namespace escape is not covered

Proctree bounds input, output and execution. It does not validate the executable, provide isolation or prevent descendants from using ambient authority

Verification

go test -count=1 ./...
go test -race -count=1 ./...

CI also runs compatibility, coverage, fuzz, container, native-platform, virtual-platform, cross-build and CodeQL checks

Documentation

Index

Constants

View Source
const DefaultCleanupTimeout = time.Second
View Source
const MaxArgumentBytes = 64 << 10
View Source
const MaxArguments = 256
View Source
const MaxCleanupTimeout = 30 * time.Second
View Source
const MaxEnvironment = 128
View Source
const MaxEnvironmentBytes = 64 << 10
View Source
const MaxInputBytes = 1 << 20
View Source
const MaxOutputBytes = 16 << 20
View Source
const MaxPathBytes = 4 << 10
View Source
const MaxTimeout = 30 * time.Minute

Variables

View Source
var ErrCancelled = errors.New("process execution cancelled")
View Source
var ErrCleanup = errors.New("process cleanup failed")
View Source
var ErrDeadline = errors.New("process execution deadline exceeded")
View Source
var ErrExit = errors.New("process exited unsuccessfully")
View Source
var ErrInvalid = errors.New("invalid process command")
View Source
var ErrOutputLimit = errors.New("process output exceeds its bound")
View Source
var ErrOwnership = errors.New("process ownership failed")
View Source
var ErrStart = errors.New("process start failed")
View Source
var ErrUnsupported = errors.New("process-tree ownership is unsupported")

Functions

func DispatchWatchdog

func DispatchWatchdog(arguments []string) (bool, int)

Types

type Command

type Command struct {
	Executable     string
	Arguments      []string
	Directory      string
	Environment    []string
	Input          []byte
	StdoutLimit    int
	StderrLimit    int
	Timeout        time.Duration
	CleanupTimeout time.Duration
}

type Outcome

type Outcome string
const OutcomeCancelled Outcome = "cancelled"
const OutcomeCleanupFailure Outcome = "cleanup_failure"
const OutcomeCompleted Outcome = "completed"
const OutcomeDeadline Outcome = "deadline"
const OutcomeExitFailure Outcome = "exit_failure"
const OutcomeInvalid Outcome = "invalid"
const OutcomeOutputLimit Outcome = "output_limit"
const OutcomeOwnershipFailure Outcome = "ownership_failure"
const OutcomeStartFailure Outcome = "start_failure"
const OutcomeUnsupported Outcome = "unsupported"

type Result

type Result struct {
	Started  bool
	ExitCode int
	Stdout   []byte
	Stderr   []byte
	Outcome  Outcome
}

func Run

func Run(ctx context.Context, command Command) (Result, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL