Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ jobs:
uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
with:
go-version-file: go.mod

- name: Lint
uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0
with:
# This version number must be kept in sync with Makefile lint one.
version: v2.10.1

- name: Test
run: go test ./...
Expand Down
58 changes: 58 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
version: "2"

run:
timeout: 5m

linters:
default: none
enable:
- errcheck
- errorlint
- govet
- ineffassign
- gosec
- staticcheck
- unused
Comment thread
Sefi4 marked this conversation as resolved.
settings:
errorlint:
errorf: true
asserts: true
comparison: true
staticcheck:
checks:
- all
gosec:
excludes:
# Integer overflow conversion is acceptable in BPF context (e.g. mntns_id, pid).
- G115
Comment thread
Sefi4 marked this conversation as resolved.
exclusions:
generated: lax
rules:
# Ignore check: Packages must have a package comment
- linters:
- staticcheck
text: "ST1000: at least one file in a package should have a package comment"
# Ignore rule about ID vs Id: https://github.com/golang/lint/issues/89
- linters:
- staticcheck
text: "ST1003:"
paths:
# Exclude generated build directory
- ^build/
Comment thread
Sefi4 marked this conversation as resolved.

formatters:
enable:
- gofmt
- goimports
settings:
goimports:
local-prefixes:
- github.com/micromize-dev/micromize
exclusions:
generated: lax
paths:
- ^build/
Comment thread
Sefi4 marked this conversation as resolved.

issues:
max-issues-per-linter: 0
max-same-issues: 0
6 changes: 6 additions & 0 deletions Dockerfiles/linter.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
ARG IMAGE
FROM ${IMAGE}

# The timeout specified below is used by 'make lint'. Please keep in sync with
# the timeout specified in .golangci.yml used by the CI.
ENTRYPOINT ["golangci-lint", "run", "--timeout=5m0s"]
Comment thread
Sefi4 marked this conversation as resolved.
19 changes: 19 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ LDFLAGS := -X github.com/inspektor-gadget/inspektor-gadget/internal/version.vers
GADGETS := fs-restrict cap-restrict ptrace-restrict binary-attestation
CONFORM_VERSION ?= v0.1.0-alpha.30

# This version number must be kept in sync with CI workflow lint one.
LINTER_IMAGE ?= golangci/golangci-lint:v2.10.1

.PHONY: setup-hooks
setup-hooks:
go install github.com/siderolabs/conform/cmd/conform@$(CONFORM_VERSION)
Expand All @@ -26,6 +29,22 @@ license-add:
@go run github.com/google/addlicense@v1.2.0 -y "" -l apache -c "The micromize authors" \
$$(find . -name '*.go' -not -path './build/*')

.PHONY: lint
lint:
docker build -t linter -f Dockerfiles/linter.Dockerfile --build-arg IMAGE=$(LINTER_IMAGE) Dockerfiles
Comment thread
Sefi4 marked this conversation as resolved.
# XDG_CACHE_HOME is necessary to avoid this type of errors:
# ERRO Running error: context loading failed: failed to load packages: failed to load with go/packages: err: exit status 1: stderr: failed to initialize build cache at /.cache/go-build: mkdir /.cache: permission denied
# Process 15167 has exited with status 3
# While GOLANGCI_LINT_CACHE is used to store golangci-lint cache.
Comment thread
Sefi4 marked this conversation as resolved.
docker run --rm --env XDG_CACHE_HOME=/tmp/xdg_home_cache \
--env GOLANGCI_LINT_CACHE=/tmp/golangci_lint_cache \
--user $(shell id -u):$(shell id -g) -v $(shell pwd):/app -w /app \
linter
Comment thread
Sefi4 marked this conversation as resolved.

.PHONY: clean
clean:
rm -rf $(OUTPUT_DIR) build/src build/gadgets
Comment thread
Sefi4 marked this conversation as resolved.

Comment thread
Sefi4 marked this conversation as resolved.
.PHONY: build-all
build-all: $(GADGETS) build-app

