security

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Mar 4, 2026 License: BSD-3-Clause Imports: 10 Imported by: 0

README

Security Package

This package provides security features for Rye:

  • system call filtering seccomp (on Linux),
  • filesystem access control landlock (on Linux)
  • code signing verification

Unified Security Policy

All security features are configured through a policy system. Policies can come from:

  1. Embedded (compiled into binary) - highest priority, cannot be bypassed
  2. System (/etc/rye/mandatory.yaml) - must be root-owned
  3. Local (.ryesec in script directory) - must be root-owned
  4. CLI flags - lowest priority
Policy File Format
version: "1.0"
description: "My application security policy"

seccomp:
  enabled: true
  profile: strict      # strict, readonly
  action: kill         # errno, kill, trap, log

landlock:
  enabled: true
  profile: custom      # readonly, readexec, custom
  paths:
    - "/app:r"
    - "/data:rw"
    - "/tmp:rw"

codesig:
  enforced: true
  public_keys:         # Inline keys (hex-encoded Ed25519)
    - "827ba5f0..."
  public_keys_file: "/etc/rye/trusted_keys"  # Or load from file

mandatory: true        # Cannot be relaxed by CLI flags
Security Requirements for Policy Files

Policy files (.ryesec, /etc/rye/*.yaml, key files) must be:

  • Owned by root (uid 0)
  • Not writable by group or others (mode 644 or stricter)

If these requirements are not met, Rye will refuse to run.

Components

Seccomp (System Call Filtering)

Restricts which system calls the process can make.

Profile Description
strict Minimal syscalls for Go runtime, blocks execve
readonly Allows network, blocks file write syscalls
Action Behavior
errno Return EPERM (allows graceful handling)
kill Terminate immediately (most secure)
trap Send SIGSYS (debugging)
log Log but allow (debugging only)
Landlock (Filesystem Access Control)

Restricts which files/directories the process can access.

Profile Description
readonly Read-only access to specified paths
readexec Read and execute access
custom Per-path permissions: r (read), w (write), x (execute)
Code Signing

Verifies that scripts are signed by trusted keys.

Public keys can be specified:

  • Inline in the policy (public_keys array)
  • In a separate file (public_keys_file - must be root-owned)

Script signature format:

; Your Rye script here
print "Hello"
;ryesig <hex-encoded-ed25519-signature>

Usage

# Create security policy
cat > security.yaml << 'EOF'
version: "1.0"
seccomp:
  enabled: true
  profile: strict
  action: kill
landlock:
  enabled: true
  profile: readonly
mandatory: true
EOF

# Generate embedded policy code
go run cmd/ryesecgen/main.go -input security.yaml

# Build with embedded policy
go build -tags "embed_security,seccomp,landlock" -o myapp
Option 2: Per-Application Policy (.ryesec)
# Create policy in application directory
sudo cat > /opt/myapp/.ryesec << 'EOF'
version: "1.0"
seccomp:
  enabled: true
  profile: strict
  action: kill
mandatory: true
EOF

sudo chown root:root /opt/myapp/.ryesec
sudo chmod 644 /opt/myapp/.ryesec

# Run with policy auto-applied
rye /opt/myapp/main.rye
Option 3: System-Wide Policy
sudo mkdir -p /etc/rye
sudo cat > /etc/rye/mandatory.yaml << 'EOF'
version: "1.0"
seccomp:
  enabled: true
  profile: readonly
  action: errno
mandatory: true
EOF

sudo chown root:root /etc/rye/mandatory.yaml
sudo chmod 644 /etc/rye/mandatory.yaml

# All Rye scripts now run with this policy
rye any_script.rye
Option 4: CLI Flags (Development Only)
# These can be overridden by policy files
rye -seccomp-profile=strict -landlock script.rye

Building with Security Support

# Full security support
go build -tags "seccomp,landlock"

# With embedded policy
go build -tags "embed_security,seccomp,landlock"

# Or use the build script
./build_secure -policy security.yaml -output myapp

Signing Scripts

; Generate keys
ed25519-generate-keys |set! { pub priv }

; Save public key (add to policy)
pub |encode-to\hex |print

; Sign a script
script-content: read %myscript.rye
signature: script-content priv |sign |encode-to\hex
; Append ";ryesig " + signature to the script

Documentation

Overview

codesig.go - Code signature verification for Rye scripts

Code signing is configured through security policies (.ryesec, /etc/rye/*.yaml, or embedded). Public keys can be specified inline in the policy or loaded from a separate file.

Index

Constants

View Source
const LocalPolicyFilename = ".ryesec"

LocalPolicyFilename is the name of local policy files

Variables

View Source
var CurrentCodeSigEnabled bool

CurrentCodeSigEnabled indicates whether code signature verification is currently enabled

View Source
var CurrentLandlockProfile string

CurrentLandlockProfile stores the active landlock profile

View Source
var CurrentSeccompProfile string

CurrentSeccompProfile stores the active seccomp profile

View Source
var SystemPolicyPaths = []string{
	"/etc/rye/mandatory.yaml",
	"/etc/rye/security.yaml",
}

SystemPolicyPaths defines where to look for system-wide policies

View Source
var TrustedPublicKeys []ed25519.PublicKey

TrustedPublicKeys stores the list of trusted public keys

Functions

func ApplySecurityPolicy added in v0.2.0

func ApplySecurityPolicy(policy *SecurityPolicy) error

ApplySecurityPolicy applies the given security policy

func DisableSeccompForDebug

func DisableSeccompForDebug()

DisableSeccompForDebug is a stub implementation for systems where seccomp is not available

func InitLandlock

func InitLandlock(config LandlockConfig) error

InitLandlock initializes the landlock filesystem access control for Rye This is a stub implementation for non-Linux systems

func InitSeccomp

func InitSeccomp(config SeccompConfig) error

InitSeccomp is a stub implementation for systems where seccomp is not available or when the seccomp build tag is not enabled

func IsEmbeddedBuild added in v0.2.0

func IsEmbeddedBuild() bool

IsEmbeddedBuild returns false for non-embedded builds

func LoadPublicKeysFromFile added in v0.2.0

func LoadPublicKeysFromFile(filePath string) error

LoadPublicKeysFromFile loads trusted public keys from a file The file must be owned by root and not writable by group/others

func LoadPublicKeysFromStrings added in v0.2.0

func LoadPublicKeysFromStrings(hexKeys []string) error

LoadPublicKeysFromStrings loads trusted public keys from a slice of hex-encoded strings

func SetupSeccompTrapHandler

func SetupSeccompTrapHandler()

SetupSeccompTrapHandler is a stub implementation for systems where seccomp is not available

func VerifySignature

func VerifySignature(content []byte, signature []byte) bool

VerifySignature verifies a signature against the content using trusted public keys

Types

type LandlockConfig

type LandlockConfig struct {
	Enabled bool
	Profile string
	Paths   []string
}

LandlockConfig holds the configuration for landlock filesystem access control This is a stub implementation for non-Linux systems

type PolicySource added in v0.2.0

type PolicySource string

PolicySource indicates where the security policy came from

const (
	PolicySourceNone     PolicySource = "none"
	PolicySourceCLI      PolicySource = "cli"
	PolicySourceLocal    PolicySource = "local"    // .ryesec in script dir
	PolicySourceSystem   PolicySource = "system"   // /etc/rye/
	PolicySourceEmbedded PolicySource = "embedded" // Compiled into binary
)

type SeccompConfig

type SeccompConfig struct {
	Enabled bool
	Profile string
	Action  string
}

SeccompConfig holds the configuration for seccomp filtering

type SecurityPolicy added in v0.2.0

type SecurityPolicy struct {
	// Metadata
	Version     string       `yaml:"version"`
	Description string       `yaml:"description,omitempty"`
	Source      PolicySource `yaml:"-"` // Set at runtime, not from file

	// Seccomp configuration
	Seccomp struct {
		Enabled bool   `yaml:"enabled"`
		Profile string `yaml:"profile"` // "strict", "readonly"
		Action  string `yaml:"action"`  // "errno", "kill", "trap", "log"
	} `yaml:"seccomp"`

	// Landlock configuration
	Landlock struct {
		Enabled bool     `yaml:"enabled"`
		Profile string   `yaml:"profile"` // "readonly", "readexec", "custom"
		Paths   []string `yaml:"paths"`   // For custom profile: "/path:rw" format
	} `yaml:"landlock"`

	// Code signing configuration
	CodeSig struct {
		Enforced       bool     `yaml:"enforced"`
		PublicKeys     []string `yaml:"public_keys,omitempty"`      // Inline hex-encoded keys
		PublicKeysFile string   `yaml:"public_keys_file,omitempty"` // Path to file with keys (must be root-owned)
	} `yaml:"codesig"`

	// Policy enforcement
	Mandatory bool `yaml:"mandatory"` // If true, cannot be relaxed by CLI flags

	// Allowed paths for scripts (if empty, any script can run)
	AllowedScriptPaths []string `yaml:"allowed_script_paths,omitempty"`
}

SecurityPolicy represents a complete security configuration

func GetEmbeddedPolicy added in v0.2.0

func GetEmbeddedPolicy() *SecurityPolicy

GetEmbeddedPolicy returns nil when no policy is embedded This stub is used when building without the embed_security tag

func LoadSecurityPolicy added in v0.2.0

func LoadSecurityPolicy(scriptDir string, cliPolicy *SecurityPolicy) (*SecurityPolicy, error)

LoadSecurityPolicy loads security policy with the following precedence: 1. Embedded policy (highest - compiled into binary) 2. System policy (/etc/rye/mandatory.yaml) 3. Local policy (.ryesec in script directory) 4. CLI flags (lowest)

func MergePolicies added in v0.2.0

func MergePolicies(base, override *SecurityPolicy) *SecurityPolicy

MergePolicies merges a base policy with overrides Only allows overrides to be MORE restrictive, not less

func (*SecurityPolicy) String added in v0.2.0

func (p *SecurityPolicy) String() string

String returns a human-readable description of the policy

func (*SecurityPolicy) ValidateScriptPath added in v0.2.0

func (p *SecurityPolicy) ValidateScriptPath(scriptPath string) error

ValidateScriptPath checks if a script is allowed to run under this policy

Jump to

Keyboard shortcuts

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