Back to blog
AWSBest PracticesCloud SecurityNetworkingStorage

AWS Transfer Family Server Has a Public Endpoint: Risks and Remediation

Learn why a public AWS Transfer Family endpoint is risky, how to switch to a secure VPC endpoint, and how to prevent public SFTP servers with policy-as-code.

TL;DR

This check flags AWS Transfer Family servers that use a public endpoint, exposing your SFTP, FTPS, or FTP service directly to the internet. Switch to a VPC endpoint and restrict access with security groups, or front the server with an Elastic IP and tight network controls.

AWS Transfer Family lets you run managed SFTP, FTPS, and FTP servers backed by S3 or EFS, without operating any file transfer infrastructure yourself. It is a convenient way to give partners, vendors, or internal teams a familiar file transfer protocol while storing the data in AWS. The convenience comes with a choice during setup that has real security consequences: the endpoint type.

When a Transfer Family server is created with a public endpoint, it becomes reachable from anywhere on the internet. This check, transfer_public, identifies any server in your account configured that way so you can decide whether that exposure is intentional and properly controlled.


What this check detects

The check inspects each AWS Transfer Family server and reads its EndpointType property. There are three possible values:

  • PUBLIC — the server is assigned an AWS-managed public endpoint reachable from the open internet. You cannot attach a security group or place it inside your VPC.
  • VPC — the server lives inside a VPC. You control access with security groups and subnet routing, and you can make it internet-facing, internal-only, or both.
  • VPC_ENDPOINT — a legacy option that AWS has deprecated in favor of VPC.

If the endpoint type is PUBLIC, the check reports a finding. It is not saying you have been breached, it is saying you have an internet-facing file transfer surface that deserves scrutiny.

Note: A public Transfer Family endpoint has no security group. There is no native way to limit which source IP addresses can reach it at the network layer. The only built-in filtering happens inside a custom identity provider or at the protocol authentication step, which is far later in the connection lifecycle than a firewall.


Why it matters

A public endpoint means the TCP port for your protocol (22 for SFTP, 21 for FTP/FTPS, plus the FTPS data port range) accepts connections from every IP address on the planet. That exposure introduces several concrete risks.

No network-layer access control

With a VPC endpoint you attach a security group and allow only your partners' known IP ranges. With a public endpoint, that lever does not exist. Every authentication attempt, valid or malicious, reaches your server. Attackers continuously scan the internet for open SFTP and FTP ports, and a public Transfer server will start receiving connection attempts within hours of going live.

Credential brute forcing and weak auth

If you use service-managed authentication with passwords, or a custom identity provider that accepts passwords, an exposed endpoint invites credential stuffing and brute force attempts. SFTP key-based auth is much stronger, but plenty of partner integrations still rely on passwords because the partner's client cannot manage keys cleanly.

Data exfiltration blast radius

Transfer Family servers usually have an IAM role granting access to one or more S3 buckets or EFS file systems. A compromised account on a public-facing server can read or overwrite the data that role can touch. For regulated data, financial records, or partner PII, that is a reportable incident waiting to happen.

Warning: FTP (plain, not FTPS) sends credentials and data in cleartext. AWS only allows FTP on VPC endpoints that are internal, never on public endpoints, but if you see FTP enabled anywhere in your account, treat it as a separate high priority finding regardless of this check.

Compliance friction

Frameworks like PCI DSS, HIPAA, and SOC 2 expect you to restrict network access to systems handling sensitive data. An internet-facing file transfer server with no source IP filtering is hard to justify in an audit, and you will likely end up writing a compensating control document instead of just fixing the endpoint type.


How to fix it

The endpoint type cannot be changed in place from PUBLIC to VPC while the server is running in all cases, and AWS requires the server to be stopped for the update. The cleanest path is usually to recreate the server with a VPC endpoint, but an in-place update is possible. Both approaches are covered below.

Danger: Changing the endpoint type changes the hostname your clients connect to and can break every existing partner integration. Plan a maintenance window, notify partners of the new endpoint, and update DNS or client configs before cutting over. Do not run these commands against a production server during business hours without coordination.

Step 1: Identify the affected servers

aws transfer list-servers \
  --query "Servers[?EndpointType=='PUBLIC'].[ServerId,State,IdentityProviderType]" \
  --output table

Step 2: Inspect the server before changing anything

aws transfer describe-server --server-id s-0123456789abcdef0

Note the protocols, the identity provider type, and the logging role so you can reproduce them on the new configuration.

Step 3: Stop the server

The endpoint type can only be updated while the server is offline.

aws transfer stop-server --server-id s-0123456789abcdef0

Wait for the state to become OFFLINE before continuing:

aws transfer describe-server \
  --server-id s-0123456789abcdef0 \
  --query "Server.State"

Step 4: Switch to a VPC endpoint

Pick subnets in the VPC where the server should live and a security group that allows only your trusted source ranges on the relevant port.

