Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Log file transfers in the connection log #29145

Description

@sreya

Problem

We can already block common SSH file transfer entry points with CODER_AGENT_BLOCK_FILE_TRANSFER (scp, sftp, rsync, and nc), but when transfers are allowed we don't record what moved. SFTP runs in-process, so a file pull produces a generic SSH connection-log row without any file details.

For incident response we need to answer "what files were uploaded to or downloaded from this workspace?" This belongs in the connection log, not the audit log.

Proposal

We should add per-file SFTP records, including SCP clients using SFTP, under the existing SSH connection. Each record should show the workspace path, direction, byte counts, timestamps, and result. Expose these through expandable connection-log rows and a paginated API.

Legacy SCP, rsync, and nc should get command-level classification only. That classification is not a substitute for the per-file SFTP work.

Implementation Notes

  • Pass the session/channel UUID from agent/agentssh/agentssh.go into transfer reporting. This is not the shared SSH transport ID or an authenticated Coder user identity.
  • pkg/sftp.NewServer has no per-file observer today. Add an opt-in upstream observer and pin the dependency rather than replacing the filesystem backend for logging.
  • Emit one terminal summary per open attempt, not per packet, including failed opens and interrupted handles. Keep read/write counters separate.
  • Direction is relative to the workspace. Counts are observed I/O, not unique file size; a clean close does not prove a complete copy. Record requested paths, not assumed canonical or client-local paths.
  • Give transfers separate IDs and batching. Existing connection-only deduplication would collapse multiple file records.

Schema Updates

Add connection_log_file_transfers, rather than storing an unbounded file list on connection_logs:

Columns Type / purpose
connection_log_id, transfer_id UUIDs, composite primary key; transfer ID generated by the agent
organization_id UUID, derived by the server
protocol, path, direction Text; direction is upload, download, or both
bytes_read, bytes_written Nonnegative bigint counters
started_at, ended_at Timestamptz
result, error_code Text: closed, failed, or interrupted; nullable bounded error code

Reference connection_logs.id with cascading deletion and index (connection_log_id, started_at, transfer_id) for pagination. Add nullable transfer-method classification to SSH connection metadata without changing its connection type. Coordinate with #27412.

Considerations

Coverage

Legacy SCP, rsync, and nc invocations do not provide trustworthy per-file details. Record the recognized utility, not raw arguments or inferred filenames. Interactive-shell transfers, arbitrary network traffic, and the agent's HTTP file APIs are outside this first pass.

Ordering and delivery

Transfer batches must carry the original session envelope. In one transaction, upsert the parent using (connection_id, workspace_id, agent_name), resolve its database ID, and insert transfers idempotently. Preserve existing disconnect fields. This handles transfers arriving before the connection row and missing initial connection reports.

Delivery remains best effort. Use a separate bounded queue and batches so file events cannot starve connection reports or block file I/O. Expose dropped-event counts and mark incomplete detail where possible.

Retention

Use existing connection-log retention and authorization. Retention currently uses connection start time, even for active sessions: recent transfers on an old session share that cutoff. Test this behavior and prevent late transfer reports from recreating expired parents. The default remains unlimited retention.

Other Requirements

  • Keep the existing connection-log entitlement and enable/disable behavior. Do not emit audit events.
  • Record no contents or raw commands. Safely serialize unusual paths and escape them on display; bound payloads and flag truncation.
  • Negotiate reporting support with older agents/servers; unsupported logging must not break SSH or SFTP.
  • Preserve transfer blocking, SFTP filesystem semantics, working-directory behavior, and Windows support.

Implementation

Each step should follow red-green-refactor: add failing regression tests, implement, then simplify without changing behavior.

  • Extend TestAgent_SFTP, TestAgent_SCP, and TestAgent_FileTransferBlocked: both directions, multiple/empty files, directory-only sessions, bidirectional handles, normal EOF, failures, interruptions, and unchanged blocking.
  • Add the SFTP observer dependency and instrument agent/agentssh. Ensure transfer-producing sessions have a parent even when JetBrains session reporting would be suppressed.
  • Extend agent/proto, agent reporting, coderd/agentapi/connectionlog.go, and enterprise batching. Add migrations, SQLC queries and SDK types. Test ordering, retries, retention, queue saturation and mixed versions.
  • Add organization-scoped GET /api/v2/organizations/{organization}/connectionlog/{connectionlog}/file-transfers, authorized through the parent. Add lazy-loaded, paginated ConnectionLogRow details, behavior tests and stories. Test cross-organization denial and loading/error states.
  • Run generation, targeted Go/race tests, migration/RBAC/retention tests, frontend checks and frontend-review. Validate a multi-file upload/download end to end, including blocked and interrupted transfers, with no new audit entries.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions