act icon indicating copy to clipboard operation
act copied to clipboard

Machine's ip address recorded in generated man page

Open jelly opened this issue 4 months ago β€’ 9 comments

Bug report info

act version:            0.2.80
GOOS:                   linux
GOARCH:                 amd64
NumCPU:                 16
Docker host:            DOCKER_HOST environment variable is not set
Sockets found:
        $XDG_RUNTIME_DIR/podman/podman.sock
Config files:
Build info:
        Go version:            go1.24.5
        Module path:           github.com/nektos/act
        Main version:          (devel)
        Main path:             github.com/nektos/act
        Main checksum:
        Build settings:
                -buildmode:           pie
                -compiler:            gc
                -trimpath:            true
                CGO_ENABLED:          1
                GOARCH:               amd64
                GOOS:                 linux
                GOAMD64:              v1

Error: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

Command used with act

act --man-page

Describe issue

The generated man page includes the outbound ip address of the server which the act generated the man page of. This makes the package non-reproducible for Arch Linux as rebuilding the package on a different server will record a different IP Address making the package non-reproducible.

From a privacy perspective it also doesn't seem worth it to record the users IP Address in a man page, replacing it with an example ip address should resolve both issues.

β”‚ β”œβ”€β”€ usr/share/man/man1/act.1.gz
β”‚ β”‚ β”œβ”€β”€ act.1
β”‚ β”‚ β”‚ @@ -26,15 +26,15 @@
β”‚ β”‚ β”‚  	If action contents exists, it will not be fetch and pull again. If turn on this, will turn off force pull
β”‚ β”‚ β”‚  
β”‚ β”‚ β”‚  .PP
β”‚ β”‚ β”‚  \fB-a\fP, \fB--actor\fP="nektos/act"
β”‚ β”‚ β”‚  	user that triggered the event
β”‚ β”‚ β”‚  
β”‚ β”‚ β”‚  .PP
β”‚ β”‚ β”‚ -\fB--artifact-server-addr\fP="162.55.28.166"
β”‚ β”‚ β”‚ +\fB--artifact-server-addr\fP="147.75.84.133"
β”‚ β”‚ β”‚  	Defines the address to which the artifact server binds.
β”‚ β”‚ β”‚  
β”‚ β”‚ β”‚  .PP
β”‚ β”‚ β”‚  \fB--artifact-server-path\fP=""
β”‚ β”‚ β”‚  	Defines the path where the artifact server stores uploads and retrieves downloads from. If not specified the artifact server will not start.
β”‚ β”‚ β”‚  
β”‚ β”‚ β”‚  .PP
β”‚ β”‚ β”‚ @@ -46,15 +46,15 @@
β”‚ β”‚ β”‚  	bind working directory to container, rather than copy
β”‚ β”‚ β”‚  
β”‚ β”‚ β”‚  .PP
β”‚ β”‚ β”‚  \fB--bug-report\fP[=false]
β”‚ β”‚ β”‚  	Display system information for bug report
β”‚ β”‚ β”‚  
β”‚ β”‚ β”‚  .PP
β”‚ β”‚ β”‚ -\fB--cache-server-addr\fP="162.55.28.166"
β”‚ β”‚ β”‚ +\fB--cache-server-addr\fP="147.75.84.133"
β”‚ β”‚ β”‚  	Defines the address to which the cache server binds.
β”‚ β”‚ β”‚  
β”‚ β”‚ β”‚  .PP
β”‚ β”‚ β”‚  \fB--cache-server-external-url\fP=""
β”‚ β”‚ β”‚  	Defines the external URL for if the cache server is behind a proxy. e.g.: https://act-cache-server.example.com. Be careful that there is no trailing slash.
β”‚ β”‚ β”‚  
β”‚ β”‚ β”‚  .PP

Link to GitHub repository

No response

Workflow content

None

Relevant log output

None

Additional information

No response

jelly avatar Aug 04 '25 15:08 jelly