aws transfer update-server \
  --server-id s-0123456789abcdef0 \
  --endpoint-type VPC \
  --endpoint-details '{
    "SubnetIds": ["subnet-0a1b2c3d", "subnet-4e5f6g7h"],
    "VpcId": "vpc-0abc1234",
    "SecurityGroupIds": ["sg-0restrict01"]
  }'

If partners need to reach the server over the internet, attach Elastic IPs so the VPC endpoint becomes internet-facing while still keeping a security group in front of it:

aws transfer update-server \
  --server-id s-0123456789abcdef0 \
  --endpoint-type VPC \
  --endpoint-details '{
    "SubnetIds": ["subnet-0a1b2c3d"],
    "VpcId": "vpc-0abc1234",
    "SecurityGroupIds": ["sg-0restrict01"],
    "AddressAllocationIds": ["eipalloc-0aa11bb22"]
  }'

Step 5: Lock down the security group

Allow only known partner IP ranges, not 0.0.0.0/0.

aws ec2 authorize-security-group-ingress \
  --group-id sg-0restrict01 \
  --protocol tcp \
  --port 22 \
  --cidr 203.0.113.10/32

Step 6: Start the server and test

aws transfer start-server --server-id s-0123456789abcdef0

Once it reports ONLINE, connect from an allowed source and confirm authentication and file transfer work, then connect from a non-allowed source and confirm the connection is refused.

Tip: If you front the VPC endpoint with Elastic IPs, the public IP addresses stay stable across server restarts. Give partners those IPs or a CNAME pointing to them so future changes do not force another round of integration updates.

Terraform example

If you manage Transfer Family with Terraform, define the endpoint type explicitly so a public endpoint never sneaks in through a default.

resource "aws_transfer_server" "sftp" {
  identity_provider_type = "SERVICE_MANAGED"
  protocols              = ["SFTP"]
  endpoint_type          = "VPC"

  endpoint_details {
    vpc_id                 = aws_vpc.main.id
    subnet_ids             = [aws_subnet.private_a.id, aws_subnet.private_b.id]
    security_group_ids     = [aws_security_group.transfer.id]
    address_allocation_ids = [aws_eip.transfer_a.id, aws_eip.transfer_b.id]
  }

  tags = {
    Name = "partner-sftp"
  }
}

resource "aws_security_group" "transfer" {
  name_prefix = "transfer-sftp-"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["203.0.113.0/24"]
  }
}

How to prevent it from happening again

Fixing one server is good. Making sure the next one cannot be created public is better.

Policy-as-code in CI/CD

Add a Checkov or OPA policy that rejects Terraform plans with a public endpoint. Checkov ships a built-in check for exactly this:

checkov -d . --check CKV_AWS_164

Wire that into your pipeline so a pull request introducing endpoint_type = "PUBLIC" fails before it ever reaches an apply.

Service Control Policy guardrail

For organizations using AWS Organizations, you can deny creation of public Transfer servers across every account with an SCP condition.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyPublicTransferServers",
      "Effect": "Deny",
      "Action": "transfer:CreateServer",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "transfer:EndpointType": "PUBLIC"
        }
      }
    }
  ]
}

Note: Test SCP conditions in a non-production OU first. The transfer:EndpointType condition key behavior should be verified against your accounts, because a misconfigured deny can block legitimate VPC server creation if combined with broader statements.

Continuous monitoring with Lensix

Point detection catches drift that slips past pipeline gates, like a server created by hand in the console during an incident. Run the transfer_public check on a schedule so any new public endpoint is surfaced quickly rather than discovered during an audit months later.


Best practices

  • Default to VPC endpoints. Treat public endpoints as the exception that requires a written justification, not the starting point.
  • Use SFTP with key-based authentication. Avoid FTP entirely, and prefer SSH keys over passwords wherever the partner's client supports them.
  • Restrict source IPs. Whether through security groups on a VPC endpoint or a custom identity provider's source IP logic, never accept connections from the entire internet without filtering.
  • Scope the IAM role tightly. Grant the server's role access to only the specific buckets, prefixes, or EFS paths it needs, with no wildcard bucket access.
  • Enable structured logging. Send Transfer Family logs to CloudWatch so you have an audit trail of authentication attempts and file operations.
  • Rotate and audit credentials. Review which users and keys still have access, and remove stale partner accounts on a regular cadence.
  • Encrypt in transit and at rest. Use SFTP or FTPS for transport encryption and make sure the backing S3 bucket or EFS file system has encryption enabled.

A public Transfer Family endpoint is not always wrong, but it is rarely necessary. In most cases a VPC endpoint with security groups and, if needed, Elastic IPs gives you the same partner connectivity with a fraction of the exposure. Fix the servers this check flags, add a guardrail so new ones default to VPC, and keep monitoring so the next public endpoint never lives in your account longer than it takes to notice it.