Expand Down
3 changes: 2 additions & 1 deletion cmd/micromize/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ import (
"strings"
"syscall"

"github.com/spf13/cobra"

"github.com/micromize-dev/micromize/internal/gadget"
"github.com/micromize-dev/micromize/internal/logger"
"github.com/micromize-dev/micromize/internal/operators"
"github.com/micromize-dev/micromize/internal/runtime"
"github.com/micromize-dev/micromize/internal/utils"
"github.com/spf13/cobra"
)

const (
Expand Down
11 changes: 6 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,16 @@ module github.com/micromize-dev/micromize
go 1.25.5

require (
github.com/cilium/ebpf v0.20.0
github.com/cyphar/filepath-securejoin v0.5.1
github.com/docker/cli v29.2.0+incompatible
github.com/go-jose/go-jose/v4 v4.1.3
github.com/inspektor-gadget/inspektor-gadget v0.49.1
github.com/opencontainers/image-spec v1.1.1
github.com/quay/claircore v1.5.45
github.com/sirupsen/logrus v1.9.4
github.com/spf13/cobra v1.10.2
golang.org/x/sync v0.19.0
Comment on lines 5 to +15

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

go.mod adds github.com/go-jose/go-jose/v4 as a direct dependency, but the only in-repo usage appears to be go-jose/v4/testutils/require in internal/sbom/sbom_test.go. Consider removing this dependency (or replacing it with standard testing assertions / a project-standard assertion lib) so the main module dependency set isn’t expanded just to support a single test helper.

Copilot uses AI. Check for mistakes.
oras.land/oras-go/v2 v2.6.0
)

Expand All @@ -21,7 +27,6 @@ require (
github.com/blang/semver v3.5.1+incompatible // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cilium/ebpf v0.20.0 // indirect
github.com/cloudflare/cbpfc v0.0.0-20240920015331-ff978e94500b // indirect
github.com/containerd/cgroups/v3 v3.0.5 // indirect
github.com/containerd/containerd v1.7.30 // indirect
Expand All @@ -35,10 +40,8 @@ require (
github.com/containerd/ttrpc v1.2.7 // indirect
github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/coreos/go-systemd/v22 v22.7.0 // indirect
github.com/cyphar/filepath-securejoin v0.5.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/cli v29.2.0+incompatible // indirect
github.com/docker/docker v28.5.2+incompatible // indirect
github.com/docker/docker-credential-helpers v0.9.3 // indirect
github.com/docker/go-connections v0.6.0 // indirect
Expand Down Expand Up @@ -98,7 +101,6 @@ require (
github.com/notaryproject/notation-plugin-framework-go v1.0.0 // indirect
github.com/notaryproject/tspclient-go v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/opencontainers/runtime-spec v1.2.1 // indirect
github.com/opencontainers/selinux v1.13.1 // indirect
github.com/packetcap/go-pcap v0.0.0-20250723190045-d00b185f30b7 // indirect
Expand Down Expand Up @@ -139,7 +141,6 @@ require (
golang.org/x/mod v0.31.0 // indirect
golang.org/x/net v0.49.0 // indirect
golang.org/x/oauth2 v0.33.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.40.0 // indirect
golang.org/x/term v0.39.0 // indirect
golang.org/x/text v0.33.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ github.com/go-asn1-ber/asn1-ber v1.5.7 h1:DTX+lbVTWaTw1hQ+PbZPlnDZPEIs0SS/GCZAl5
github.com/go-asn1-ber/asn1-ber v1.5.7/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-ldap/ldap/v3 v3.4.10 h1:ot/iwPOhfpNVgB1o+AVXljizWZ9JTp7YF5oeyONmcJU=
github.com/go-ldap/ldap/v3 v3.4.10/go.mod h1:JXh4Uxgi40P6E9rdsYqpUtbW46D9UTjJ9QSwGRznplY=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
Expand Down
12 changes: 9 additions & 3 deletions internal/operators/operators.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ type DataOperator = igoperators.DataOperator

func NewLocalManager() (igoperators.DataOperator, error) {
slog.Debug("Initializing local manager operator")
host.Init(host.Config{})
if err := host.Init(host.Config{}); err != nil {
return nil, fmt.Errorf("init host: %w", err)
}
localManagerOp := localmanager.LocalManagerOperator
localManagerParams := localManagerOp.GlobalParamDescs().ToParams()

Expand Down Expand Up @@ -244,7 +246,9 @@ func populateExpectedHashes(gadgetCtx igoperators.GadgetContext, innerMaps *sync
// Insert the inner map into the outer map keyed by mntns_id
if err := outerMap.Put(mntnsID, uint32(innerMap.FD())); err != nil {
slog.Error("Failed to insert inner map into expected_hashes", "mntns_id", mntnsID, "error", err)
innerMap.Close()
if err := innerMap.Close(); err != nil {
slog.Error("Failed to close inner BPF map", "mntns_id", mntnsID, "error", err)
}
return
}

Expand Down Expand Up @@ -281,7 +285,9 @@ func handleContainerRemoved(gadgetCtx igoperators.GadgetContext, innerMaps *sync

if val, loaded := innerMaps.LoadAndDelete(mntnsID); loaded {
if m, ok := val.(*ebpf.Map); ok && m != nil {
m.Close()
if err := m.Close(); err != nil {
slog.Debug("Failed to close inner BPF map on container removal", "mntns_id", mntnsID, "error", err)
}
}
}

Expand Down
4 changes: 3 additions & 1 deletion internal/operators/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,9 @@ func formatAndPrintEvent(f *eventFields, data datasource.Data) {
}

outputMu.Lock()
fmt.Fprintln(os.Stdout, sb.String())
if _, err := fmt.Fprintln(os.Stdout, sb.String()); err != nil {
slog.Error("Failed to write event output", "error", err)
}
outputMu.Unlock()
}

Expand Down
4 changes: 3 additions & 1 deletion internal/runtime/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,7 @@ func (m *Manager) RunGadget(gadgetCtx *gadgetcontext.GadgetContext, params map[s
// Close cleans up runtime resources
func (m *Manager) Close() {
slog.Debug("Closing runtime manager")
m.runtime.Close()
if err := m.runtime.Close(); err != nil {
slog.Error("Error closing runtime", "error", err)
}
}
30 changes: 23 additions & 7 deletions internal/sbom/sbom.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"strings"
"sync"

securejoin "github.com/cyphar/filepath-securejoin"
dockerconfig "github.com/docker/cli/cli/config"
"github.com/docker/cli/cli/config/configfile"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
Expand Down Expand Up @@ -135,8 +136,11 @@ func ImageRefFromDockerConfig(containerID string) string {
}

for _, root := range dockerDataRootsFn() {
cfgPath := filepath.Join(root, "containers", containerID, "config.v2.json")
data, err := os.ReadFile(cfgPath)
cfgPath, err := securejoin.SecureJoin(root, filepath.Join("containers", containerID, "config.v2.json"))
if err != nil {
continue
}
data, err := os.ReadFile(filepath.Clean(cfgPath))
if err != nil {
continue
}
Expand Down Expand Up @@ -335,7 +339,11 @@ func fetchCosignAttestation(ctx context.Context, repo *remote.Repository, imageD
if err != nil {
return nil, fmt.Errorf("fetching cosign attestation manifest: %w", err)
}
defer rc.Close()
defer func() {
if err := rc.Close(); err != nil {
slog.Debug("Failed to close cosign attestation manifest reader", "error", err)
}
}()

manifestBytes, err := io.ReadAll(rc)
if err != nil {
Expand Down Expand Up @@ -368,7 +376,11 @@ func fetchDSSEEnvelope(ctx context.Context, repo *remote.Repository, layer ocisp
if err != nil {
return nil, fmt.Errorf("fetching DSSE envelope: %w", err)
}
defer layerRC.Close()
defer func() {
if err := layerRC.Close(); err != nil {
slog.Debug("Failed to close DSSE envelope reader", "error", err)
}
}()

envelopeBytes, err := io.ReadAll(layerRC)
if err != nil {
Expand Down Expand Up @@ -459,10 +471,14 @@ func loadDockerConfig() (*configfile.ConfigFile, error) {
return cfg, nil
}

sudoHome := filepath.Join("/home", sudoUser)
sudoCfg, err := dockerconfig.Load(filepath.Join(sudoHome, ".docker"))
sudoHome, err := securejoin.SecureJoin("/home", sudoUser)
if err != nil {
slog.Debug("Could not resolve home directory for SUDO_USER", "error", err)
return cfg, nil
}
sudoCfg, err := dockerconfig.Load(filepath.Clean(filepath.Join(sudoHome, ".docker")))
if err != nil {
slog.Debug("Could not load Docker config for SUDO_USER", "user", sudoUser, "error", err)
slog.Debug("Could not load Docker config for SUDO_USER")
Comment thread
Sefi4 marked this conversation as resolved.
return cfg, nil
}

Expand Down
11 changes: 8 additions & 3 deletions internal/sbom/sbom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"os"
"path/filepath"
"testing"

"github.com/go-jose/go-jose/v4/testutils/require"
Comment on lines +23 to +24

Copilot AI Feb 28, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

internal/sbom/sbom_test.go adds a dependency on github.com/go-jose/go-jose/v4/testutils/require. This is a testutils package from an unrelated module and generally not intended as a stable external test assertion library; it also forces adding go-jose as a direct module dependency for a single NoError call. Prefer using standard testing checks (or an existing/common assertion library in this repo) to avoid the extra dependency and potential future breakage.

Suggested change
"github.com/go-jose/go-jose/v4/testutils/require"

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is unrelated to this PR. I'll fix it in a follow-up PR

)

func TestNormalizeImageRef(t *testing.T) {
Expand Down Expand Up @@ -99,14 +101,17 @@ func TestImageRefFromDockerConfig(t *testing.T) {
tmpDir := t.TempDir()
containerID := "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
containerDir := filepath.Join(tmpDir, "containers", containerID)
if err := os.MkdirAll(containerDir, 0o755); err != nil {
if err := os.MkdirAll(containerDir, 0o750); err != nil {
t.Fatal(err)
}

writeConfig := func(image string) {
cfg := map[string]any{"Config": map[string]string{"Image": image}}
data, _ := json.Marshal(cfg)
os.WriteFile(filepath.Join(containerDir, "config.v2.json"), data, 0o644)
data, err := json.Marshal(cfg)
require.NoError(t, err)
if err := os.WriteFile(filepath.Join(containerDir, "config.v2.json"), data, 0o600); err != nil {
t.Fatal(err)
}
}

// Temporarily override dockerDataRoots to use our tmpDir.
Expand Down
2 changes: 1 addition & 1 deletion internal/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func GetHostPidNamespaceID() (uint64, error) {
func ValidateBPFLSM() error {
data, err := os.ReadFile(lsmFilePath)
if err != nil {
return fmt.Errorf("failed to read %s: %w\nBPF LSM support cannot be verified. Ensure the kernel has LSM support enabled.", lsmFilePath, err)
return fmt.Errorf("failed to read %s: Unable to verify whether BPF LSM is enabled: %w", lsmFilePath, err)
}

lsmList := strings.TrimSpace(string(data))
Expand Down
2 changes: 1 addition & 1 deletion internal/utils/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func TestValidateBPFLSM(t *testing.T) {
tmpDir := t.TempDir()
tmpFile := filepath.Join(tmpDir, "lsm")

if err := os.WriteFile(tmpFile, []byte(tt.lsmContent), 0644); err != nil {
if err := os.WriteFile(tmpFile, []byte(tt.lsmContent), 0600); err != nil {
t.Fatalf("Failed to create temp file: %v", err)
}

Expand Down
Loading