It's used as a default value for that option. Manpages are generated straight from the flags declaration. If you wish to not include that, you can patch the source: https://github.com/nektos/act/blob/bf8e52ba712f06780032b6419ff7e89f7a05a977/cmd/root.go#L118C2-L118C9

panekj avatar Aug 06 '25 15:08 panekj

I believe this is about the archlinux package repository using this command in a packaging script

IMHO knowing which ip is used by act in --help by default is helpful, man page generation was not by initiative.

Maybe redact them in the man page command?

func sanitizeFlagDefaults(cmd *cobra.Command) {
    cmd.PersistentFlags().VisitAll(func(f *pflag.Flag) {
        if isIPAddress(f.DefValue) {
            f.DefValue = "[REDACTED_IP]"
        }
    })
}

func isIPAddress(value string) bool {
    ipRegex := regexp.MustCompile(`\b(?:\d{1,3}\.){3}\d{1,3}\b`)
    return ipRegex.MatchString(value)
}

ChristopherHX avatar Aug 06 '25 20:08 ChristopherHX

I was tryin to do it via Set() but it seems it doesn't work that way. The above change works, but I thought we could maybe also change the type we use for those addresses from StringVarP to IPVarP so that way we get the IP address validation and could drop the regex.

0001-fix-replace-address-flags-with-net.IP-and-redact-in-.patch
From 0fce70c1aa7123c64c48bff1937028f40ccedfcb Mon Sep 17 00:00:00 2001
From: Jakub Panek <[email protected]>
Date: Wed, 6 Aug 2025 23:09:03 +0200
Subject: [PATCH] fix: replace address flags with net.IP and redact in manpages

---
 cmd/input.go                 |  5 +++--
 cmd/root.go                  | 19 ++++++++++++++-----
 pkg/artifactcache/handler.go |  2 +-
 pkg/common/outbound_ip.go    |  2 ++
 4 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/cmd/input.go b/cmd/input.go
index 36c7f7ace6f5..2408d5ad2d24 100644
--- a/cmd/input.go
+++ b/cmd/input.go
@@ -1,7 +1,8 @@
 package cmd
 
 import (
+	"net"
 	"path/filepath"
 
 	log "github.com/sirupsen/logrus"
 )
@@ -41,14 +42,14 @@ type Input struct {
 	containerCapAdd                    []string
 	containerCapDrop                   []string
 	autoRemove                         bool
 	artifactServerPath                 string
-	artifactServerAddr                 string
+	artifactServerAddr                 net.IP
 	artifactServerPort                 string
 	noCacheServer                      bool
 	cacheServerPath                    string
 	cacheServerExternalURL             string
-	cacheServerAddr                    string
+	cacheServerAddr                    net.IP
 	cacheServerPort                    uint16
 	jsonLogger                         bool
 	noSkipCheckout                     bool
 	remoteName                         string
diff --git a/cmd/root.go b/cmd/root.go
index f51ed64b77ce..a014a7d7dd09 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -112,15 +112,15 @@ func createRootCommand(ctx context.Context, input *Input, version string) *cobra
 	rootCmd.PersistentFlags().StringVarP(&input.containerDaemonSocket, "container-daemon-socket", "", "", "URI to Docker Engine socket (e.g.: unix://~/.docker/run/docker.sock or - to disable bind mounting the socket)")
 	rootCmd.PersistentFlags().StringVarP(&input.containerOptions, "container-options", "", "", "Custom docker container options for the job container without an options property in the job definition")
 	rootCmd.PersistentFlags().StringVarP(&input.githubInstance, "github-instance", "", "github.com", "GitHub instance to use. Only use this when using GitHub Enterprise Server.")
 	rootCmd.PersistentFlags().StringVarP(&input.artifactServerPath, "artifact-server-path", "", "", "Defines the path where the artifact server stores uploads and retrieves downloads from. If not specified the artifact server will not start.")
-	rootCmd.PersistentFlags().StringVarP(&input.artifactServerAddr, "artifact-server-addr", "", common.GetOutboundIP().String(), "Defines the address to which the artifact server binds.")
+	rootCmd.PersistentFlags().IPVarP(&input.artifactServerAddr, "artifact-server-addr", "", common.OutboundIP, "Defines the address to which the artifact server binds.")
 	rootCmd.PersistentFlags().StringVarP(&input.artifactServerPort, "artifact-server-port", "", "34567", "Defines the port where the artifact server listens.")
 	rootCmd.PersistentFlags().BoolVarP(&input.noSkipCheckout, "no-skip-checkout", "", false, "Use actions/checkout instead of copying local files into container")
 	rootCmd.PersistentFlags().BoolVarP(&input.noCacheServer, "no-cache-server", "", false, "Disable cache server")
 	rootCmd.PersistentFlags().StringVarP(&input.cacheServerPath, "cache-server-path", "", filepath.Join(CacheHomeDir, "actcache"), "Defines the path where the cache server stores caches.")
 	rootCmd.PersistentFlags().StringVarP(&input.cacheServerExternalURL, "cache-server-external-url", "", "", "Defines the external URL for if the cache server is behind a proxy. e.g.: https://act-cache-server.example.com. Be careful that there is no trailing slash.")
-	rootCmd.PersistentFlags().StringVarP(&input.cacheServerAddr, "cache-server-addr", "", common.GetOutboundIP().String(), "Defines the address to which the cache server binds.")
+	rootCmd.PersistentFlags().IPVarP(&input.cacheServerAddr, "cache-server-addr", "", common.OutboundIP, "Defines the address to which the cache server binds.")
 	rootCmd.PersistentFlags().Uint16VarP(&input.cacheServerPort, "cache-server-port", "", 0, "Defines the port where the artifact server listens. 0 means a randomly available port.")
 	rootCmd.PersistentFlags().StringVarP(&input.actionCachePath, "action-cache-path", "", filepath.Join(CacheHomeDir, "act"), "Defines the path where the actions get cached and host workspaces created.")
 	rootCmd.PersistentFlags().BoolVarP(&input.actionOfflineMode, "action-offline-mode", "", false, "If action contents exists, it will not be fetch and pull again. If turn on this, will turn off force pull")
 	rootCmd.PersistentFlags().StringVarP(&input.networkName, "network", "", "host", "Sets a docker network name. Defaults to host.")
@@ -257,8 +257,17 @@ func generateManPage(cmd *cobra.Command) error {
 		Section: "1",
 		Source:  fmt.Sprintf("act %s", cmd.Version),
 	}
 	buf := new(bytes.Buffer)
+
+	func(cmd *cobra.Command) {
+		cmd.PersistentFlags().VisitAll(func(f *pflag.Flag) {
+			if f.Value.Type() == "ip" {
+				f.DefValue = "127.0.0.1"
+			}
+		})
+	}(cmd)
+
 	cobra.CheckErr(doc.GenMan(cmd, header, buf))
 	fmt.Print(buf.String())
 	return nil
 }
@@ -628,9 +637,9 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
 			ContainerCapAdd:                    input.containerCapAdd,
 			ContainerCapDrop:                   input.containerCapDrop,
 			AutoRemove:                         input.autoRemove,
 			ArtifactServerPath:                 input.artifactServerPath,
-			ArtifactServerAddr:                 input.artifactServerAddr,
+			ArtifactServerAddr:                 input.artifactServerAddr.String(),
 			ArtifactServerPort:                 input.artifactServerPort,
 			NoSkipCheckout:                     input.noSkipCheckout,
 			RemoteName:                         input.remoteName,
 			ReplaceGheActionWithGithubCom:      input.replaceGheActionWithGithubCom,
@@ -668,15 +677,15 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
 		if err != nil {
 			return err
 		}
 
