Security Implications of --disable-file-downloads and --disable-file-uploads in code-server

Disabling file transfers with --disable-file-downloads and --disable-file-uploads eliminates two primary attack vectors in code-server by removing UI elements and blocking APIs that would otherwise allow data exfiltration or malicious file injection into remote workspaces.

The coder/code-server project runs a full VS Code instance inside a remote browser, exposing the underlying file system through the editor's interface. When deploying in security-sensitive environments, administrators must control how data flows between the remote host and client machines. This article examines the specific security mechanisms behind these CLI flags, tracing their implementation from src/node/cli.ts through to the frontend context keys that gate user actions.

Architecture of File Transfer Controls

The security model relies on a propagation chain: CLI flags populate the environment service, which publishes context keys that the UI layer consumes to hide elements and reject API calls.

CLI Flag Definition and Injection

The flags are defined in src/node/cli.ts at lines 182–191, where the argument parser registers both options and injects them into the process environment. When present, these boolean values flow into the args object that the entire application consumes.

  • --disable-file-downloads: Stored at lines 182–186, this flag controls whether users can export files from the remote workspace to their local machine.
  • --disable-file-uploads: Defined at lines 187–191, this flag governs the ability to import files from the client into the remote environment.

Context Key Propagation to the Frontend

The bridge between the backend configuration and frontend enforcement occurs in patches/getting-started.diff (lines 206–228). This patch injects two readonly properties into the browser's environment service:

  • isEnabledFileDownloads → published as the context key IsEnabledFileDownloads
  • isEnabledFileUploads → published as the context key IsEnabledFileUploads

As implemented in patches/external-file-actions.diff, the UI layer checks these context keys before rendering the "Show Local" download button, enabling drag-and-drop handlers, or executing transfer commands. When a flag is set to false, the associated UI elements are removed from the DOM and the underlying API returns errors to any extension attempting to invoke transfers.

Security Threats Mitigated by Disabling Transfers

Enabling these flags (setting them to true to disable the features) reduces the attack surface by closing specific data channels. The security consequences differ significantly from the default permissive state.

Preventing Data Exfiltration

By default, code-server renders a "Show Local" button in the file tree that allows users to download any file they have permission to read. In environments containing sensitive source code, credentials, or configuration files, this creates a straightforward exfiltration channel. When --disable-file-downloads is active, the button is hidden and the download command handler rejects all requests, ensuring that even a compromised user session cannot easily leak files through the browser interface.

Blocking Malware and Payload Injection

The upload mechanism provides a direct path for attackers to introduce binaries, scripts, or malicious payloads into the remote workspace. An adversary who gains access to a running VS Code session could drag-and-drop or programmatically upload executable files that run on the host. The --disable-file-uploads flag removes the upload area from the file-tree UI and blocks the upload API, preventing injection even if the session is compromised.

Reducing Extension Attack Surface

Extensions frequently use the file transfer APIs to fetch dependencies or resources. While legitimate extensions use this for language servers and linters, malicious or compromised extensions can abuse these channels to pull in additional payloads or exfiltrate data. Disabling transfers causes such extensions to fail during initialization or execution, breaking functionality but preventing abuse. This is verified in the end-to-end tests located in test/e2e/downloads.test.ts and test/e2e/uploads.test.ts, which confirm that API calls return errors when the flags are enabled.

Configuration and Verification Examples

Launching with Security Flags

Apply these flags at startup to enforce transfer restrictions immediately:


# Disable both upload and download capabilities

code-server --disable-file-downloads --disable-file-uploads

# Alternative: Environment variables for containerized deployments

CS_DISABLE_FILE_DOWNLOADS=1 CS_DISABLE_FILE_UPLOADS=1 code-server

The CLI parser in src/node/cli.ts processes these arguments and stores them in the global args configuration object, which the environment service reads during initialization.

Verifying Flags Within Extensions

Extension developers or security auditors can check these permissions programmatically through the context key service:

import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IsEnabledFileDownloads, IsEnabledFileUploads } from 'vs/platform/contextkey/common/contextkey';

function auditTransferPermissions(accessor: ServicesAccessor): void {
    const contextKeyService = accessor.get(IContextKeyService);
    
    const downloadsAllowed = contextKeyService.getValue(IsEnabledFileDownloads.key);
    const uploadsAllowed = contextKeyService.getValue(IsEnabledFileUploads.key);
    
    console.log('File downloads enabled:', downloadsAllowed);
    console.log('File uploads enabled:', uploadsAllowed);
}

When the server runs with flags set, these context keys resolve to false, causing any conditional UI rendering or command execution to bypass the transfer functionality.

Frontend Error Handling

The frontend code explicitly checks the environment service before initiating transfers, as shown in the typing definitions from patches/external-file-actions.diff:

import { IFileService } from 'vs/platform/files/common/fileService';

async function safeDownloadFile(fileService: IFileService, uri: URI): Promise<void> {
    if (!environmentService.isEnabledFileDownloads) {
        throw new Error('File downloads are disabled by the server configuration.');
    }
    // Proceed with standard download workflow...
}

This ensures that even if a user circumvents the UI hiding mechanisms, the underlying service layer still enforces the security policy.

Summary

  • --disable-file-downloads removes the "Show Local" button and download commands from the UI, preventing users from exporting files through the browser and blocking extensions from using the download API.
  • --disable-file-uploads disables drag-and-drop import functionality and upload areas, stopping both manual and programmatic file injection into the workspace.
  • The enforcement mechanism flows from src/node/cli.ts through environment services and context keys (IsEnabledFileDownloads, IsEnabledFileUploads) to UI gating, as implemented in patches/getting-started.diff.
  • End-to-end tests in test/e2e/downloads.test.ts and test/e2e/uploads.test.ts validate that these flags correctly block transfer APIs.
  • The trade-off requires users to rely on external tools like scp, rsync, or Git for legitimate file transfers, but significantly reduces risks of data exfiltration and malware injection.

Frequently Asked Questions

Can users bypass these flags using VS Code extensions?

No. The flags propagate to context keys that the entire frontend ecosystem respects, including the extension host. When IsEnabledFileDownloads or IsEnabledFileUploads resolve to false, the underlying service layers return errors to any API caller, including extensions. Malicious extensions attempting to exfiltrate data or upload payloads will fail at the API boundary, as confirmed by the test suites in test/e2e/downloads.test.ts and test/e2e/uploads.test.ts.

Do these flags affect Git operations or terminal-based file transfers?

No. These flags only disable the UI-driven and API-driven transfer mechanisms built into code-server's browser interface. Git fetch/pull/push operations, terminal-based scp commands, and other external transfer tools operate outside the VS Code extension API and remain unaffected. Users must resort to these external methods when the flags are enabled.

What happens if I only disable one flag but not the other?

Each flag operates independently. Disabling only --disable-file-downloads allows users to upload files while preventing downloads, creating a one-way data flow suitable for ingestion-only workflows. Conversely, disabling only --disable-file-uploads permits data export while blocking imports. The context keys IsEnabledFileDownloads and IsEnabledFileUploads are evaluated separately throughout the codebase.

Are these flags available in all versions of code-server?

These flags were introduced through specific patches including patches/getting-started.diff and patches/external-file-actions.diff. Administrators should verify their installation includes these patches by checking the version release notes or inspecting src/node/cli.ts for the flag definitions at lines 182–191. The end-to-end test coverage in test/e2e/ confirms the functionality is active in builds that include these files.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →