Documentation
¶
Overview ¶
Package cmd provides a Starlark module for executing external commands.
Security posture (PKG-09): the module is DISABLED by default — a script that loads it cannot run anything until the Go host explicitly enables it with an allowlist via NewModuleWithAllow. When enabled it is still deny-by-default: only commands whose canonical form matches an allowlist prefix run. Commands are always executed via argv (exec.Command), never through a shell, so there is no shell interpolation. Command text is hardened against control and zero-width/format characters before allowlist matching and execution. The enable flag and allowlist are host policy set in Go; a script (or an environment variable) can never widen them.
Example ¶
Example shows the happy path: the host enables the module with an allowlist, and a permitted command runs via argv (no shell).
package main
import (
"fmt"
"log"
"strings"
"github.com/1set/starlet"
"github.com/starpkg/cmd"
"go.starlark.net/starlark"
)
// runScript loads the given cmd module into a starlet machine, runs the script,
// and returns its captured print output plus any run error.
func runScript(module *cmd.Module, script string) (string, error) {
env := starlet.NewDefault()
env.SetScriptContent([]byte(script))
var printOutput strings.Builder
env.SetPrintFunc(func(_ *starlark.Thread, msg string) {
printOutput.WriteString(msg)
printOutput.WriteString("\n")
})
env.SetLazyloadModules(map[string]starlet.ModuleLoader{"cmd": module.LoadModule()})
_, err := env.Run()
return printOutput.String(), err
}
func main() {
// Enable the module and permit only the "go" tool.
module := cmd.NewModuleWithAllow("go")
script := `
load("cmd", "run")
def main():
result = run("go version")
print("succeeded:", result.success)
print("exit code:", result.exit_code)
main()
`
out, err := runScript(module, script)
if err != nil {
log.Fatalf("Failed to run script: %v", err)
}
fmt.Print(out)
}
Output: succeeded: True exit code: 0
Index ¶
Examples ¶
Constants ¶
const ModuleName = "cmd"
ModuleName defines the expected name for this module when used in Starlark's load() function
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Module ¶
type Module struct {
// contains filtered or unexported fields
}
Module wraps the ConfigurableModule with specific functionality for command execution. enabled, allow and allowAll are host policy (set in Go) and are never overridable by a script or by environment variables.
Example (Disabled) ¶
ExampleModule_disabled shows the secure default: a module created with NewModule is disabled, so run() refuses until the host opts in.
package main
import (
"fmt"
"strings"
"github.com/1set/starlet"
"github.com/starpkg/cmd"
"go.starlark.net/starlark"
)
// runScript loads the given cmd module into a starlet machine, runs the script,
// and returns its captured print output plus any run error.
func runScript(module *cmd.Module, script string) (string, error) {
env := starlet.NewDefault()
env.SetScriptContent([]byte(script))
var printOutput strings.Builder
env.SetPrintFunc(func(_ *starlark.Thread, msg string) {
printOutput.WriteString(msg)
printOutput.WriteString("\n")
})
env.SetLazyloadModules(map[string]starlet.ModuleLoader{"cmd": module.LoadModule()})
_, err := env.Run()
return printOutput.String(), err
}
func main() {
module := cmd.NewModule() // disabled by default
script := `
load("cmd", "run")
run("go version")
`
_, err := runScript(module, script)
fmt.Println("disabled module refuses to run:", err != nil)
}
Output: disabled module refuses to run: true
func NewModule ¶
func NewModule() *Module
NewModule creates a new instance of Module with default configurations. The module is DISABLED: run() returns an error until the host enables it with an allowlist via NewModuleWithAllow.
func NewModuleWithAllow ¶
NewModuleWithAllow returns a module that is ENABLED with the given allowlist. Each entry is a prefix matched against the canonical command (argv joined by a single space) at a word boundary: "git" permits "git status" but not "gitleaks"; "go test" permits "go test ./..." but not "go build". An empty allowlist enables the module but permits nothing (deny-all).
func NewModuleWithAllowAll ¶ added in v0.1.1
func NewModuleWithAllowAll() *Module
NewModuleWithAllowAll returns a module that is ENABLED and permits EVERY command — the allowlist check is bypassed entirely. This is the explicit "dangerous, run anything" escape hatch for a host that has already decided the caller is fully trusted (e.g. a CLI operator who passed a --dangerously-allow-all style flag); prefer NewModuleWithAllow with a specific allowlist whenever the set of commands is known. It still applies the same input hardening as every other path (sanitizeCommand rejects control / zero-width characters, and execution stays argv-only — never a shell). Like enable and allow, the allow-all decision is Go-host state bound at construction: nothing a script does, and no environment variable, can set or widen it.
func NewModuleWithConfig ¶
func NewModuleWithConfig(cwd string, env map[string]string, timeout float64, combineOutput, realtimeOutput, captureOutput bool) *Module
NewModuleWithConfig creates a new instance of Module with the given configuration values. Like NewModule, the returned module is DISABLED until enabled with an allowlist.
func (*Module) LoadModule ¶
func (m *Module) LoadModule() starlet.ModuleLoader
LoadModule returns the Starlark module loader with command-specific functions