-		cancel := artifacts.Serve(ctx, input.artifactServerPath, input.artifactServerAddr, input.artifactServerPort)
+		cancel := artifacts.Serve(ctx, input.artifactServerPath, input.artifactServerAddr.String(), input.artifactServerPort)
 
 		const cacheURLKey = "ACTIONS_CACHE_URL"
 		var cacheHandler *artifactcache.Handler
 		if !input.noCacheServer && envs[cacheURLKey] == "" {
 			var err error
-			cacheHandler, err = artifactcache.StartHandler(input.cacheServerPath, input.cacheServerExternalURL, input.cacheServerAddr, input.cacheServerPort, common.Logger(ctx))
+			cacheHandler, err = artifactcache.StartHandler(input.cacheServerPath, input.cacheServerExternalURL, input.cacheServerAddr.String(), input.cacheServerPort, common.Logger(ctx))
 			if err != nil {
 				return err
 			}
 			envs[cacheURLKey] = cacheHandler.ExternalURL() + "/"
diff --git a/pkg/artifactcache/handler.go b/pkg/artifactcache/handler.go
index 90d4218f29b4..b875bf66af26 100644
--- a/pkg/artifactcache/handler.go
+++ b/pkg/artifactcache/handler.go
@@ -77,9 +77,9 @@ func StartHandler(dir, customExternalURL string, outboundIP string, port uint16,
 	}
 
 	if outboundIP != "" {
 		h.outboundIP = outboundIP
-	} else if ip := common.GetOutboundIP(); ip == nil {
+	} else if ip := common.OutboundIP; ip == nil {
 		return nil, fmt.Errorf("unable to determine outbound IP address")
 	} else {
 		h.outboundIP = ip.String()
 	}
diff --git a/pkg/common/outbound_ip.go b/pkg/common/outbound_ip.go
index 66e15e5d774f..5381ab54bb7e 100644
--- a/pkg/common/outbound_ip.go
+++ b/pkg/common/outbound_ip.go
@@ -5,8 +5,10 @@
 	"sort"
 	"strings"
 )
 
+var OutboundIP = GetOutboundIP()
+
 // GetOutboundIP returns an outbound IP address of this machine.
 // It tries to access the internet and returns the local IP address of the connection.
 // If the machine cannot access the internet, it returns a preferred IP address from network interfaces.
 // It returns nil if no IP address is found.
-- 
2.50.1

panekj avatar Aug 06 '25 21:08 panekj

The only thing I would like to avoid is a static initializer of GetOutboundIP()

var OutboundIP = GetOutboundIP()

In one of my projects someone didn't like that an udp socket is even created if passing explicit values...

Otherwise your patch looks good, we might even get ip format validation.

My activity in the nektos/act project is declining

ChristopherHX avatar Aug 17 '25 14:08 ChristopherHX

I believe this is about the archlinux package repository using this command in a packaging script

Yes, we run "./$pkgname" --man-page >"$pkgname.1" which thus records the build machine's ip address. Building it on another host would change that address.

jelly avatar Aug 18 '25 18:08 jelly

Hi, I've created a PR with the recommended fix: https://github.com/nektos/act/pull/5948

Please let me know if this resolves the issue as expected.

AbhinavSivanandhan avatar Oct 10 '25 08:10 AbhinavSivanandhan

Hi! When you have a moment, could you take a look at #5948? What: redact IP-like defaults only for --man-page (no runtime change) β€” Fixes #5894. Notes: tight scope (-addr|-address, IPv4/:port), placeholder [auto-detected IP]. Tests + manual check added. I’m happy to switch the placeholder or adjust scope per your guidance. If this isn’t a priority, no worries, I’ll just close it. Thanks!

@jelly @panekj @ChristopherHX

AbhinavSivanandhan avatar Oct 13 '25 15:10 AbhinavSivanandhan

We cannot merge anything right now, this project is frozen only a single existing admin can repair this state. Requested explicitly a review in https://github.com/nektos/act/pull/5944.

Once this PR is merged or otherwise fixed, I would review your PR.


What follows is my own opinion on the state of nektos/act:

In long term I plan to leave this GitHub Organization and sunset my work here, because it is no longer maintainable

Moved my golang open source work to the Gitea Project, which has a more active and friendly community

ChristopherHX avatar Oct 13 '25 16:10 ChristopherHX

Thank you so much for letting me know Christopher! This saved me a lot of time.

AbhinavSivanandhan avatar Oct 13 '25 18:10 AbhinavSivanandhan