ekofyi
Security Research6 min read

Terrascan's SSRF Flaw Lets Attackers Pivot Through Your Policy Scanner

CVE-2026-47357 exposes a high-severity SSRF in Terrascan's remote scan API endpoint, letting attackers reach internal services through your IaC policy scanner. Here's how it works and what to do.

Your Policy Scanner Just Became an Attack Proxy

If you're running Terrascan as a service — which plenty of teams do for centralized IaC policy scanning — you need to stop what you're doing and check your version. Published on May 19, 2026, CVE-2026-47357 is a high-severity Server-Side Request Forgery (SSRF) vulnerability that turns your security tool into an open proxy for attackers to reach your internal network.

The irony here is thick. The tool you deployed to enforce security policies on your infrastructure code can now be weaponized to bypass network boundaries. SSRF in a security scanner is particularly nasty because these tools often run with elevated network access — they need to reach your repos, your registries, your cloud APIs. That's exactly the kind of access an attacker wants.

What Happened

Terrascan versions v1.18.3 and prior contain an SSRF vulnerability in the remote directory scan endpoint. The specific vector is the remote_url parameter in the API endpoint:

http
POST /v1/{iac}/{iacVersion}/{cloud}/remote/dir/scan

The CVSS score is 7.5 (HIGH), which reflects the fact that this is exploitable over the network without authentication and can compromise confidentiality of internal services. The attack complexity is low — no special conditions needed, no user interaction required.

The root cause is straightforward: Terrascan's server mode accepts a user-supplied URL for remote repository scanning and doesn't properly validate or restrict where that URL can point. Instead of limiting requests to legitimate Git hosting services or external repositories, it follows whatever URL you hand it — including http://169.254.169.254, http://localhost:6379, or any other internal endpoint you want to probe.

This is a textbook SSRF. The application makes server-side HTTP requests on behalf of the user without adequate input validation on the destination.

Technical Deep-Dive

Let me walk through how this works. When you run Terrascan in server mode, it exposes a REST API for scanning IaC files. One of those endpoints lets you point it at a remote repository URL so it can clone/download the code and scan it. The intended use case is something like:

bash
curl -X POST "http://terrascan-server:9010/v1/terraform/v14/aws/remote/dir/scan" \
  -H "Content-Type: application/json" \
  -d '{"remote_url": "https://github.com/your-org/your-infra-repo.git", "remote_type": "git"}'

That's the happy path. Now here's the exploit scenario. An attacker who can reach the Terrascan API (which might be exposed internally, or worse, publicly) sends:

bash
curl -X POST "http://terrascan-server:9010/v1/terraform/v14/aws/remote/dir/scan" \
  -H "Content-Type: application/json" \
  -d '{"remote_url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/", "remote_type": "git"}'

The Terrascan server dutifully makes a request to the AWS metadata service from its own network context. Depending on how the error handling works, the attacker might get the response body back directly in an error message, or they can infer information from timing and response codes.

The vulnerable pattern in the code likely looks something like this (simplified):

go
func handleRemoteScan(w http.ResponseWriter, r *http.Request) {
    var req ScanRequest
    json.NewDecoder(r.Body).Decode(&req)
    
    // No validation on remote_url — this is the problem
    resp, err := http.Get(req.RemoteURL)
    if err != nil {
        // Error might leak response details
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    // Process the downloaded content...
}

The missing piece is URL validation. There's no check for private IP ranges, no allowlist of permitted schemes or hosts, no DNS rebinding protection. The server just follows wherever the URL points.

This is especially dangerous in cloud environments. If Terrascan runs on an EC2 instance, ECS task, or GKE pod, the attacker can hit the cloud metadata endpoint to steal IAM credentials. If it runs in a Kubernetes cluster, they can probe the Kubernetes API, etcd, or other internal services. The blast radius depends entirely on what network access the Terrascan process has — and security tools typically have a lot.

Impact Analysis

Who's affected? Anyone running Terrascan in server mode (the terrascan server command) on versions v1.18.3 or earlier. If you only use Terrascan as a CLI tool in CI pipelines without the HTTP server, you're not directly exposed to this specific vector.

But here's the thing — the server mode is the recommended deployment for organizations that want centralized policy scanning. It's what you'd use in a platform engineering setup where multiple teams submit scans through an API. These deployments tend to sit inside the network perimeter with broad access to internal services, making the SSRF particularly valuable to an attacker.

The real-world implications include: stealing cloud credentials from metadata services, scanning internal networks for services, accessing internal APIs that trust requests from the Terrascan host, and potentially reading sensitive data from internal services that don't require authentication.

What To Do About It Right Now

First, check your Terrascan version:

bash
terrascan version

If you're on v1.18.3 or earlier and running in server mode, you need to act immediately. Upgrade to the patched version (check the Terrascan releases page for the fix — it should be v1.18.4 or later).

If you can't upgrade immediately, apply network-level mitigations:

yaml
# Example: Kubernetes NetworkPolicy to restrict Terrascan egress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: terrascan-egress-restrict
spec:
  podSelector:
    matchLabels:
      app: terrascan
  policyTypes:
    - Egress
  egress:
    - to:
        - ipBlock:
            cidr: 0.0.0.0/0
            except:
              - 169.254.169.254/32  # Block metadata service
              - 10.0.0.0/8          # Block internal RFC1918
              - 172.16.0.0/12
              - 192.168.0.0/16
      ports:
        - protocol: TCP
          port: 443

Also, if you're running on AWS, make sure you've migrated to IMDSv2 with hop limit set to 1. This won't prevent the SSRF, but it prevents the metadata credential theft scenario since IMDSv2 requires a PUT request with a token that SSRF through a GET-based fetch can't easily replicate:

bash
aws ec2 modify-instance-metadata-options \
  --instance-id i-1234567890abcdef0 \
  --http-tokens required \
  --http-put-response-hop-limit 1

Tip: Audit your Terrascan server access logs for any requests with remote_url values pointing to internal IPs, localhost, 169.254.x.x, or non-standard schemes. If you find any, assume compromise and rotate credentials on that host.

The Bigger Picture

This is a pattern I keep seeing: security tools themselves becoming the vulnerability. Scanners, SIEM agents, policy engines — they all need broad network access and elevated permissions to do their jobs. That makes them high-value targets. When you deploy a security tool, you need to threat-model the tool itself with the same rigor you'd apply to any other service.

SSRF is a solved problem in terms of knowing how to prevent it — URL validation, allowlists, egress filtering, metadata service hardening. The fact that it keeps showing up in 2026, in security-focused tooling no less, tells me we're still not treating internal services with the zero-trust mindset we preach. Every service that makes outbound requests on behalf of user input is an SSRF candidate. Audit yours.

Related posts

Written by Eko

If you found this useful, follow @ekofyi on X for more notes like this — or get in touch if you have a problem to solve.