MCPcopy Index your code
hub / github.com/AkihiroSuda/gomodjail

github.com/AkihiroSuda/gomodjail @v0.3.2

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.3.2 ↗ · + Follow
128 symbols 329 edges 36 files 7 documented · 5%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

[📂Profiles]

gomodjail: jail for Go modules

gomodjail imposes syscall restrictions on a specific set of Go modules, so as to mitigate their potential vulnerabilities and supply chain attack vectors.

In other words, gomodjail is a "container" (as in Docker containers) for Go modules.

gomodjail can be applied just in the following two steps:

Step 1: add gomodjail:confined comment to go.mod:

require (
        example.com/module v1.0.0 // gomodjail:confined
)

Step2: run the program with gomodjail run --go-mod=go.mod:

gomodjail run --go-mod=FILE -- PROG [ARGS]...

[!IMPORTANT]

See Caveats.

Requirements

Runtime dependencies: - Linux (4.8 or later) or macOS - x86_64 (aka "amd64") or aarch64 ("arm64")

Build dependencies: - Go

Install

make
sudo make install

Makefile variables: - PREFIX: installation prefix (default: /usr/local)

Example

An example program is located in ./examples/victim:

cd ./examples/victim
go build
./victim

Confirm the "malicious" vi screen:

*** ARBITRARY SHELL CODE EXECUTION ***

This 'vi' command was executed by the 'github.com/AkihiroSuda/gomodjail/examples/poisoned' module.

This example is harmless, of course, but suppose that this was a malicious code.

Type ':q!' to leave this screen.

Run the program again with gomodjail run --go-mod=go.mod, and confirm that the execution of the "malicious" vi command is blocked.

gomodjail run --go-mod=go.mod -- ./victim
level=WARN msg=***Blocked*** syscall=pidfd_open module=github.com/AkihiroSuda/gomodjail/examples/poisoned

More examples

examples/profiles has several example profiles: - docker.mod: for docker (not dockerd) - ...

Caveats

  • Not applicable to a Go binary built by non-trustworthy thirdparty, as the symbol information might be faked.
  • Not applicable to a Go module that imports unsafe, reflect, plugin, etc. See Static analysis.
  • No isolation of file descriptors across modules. A confined module can still read/write an existing file descriptor, although it cannot open a new file descriptor.
  • The target binary file must not be replaced during execution.
  • The gomodjail:confined policy is not well defined and still subject to change.
  • This is not a panacea; there can be other loopholes too.

macOS: - The protection can be arbitraliry disabled by unsetting an environment variable DYLD_INSERT_LIBRARIES. - Only works with the following versions of Go: - 1.22 - 1.23 - 1.24 (excluding 1.24.0-1.24.5) - 1.25 - 1.26 - Not applicable to a Go module that use: - syscall.Syscall, syscall.RawSyscall, etc.

macOS on Intel: - Not applicable to a Go binary built with -ldflags="-s" (disable symbol table)

Advanced topics

Self-extract archive

To create a self-extract archive of gomodjail with a target program, run gomodjail pack --go-mod=go.mod PROGRAM. The self-extract archive is created as <PROGRAM>.gomodjail.

Static analysis

The gomodjail analyze command can analyze if a module imports "unsafe" codes that cannot be protected with gomodjail, such as: - unsafe - reflect - plugin - go:linkname - C - Assembly

$ gomodjail analyze ./...
/Users/suda/gopath/pkg/mod/golang.org/x/sys@v0.39.0/cpu/runtime_auxv_go121.go:10:2: unsafe or cgo-related package imported: "unsafe"
/Users/suda/gopath/pkg/mod/golang.org/x/sys@v0.39.0/cpu/runtime_auxv_go121.go:13:1: use of //go:linkname directive detected
/Users/suda/gopath/pkg/mod/golang.org/x/sys@v0.39.0/execabs/execabs.go:21:2: unsafe or cgo-related package imported: "reflect"
/Users/suda/gopath/pkg/mod/golang.org/x/sys@v0.39.0/execabs/execabs.go:22:2: unsafe or cgo-related package imported: "unsafe"
[...]

How it works

Linux: - SECCOMP_RET_TRACE is used for conditionally allowing trusted Go modules to execute the syscall. SECCOMP_RET_USER_NOTIF is not used because it cannot access all the CPU registers, due to the lack of struct pt_regs in struct seccomp_data. - Stack unwinding is used for analyzing the call stack to determine the Go module.

macOS: - DYLD_INSERT_LIBRARIES is used to hook libSystem (libc) calls. - In addition to the frame pointer (AArch64 register X29), struct g in the TLS and g->m.libcallsp are parsed to analyze the CGO call stack. This analysis is not robust and only works with specific versions of Go. (See Caveats).

Future works

  • Automatically detect non-applicable modules (explained in Caveats).
  • Apply landlock in addition to seccomp. Depends on SECCOMP_IOCTL_NOTIF_ADDFD.
  • Modify the source code of the Go runtime, so as to remove necessity of using seccomp (Linux) and DYLD_INSERT_LIBRARIES (macOS).

Additional documents

Extension points exported contracts — how you extend this code

Unwinder (Interface)
(no doc) [1 implementers]
pkg/dynamic/unwinder/unwinder.go
Tracer (Interface)
(no doc) [1 implementers]
pkg/dynamic/tracer/tracer.go
Section (Interface)
(no doc)
pkg/dynamic/unwinder/unwinder.go
ObjectFile (Interface)
(no doc)
pkg/dynamic/unwinder/unwinder.go

Core symbols most depended-on inside this repo

Close
called by 14
pkg/dynamic/unwinder/unwinder.go
Confined
called by 9
pkg/profile/profile.go
String
called by 6
pkg/dynamic/unwinder/unwinder.go
Section
called by 5
pkg/dynamic/unwinder/unwinder.go
Error
called by 5
pkg/dynamic/tracer/tracer.go
New
called by 4
pkg/profile/profile.go
BuildInfo
called by 4
pkg/dynamic/unwinder/unwinder.go
Validate
called by 3
pkg/profile/profile.go

Shape

Function 60
Method 37
Struct 16
Class 11
Interface 4

Languages

Go86%
C14%

Modules by API surface

libgomodjail_hook_darwin/libgomodjail_hook_darwin.c18 symbols
pkg/dynamic/unwinder/unwinder.go17 symbols
pkg/dynamic/tracer/tracer_darwin.go9 symbols
pkg/dynamic/unwinder/unwinder_linux.go6 symbols
pkg/dynamic/unwinder/unwinder_darwin.go6 symbols
pkg/dynamic/tracer/tracer_linux.go6 symbols
pkg/dynamic/pack/ziputil/ziputil.go6 symbols
pkg/profile/profile.go5 symbols
pkg/dynamic/tracer/regs/regs_linux_arm64.go5 symbols
pkg/dynamic/tracer/regs/regs_linux_amd64.go5 symbols
pkg/static/analyzer/analyzer.go4 symbols
pkg/dynamic/tracer/tracer.go4 symbols

For agents

$ claude mcp add gomodjail \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page