Standard CWE-78 pattern (same class as CWE-78-rows-err hotfix #1071):
iterating over sql.Rows without checking rows.Err() after the loop silently
ignores connection errors. Add the deferred Err() check to:
- approvals.go: ListPendingApprovals (GET /approvals)
- approvals.go: List (GET /workspaces/:id/approvals)
- tokens.go: List (GET /workspaces/:id/tokens)
- instructions.go: Resolve handler (GET /workspaces/:id/instructions/resolve)
- instructions.go: scanInstructions helper (used by List handler)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
loadWorkspaceSecrets() iterates over global_secrets and
workspace_secrets rows without checking rows.Err() after the loop.
If the connection is interrupted mid-iteration, the error is silently
ignored. Add the standard deferred Err() check (pattern from
secrets.go, org_helpers.go) to both loops.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Cherry-picks the filter from main commit 8fced202: only transport
config.yaml and files under prompts/ from the template directory to the
control plane. Arbitrary template files (adapter.py, Dockerfile, etc.)
are now excluded regardless of size, reducing the transport surface.
Also adds a test case verifying adapter.py is excluded even when within
the size limit.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
collectCPConfigFiles was added in PR #1075 (OFFSEC-010) but never called —
the symlink guards were dead code. This patch wires the function into
CPProvisioner.Start so the guards actually protect the CP request path.
Changes:
1. cpProvisionRequest gains ConfigFiles map[string]string field
(base64-encoded, same shape as Docker provisioner's WriteFilesToContainer)
2. Start calls collectCPConfigFiles(cfg) before building the request;
errors propagate as hard failures (a workspace without its config files
is not usable)
3. Two new tests:
- TestStart_CollectsConfigFiles: verifies TemplatePath files AND
ConfigFiles map appear in the CP request body, base64-encoded
- TestStart_SymlinkTemplatePathError: verifies a symlink TemplatePath
causes Start to fail, exercising the OFFSEC-010 root-symlink guard
Without this wiring, a malicious operator could bypass the WalkDir symlink
guards by passing TemplatePath as a symlink to the CP.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>