Skip to content

Redact secrets in command and cluster API context - #145

Merged
Shashank Mittal (shashank-iitbhu) merged 3 commits into
mainfrom
cursor/redact-sensitive-api-context
Sep 29, 2026
Merged

Shashank Mittal (shashank-iitbhu) merged 3 commits into
mainfrom
cursor/redact-sensitive-api-context

Conversation

@shashank-iitbhu

@shashank-iitbhu Shashank Mittal (shashank-iitbhu) commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary

GET /api/v1/commands and /api/v1/clusters (and the matching single-object endpoints) return object context as JSON. Command and cluster configs can store credentials there (password, Snowflake private_key path, auth token path), so callers could read them from the API.

This always redacts password, private_key, and token on JSON marshal (REDACTED) while leaving the real values in memory, in DB persistence (Context.String()), and for plugins (Context.Unmarshal). Additional key names can be configured without a code change.

Configuration

The three built-in keys are always protected. Extra names can be configured globally in Heimdall YAML; matching is case-insensitive and applies recursively to command, cluster, and job contexts:

sensitive_context_keys:
  - api_key
  - client_secret

A restart is required after changing it.

Test plan

Auth header is X-Heimdall-User. Rebuild is required for the Go change.

docker compose up --build -d

Seed a command and cluster with secrets:

curl -sS -X PUT \
  -H 'X-Heimdall-User: test_user' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "redact-test",
    "version": "0.0.1",
    "plugin": "ping",
    "status": "active",
    "description": "local redaction check",
    "tags": ["type:ping"],
    "cluster_tags": ["type:localhost"],
    "context": {
      "username": "shelf-user",
      "password": "s3cr3t-should-not-leak",
      "nested": { "private_key": "/etc/key.pem", "endpoint": "https://example" }
    }
  }' \
  'http://127.0.0.1:9090/api/v1/command/redact-test'

curl -sS -X PUT \
  -H 'X-Heimdall-User: test_user' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "ranger-local",
    "version": "0.0.1",
    "status": "active",
    "description": "local redaction check",
    "tags": ["type:localhost"],
    "context": {
      "endpoint": "http://ranger.local",
      "username": "admin",
      "password": "ranger-admin-secret",
      "private_key": "/etc/heimdall/snowflake_key.pem",
      "token": "/etc/heimdall/chipmunk.token"
    }
  }' \
  'http://127.0.0.1:9090/api/v1/cluster/ranger-local'

GET (no auth header required):

curl -sS 'http://127.0.0.1:9090/api/v1/commands?id=redact-test' | jq '.data[].context'
curl -sS 'http://127.0.0.1:9090/api/v1/command/redact-test' | jq '.context'
curl -sS 'http://127.0.0.1:9090/api/v1/clusters?id=ranger-local' | jq '.data[].context'
curl -sS 'http://127.0.0.1:9090/api/v1/cluster/ranger-local' | jq '.context'

Expected:

{
  "nested": {
    "endpoint": "https://example",
    "private_key": "REDACTED"
  },
  "password": "REDACTED",
  "username": "shelf-user"
}
{
  "endpoint": "http://ranger.local",
  "password": "REDACTED",
  "private_key": "REDACTED",
  "token": "REDACTED",
  "username": "admin"
}

Pass: keys still present, values are "REDACTED", non-secret fields unchanged.

  • Local PUT/GET as above
  • go test ./...
  • Plugin unmarshal still sees real secrets (job auth still works)

Keep password, private_key, and similar fields in responses but replace their values so GET /commands and /clusters no longer leak credentials.
@shashank-iitbhu
Shashank Mittal (shashank-iitbhu) marked this pull request as ready for review September 22, 2026 08:01
Copilot AI lite review requested due to automatic review settings September 22, 2026 08:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Comment thread pkg/context/context.go
@prasadlohakpure

Copy link
Copy Markdown
Collaborator

Shashank Mittal (@shashank-iitbhu) can we simply add json tag "-" which will skip those attributes from marshalling into output bytes?

@shashank-iitbhu

Copy link
Copy Markdown
Contributor Author

Shashank Mittal (Shashank Mittal (@shashank-iitbhu)) can we simply add json tag "-" which will skip those attributes from marshalling into output bytes?

We can do this on the complete context blob, but not just on passwords.
It marshals Context, which is a map[string]any. Maps don’t have json tags per key.

Comment thread README.md Outdated
Keep the API table focused and document redaction next to the other credential-handling guidance.
@shashank-iitbhu
Shashank Mittal (shashank-iitbhu) merged commit faa3dea into main Sep 29, 2026
7 checks passed
@shashank-iitbhu
Shashank Mittal (shashank-iitbhu) deleted the cursor/redact-sensitive-api-context branch September 29, 2026 06:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants