CVE-2022-46156: Other (NVD-CWE-Other)
value: The Synthetic Monitoring Agent for Grafana's Synthetic Monitoring application provides probe functionality and executes network checks for monitoring remote targets. Users running the Synthetic Monitoring agent prior to version 0.12.0 in their local network are impacted. The authentication token used to communicate with the Synthetic Monitoring API is exposed through a debugging endpoint. This token can be used to retrieve the Synthetic Monitoring checks created by the user and assigned to the agent identified with that token. The Synthetic Monitoring API will reject connections from already-connected agents, so access to the token does not guarantee access to the checks. Version 0.12.0 contains a fix. Users are advised to rotate the agent tokens. After upgrading to version v0.12.0 or later, it's recommended that users of distribution packages review the configuration stored in `/etc/synthetic-monitoring/synthetic-monitoring-agent.conf`, specifically the `API_TOKEN` variable which has been renamed to `SM_AGENT_API_TOKEN`. As a workaround for previous versions, it's recommended that users review the agent settings and set the HTTP listening address in a manner that limits the exposure, for example, localhost or a non-routed network, by using the command line parameter `-listen-address`, e.g. `-listen-address localhost:4050`.
CWE description: NVD is only using a subset of CWE for mapping instead of the entire CWE, and the weakness type is not covered by that subset.
CVSS v3 base score: 3.3
Published: 2022-11-30T22:15Z
Repository: https://github.com/grafana/synthetic-monitoring-agent
Language: Other
Files changed: cmd/synthetic-monitoring-agent/main.go, scripts/package/config/systemd/synthetic-monitoring-agent.conf, scripts/package/config/systemd/synthetic-monitoring-agent.service
Commit date: 2022-11-29 09:50:09 -0600
Commit message: Fix: allow getting API token from environment

Allow the API token to be obtained from the environment variable
SM_AGENT_API_TOKEN. If it's passed on the command line, that value takes
precedence. For backwards compatibility, in case the user decides to NOT
replace the existing configuration files (in Debian these are config
files, and the user has the option to NOT replace them during an upgrade
if they have edited them, and because of the way we have set this up,
they *have* edited them).

In the shipped systemd service file, replace passing the token on the
command line in favor of passing it on the environment.

Signed-off-by: Marcelo E. Magallon <marcelo.magallon@grafana.com>

Diff: diff --git a/cmd/synthetic-monitoring-agent/main.go b/cmd/synthetic-monitoring-agent/main.go
index 3ce9fc9..de6758a 100644
--- a/cmd/synthetic-monitoring-agent/main.go
+++ b/cmd/synthetic-monitoring-agent/main.go
@@ -60,10 +60,18 @@ func run(args []string, stdout io.Writer) error {
 			version.Commit(),
 		)
 		return nil
 	}
 
+	// If the token is provided on the command line, prefer that. Otherwise
+	// pull it from the environment variable SM_AGENT_API_TOKEN. If that's
+	// not available, fallback to API_TOKEN, which was the environment
+	// variable name previously used in the systemd unit files.
+	//
+	// Using API_TOKEN should be deprecated after March 1st, 2023.
+	*apiToken = stringFromEnv("API_TOKEN", stringFromEnv("SM_AGENT_API_TOKEN", *apiToken))
+
 	if *apiToken == "" {
 		return fmt.Errorf("invalid API token")
 	}
 
 	baseCtx, cancel := context.WithCancel(context.Background())
@@ -233,5 +241,13 @@ func newConnectionBackoff() *backoff.Backoff {
 		Max:    30 * time.Second,
 		Factor: math.Pow(30./2., 1./8.), // reach the target in ~ 8 steps
 		Jitter: true,
 	}
 }
+
+func stringFromEnv(name string, override string) string {
+	if override != "" {
+		return override
+	}
+
+	return os.Getenv(name)
+}
diff --git a/scripts/package/config/systemd/synthetic-monitoring-agent.conf b/scripts/package/config/systemd/synthetic-monitoring-agent.conf
index df71fec..0f100dc 100644
--- a/scripts/package/config/systemd/synthetic-monitoring-agent.conf
+++ b/scripts/package/config/systemd/synthetic-monitoring-agent.conf
@@ -1,7 +1,7 @@
 # Enter API token retrieved from grafana.com here
-API_TOKEN='YOUR TOKEN HERE'
+SM_AGENT_API_TOKEN='YOUR TOKEN HERE'
 
 # Backend API server to connect to
 API_SERVER='synthetic-monitoring-grpc.grafana.net:443' 
 
 # Don't use TLS with connections to GRPC API
diff --git a/scripts/package/config/systemd/synthetic-monitoring-agent.service b/scripts/package/config/systemd/synthetic-monitoring-agent.service
index 9bc81fb..1053e74 100644
--- a/scripts/package/config/systemd/synthetic-monitoring-agent.service
+++ b/scripts/package/config/systemd/synthetic-monitoring-agent.service
@@ -4,10 +4,10 @@ Description=Grafana synthetic monitoring agent
 [Service]
 Type=simple
 User=root
 Group=root
 EnvironmentFile=/etc/synthetic-monitoring/synthetic-monitoring-agent.conf
-ExecStart=/usr/bin/synthetic-monitoring-agent --api-token=${API_TOKEN} --api-server-address=${API_SERVER} --api-insecure=${API_INSECURE} --listen-address=${LISTEN_ADDRESS} --verbose=${VERBOSE} --debug=${DEBUG} --features=${FEATURES}
+ExecStart=/usr/bin/synthetic-monitoring-agent --api-server-address=${API_SERVER} --api-insecure=${API_INSECURE} --listen-address=${LISTEN_ADDRESS} --verbose=${VERBOSE} --debug=${DEBUG} --features=${FEATURES}
 Restart=always
 
 [Install]
 WantedBy=network-online.target

Vulnerable code: API_TOKEN='YOUR TOKEN HERE'
ExecStart=/usr/bin/synthetic-monitoring-agent --api-token=${API_TOKEN} --api-server-address=${API_SERVER} --api-insecure=${API_INSECURE} --listen-address=${LISTEN_ADDRESS} --verbose=${VERBOSE} --debug=${DEBUG} --features=${FEATURES}
Fixed code: 	// If the token is provided on the command line, prefer that. Otherwise
	// pull it from the environment variable SM_AGENT_API_TOKEN. If that's
	// not available, fallback to API_TOKEN, which was the environment
	// variable name previously used in the systemd unit files.
	//
	// Using API_TOKEN should be deprecated after March 1st, 2023.
	*apiToken = stringFromEnv("API_TOKEN", stringFromEnv("SM_AGENT_API_TOKEN", *apiToken))


func stringFromEnv(name string, override string) string {
	if override != "" {
		return override
	}

	return os.Getenv(name)
}
SM_AGENT_API_TOKEN='YOUR TOKEN HERE'
ExecStart=/usr/bin/synthetic-monitoring-agent --api-server-address=${API_SERVER} --api-insecure=${API_INSECURE} --listen-address=${LISTEN_ADDRESS} --verbose=${VERBOSE} --debug=${DEBUG} --features=${FEATURES}