Skip to content

Add agent-initiated secret creation (harness-auth-flow Phase 1)#236

Open
ptone wants to merge 7 commits into
mainfrom
scion/harness-auth-flow
Open

Add agent-initiated secret creation (harness-auth-flow Phase 1)#236
ptone wants to merge 7 commits into
mainfrom
scion/harness-auth-flow

Conversation

@ptone

@ptone ptone commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #235

  • New Hub API endpoint PUT /api/v1/agents/{agentID}/secrets/{key} for agent-initiated project-scoped secret creation
  • New sciontool secret set command for agents to store secrets from within containers
  • New Client.SetSecret() method in the sciontool hub client

Test plan

  • Hub handler unit tests: valid create (201), conflict (409), force overwrite (204), invalid token (401), user token rejected (401), agent ID mismatch (403), empty value (400), invalid type (400), file type validation, method not allowed (405), missing key (400), agent provenance in createdBy
  • Client unit tests: request construction, created response, no-content response, conflict error, not configured error, server error
  • All pre-existing secret tests pass (TestSecret_UserScope_*)

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces agent-initiated secret management by adding a new sciontool secret set CLI command and a corresponding PUT /api/v1/agents/{id}/secrets/{key} endpoint on the Hub server, along with comprehensive unit tests. The review feedback highlights a potential nil pointer dereference panic on the server if the secret backend is unconfigured, an incorrect file size limit validation due to base64 encoding overhead, and a potential OOM risk in the CLI when reading large files without a prior size check.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread pkg/hub/handlers.go
Comment on lines +7929 to +7933
var req AgentSetSecretRequest
if err := readJSON(r, &req); err != nil {
BadRequest(w, "Invalid request body: "+err.Error())
return
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The handler does not check if s.secretBackend is nil before calling GetMeta or Set on it. If the Hub is run without a configured secrets backend, this will cause a nil pointer dereference panic and crash the request handler. Add a nil check to safely return a 501 Not Implemented or 500 Internal Server Error instead.

Suggested change
var req AgentSetSecretRequest
if err := readJSON(r, &req); err != nil {
BadRequest(w, "Invalid request body: "+err.Error())
return
}
if s.secretBackend == nil {
writeError(w, http.StatusNotImplemented, ErrCodeInternalError, "Secret storage is not configured on this Hub", nil)
return
}
var req AgentSetSecretRequest
if err := readJSON(r, &req); err != nil {
BadRequest(w, "Invalid request body: "+err.Error())
return
}

Comment thread pkg/hub/handlers.go Outdated
Comment on lines +7971 to +7978
if len(req.Value) > 64*1024 {
ValidationError(w, "file secret value exceeds 64 KiB limit", map[string]interface{}{
"field": "value",
"limit": "65536 bytes",
"size": len(req.Value),
})
return
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The validation checks len(req.Value) against 64*1024 (64 KiB). However, req.Value is a base64-encoded string, which is ~33% larger than the raw file content. This means the actual file size limit enforced is only ~48 KiB, contradicting the error message ("file secret value exceeds 64 KiB limit"). Adjust the limit check to account for the base64 encoding overhead so that a full 64 KiB file can be uploaded.

// 64 KiB of raw data is approx 87382 bytes when base64-encoded.
if len(req.Value) > 87382 {
	ValidationError(w, "file secret value exceeds 64 KiB limit", map[string]interface{}{
		"field": "value",
		"limit": "65536 bytes",
		"size":  len(req.Value) * 3 / 4,
	})
	return
}

Comment on lines +85 to +89
data, err := os.ReadFile(filePath)
if err != nil {
fmt.Fprintf(cmd.ErrOrStderr(), "Error: failed to read file %s: %v\n", filePath, err)
os.Exit(1)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Reading the entire file into memory using os.ReadFile without checking its size first can cause Out-Of-Memory (OOM) issues or waste significant CPU/disk I/O if a user accidentally passes a very large file. Since the server enforces a 64 KiB limit anyway, use os.Stat to check the file size first and fail early.

info, err := os.Stat(filePath)
if err != nil {
	fmt.Fprintf(cmd.ErrOrStderr(), "Error: failed to stat file %s: %v\n", filePath, err)
	os.Exit(1)
}
if info.Size() > 64*1024 {
	fmt.Fprintf(cmd.ErrOrStderr(), "Error: file %s size (%d bytes) exceeds the 64 KiB limit\n", filePath, info.Size())
	os.Exit(1)
}
data, err := os.ReadFile(filePath)
if err != nil {
	fmt.Fprintf(cmd.ErrOrStderr(), "Error: failed to read file %s: %v\n", filePath, err)
	os.Exit(1)
}

Scion Agent (harness-auth-flow-p2-fix) added 3 commits June 11, 2026 23:09
…o-auth behavior

Phase 3a - Config-driven OverlayFileSecrets:
- Add `field` attribute to HarnessAuthFileRequirement for explicit AuthConfig mapping
- Implement OverlayFileSecretsFromConfig() with backward-compat target-suffix fallback
- Add field values to all harness config.yaml required_files entries

Phase 3b - Capture-auth scripts:
- Add capture_auth.py for claude, codex, gemini, and opencode harnesses
- Implement StageCaptureAuthAssets() to stage scripts and generate
  capture-auth-config.json from auth metadata at provision time
- Wire staging into both ContainerScriptHarness.Provision() and
  builtin harness provision path in pkg/agent/provision.go
- Register capture_auth.py as a harness config root support file

Phase 3c - No-auth harness behavior:
- Add HarnessNoAuthConfig struct with behavior and message fields
- Add no_auth sections to all four harness config.yaml files
- Read NoAuth config in agent run and propagate to RunConfig
- Override container command to drop-to-shell when NoAuth is set

Includes JSON schema updates, unit tests for OverlayFileSecretsFromConfig
and StageCaptureAuthAssets, and all existing tests pass.
…e check, filepath.Join, file stat

- Validate base64 encoding before storing secrets (HTTP 400 on invalid)
- Reject file secret targets containing '..' to prevent path traversal
- Use decoded byte length for exact 64KB size check instead of approximation
- Use filepath.Join for home directory expansion in sciontool
- Add os.Stat size check before reading file into memory
@ptone ptone force-pushed the scion/harness-auth-flow branch from 3e6f139 to 579c0dc Compare June 11, 2026 23:13
Scion Agent (harness-auth-flow-p2-fix) added 4 commits June 11, 2026 23:16
…taging, add comments

- F1: Call OverlayFileSecretsFromConfig() when harness auth metadata is
  available, falling back to OverlayFileSecrets() when it isn't
- F2: Guard StageCaptureAuthAssets in ProvisionAgent to skip
  container-script harnesses that already stage during Provision()
- F4: Sort capture-auth credentials by key for deterministic JSON output
- F5: Add TODO comment noting only drop-to-shell behavior is implemented
- F7: Add comment explaining why empty-TargetSuffix entries are skipped
- F8: Raise capture-auth staging failure from debug to warning level
- Handle bare `~` and `~/` in secret set file path expansion to prevent panic
- Ensure leading slash on TargetSuffix to avoid `~.claude` instead of `~/.claude`
- Wrap json.load in try/except in all 4 capture_auth.py files for invalid/empty JSON
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.

Agent-initiated secret creation (harness-auth-flow Phase 1)

1 participant