What data does CostSave access, collect, and store?
A complete, honest breakdown — every API call across AWS, Cloudflare, and Google Cloud, every database column, every encryption detail. No marketing language. Just facts.
Amazon Web Services (AWS)
How CostSave connects to your AWS account
When you click "Connect AWS Account", CostSave uses a CloudFormation template to create a cross-account IAM Role with read-only permissions in your AWS account. CostSave then calls sts:AssumeRole with an External ID unique to your account to get temporary credentials that auto-expire. No long-lived Access Keys are stored on our servers.
The one-click CloudFormation template creates a cross-account IAM Role. CostSave stores only the Role ARN and External ID — not secret keys. Temporary credentials are fetched on demand and never persisted.
To revoke access instantly: delete the CloudFormation stack from your AWS Console. CostSave immediately loses all access.
Exact AWS API calls made during a scan
Every call below is read-only — Describe*, List*, Get*. There is no Create*, Delete*, Modify*, or Put* call anywhere in our codebase.
ec2:DescribeInstancesec2:DescribeVolumesec2:DescribeAddressesec2:DescribeSnapshotsec2:DescribeNatGatewaysec2:DescribeNetworkInterfacesec2:DescribeVpcEndpointsec2:DescribeVpnConnectionsrds:DescribeDBInstancesrds:DescribeDBSnapshotss3:ListBucketss3:GetBucketLocations3:GetBucketVersionings3:GetBucketLifecycleConfigurationelasticloadbalancing:DescribeLoadBalancerselasticloadbalancing:DescribeTargetGroupselasticloadbalancing:DescribeTargetHealthlambda:ListFunctionscloudfront:ListDistributionsecs:ListClustersecs:DescribeClustersecs:ListServicesecs:DescribeServiceseks:ListClusterseks:DescribeClustereks:ListNodegroupseks:DescribeNodegroupsqs:ListQueuessqs:GetQueueAttributeselasticfilesystem:DescribeFileSystemswafv2:ListWebACLsguardduty:ListDetectorsguardduty:GetDetectorguardduty:ListFindingscloudwatch:GetMetricStatisticslogs:DescribeLogGroupsce:GetCostAndUsagece:GetCostForecastce:GetAnomaliesce:GetSavingsPlansCoveragece:GetSavingsPlansUtilizationce:GetSavingsPlansRecommendationscompute-optimizer:GetEC2InstanceRecommendationscompute-optimizer:GetEBSVolumeRecommendationscompute-optimizer:GetLambdaFunctionRecommendationssts:GetCallerIdentitysts:AssumeRoleWhat we never access on AWS
We call ListBuckets and check bucket configuration only. We never call GetObject on your data buckets. Your files are never read.
We call DescribeDBInstances for metadata only. We have no database credentials and cannot connect to your databases.
We call ListFunctions for names, runtimes, and memory settings only. We never call GetFunction which returns the code package.
Zero calls to secretsmanager:* or ssm:GetParameter*. Your secrets are never touched.
We read instance metadata (type, state, CPU). We never call DescribeInstanceAttribute which returns user data scripts.
Zero calls to iam:*. We don't enumerate your users, roles, or permissions.
Minimum AWS IAM policy required
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CostSaveReadOnly",
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"rds:Describe*",
"s3:ListBuckets",
"s3:GetBucketLocation",
"s3:GetBucketVersioning",
"s3:GetBucketLifecycleConfiguration",
"elasticloadbalancing:Describe*",
"lambda:ListFunctions",
"cloudfront:ListDistributions",
"ecs:List*", "ecs:Describe*",
"eks:List*", "eks:Describe*",
"sqs:ListQueues",
"sqs:GetQueueAttributes",
"elasticfilesystem:DescribeFileSystems",
"wafv2:ListWebACLs",
"guardduty:ListDetectors",
"guardduty:GetDetector",
"guardduty:ListFindings",
"cloudwatch:GetMetricStatistics",
"logs:DescribeLogGroups",
"ce:GetCostAndUsage",
"ce:GetCostForecast",
"ce:GetAnomalies",
"ce:GetSavingsPlans*",
"compute-optimizer:Get*",
"sts:GetCallerIdentity"
],
"Resource": "*"
}
]
}Cloudflare
How CostSave connects to your Cloudflare account
You provide a read-only API token from your Cloudflare dashboard. CostSave never requests write permissions. The token is encrypted with AES-256-GCM before being stored — the same encryption used for AWS credentials.
The token needs Account Analytics:Read and Account Settings:Read permissions. No zone-level write permissions are ever requested.
To revoke access: delete the API token from Cloudflare Dashboard → My Profile → API Tokens. CostSave immediately loses all access.
Exact Cloudflare API calls made during a scan
All calls are GET requests to the Cloudflare REST API and GraphQL Analytics API. No POST, PUT, PATCH, or DELETE calls are made.
GET /accountsGET /zonesGET /zones/:id/dns_recordsDNS record names, types, content — not zone file secretsGET /accounts/:id/workers/scriptsReturns script names and metadata only — no source codePOST /graphql (workersInvocationsAdaptive)Request counts per worker — no request contents or payloadsGET /accounts/:id/r2/bucketsBucket names and object counts only — no file contentsGET /accounts/:id/storage/kv/namespacesNamespace names and metadata only — no key names or valuesGET /accounts/:id/d1/databaseDatabase names and sizes only — no table contents or schemaGET /accounts/:id/pages/projectsProject names, last deployment date — no build artifactsGET /accounts/:id/cfd_tunnelTunnel names and status — no tunnel credentials or configGET /accounts/:id/queuesQueue names and message counts — no message contentsGET /accounts/:id/load_balancers/poolsGET /zones/:id/load_balancersLoad balancer status and origin pool counts onlyPOST /graphql (httpRequests1dGroups)POST /graphql (r2StorageAdaptiveGroups)POST /graphql (queuesAdaptiveGroups)Aggregate counts only — no individual request detailsWhat we never access on Cloudflare
We list worker script names and fetch invocation counts. We never call the script download endpoint. Your Worker code stays in Cloudflare.
We count objects per bucket and fetch request metrics. We never call GetObject. Your files are never read.
We list namespace names and fetch operation counts. We never enumerate keys or read values.
We read database name and size. We never execute any SQL query against your D1 databases.
Zero calls to the Worker secrets API. Your environment variables and secrets are never touched.
Analytics calls return aggregate counts (total requests per day). We never access individual request logs, IPs, or user data.
Google Cloud Platform (GCP)
How CostSave connects to your GCP account
You provide a Service Account key (JSON) with read-only IAM roles. CostSave uses this key to authenticate with Google APIs. The key is encrypted with AES-256-GCM before being stored — exactly the same encryption used for other platforms.
The service account needs these roles at the Organization or Folder level (read-only):
roles/viewer— basic read access to all resourcesroles/billing.viewer— access to billing dataroles/monitoring.viewer— access to Cloud Monitoring metrics
To revoke access: delete or disable the service account from Google Cloud Console → IAM & Admin → Service Accounts. CostSave immediately loses all access.
Exact GCP API calls made during a scan
All calls are read-only GET / list operations on Google APIs. No write, update, create, or delete operations are ever made.
cloudresourcemanager.projects.listLists active projects accessible to the service accountcompute.instances.aggregatedListcompute.disks.aggregatedListcompute.addresses.aggregatedListcompute.snapshots.listVM names, types, statuses — no disk contents or VM datamonitoring.timeSeries.list (compute.googleapis.com/instance/cpu/utilization)monitoring.timeSeries.list (cloudsql.googleapis.com/database/network/connections)Aggregate CPU / connection metrics only — no application datasqladmin.instances.listInstance names, tiers, and statuses — no database contents or credentialsstorage.buckets.listBucket names, locations, and IAM policies — no object contentscontainer.clusters.listCluster names, node counts, and node pool types — no workload datacloudfunctions.functions.listFunction names, runtimes, and memory settings — no source codecloudbilling.billingAccounts.listmonitoring.timeSeries.list (billing.googleapis.com/billing/monthly_cost)Per-project monthly cost totals onlyWhat we never access on GCP
We list bucket names and check IAM policies. We never call storage.objects.get. Your files are never read.
We list instance metadata only. We have no database credentials and cannot connect to your Cloud SQL databases.
We list function names, runtimes, and memory settings. We never download source code or environment variables.
We read VM metadata (name, type, zone, CPU metrics). We never read disk images or snapshot contents.
Zero calls to secretmanager.versions.access. Your GCP secrets are never touched.
We list cluster metadata and node counts. We never connect to the Kubernetes API or read pod logs, configs, or secrets.
What we store in our database
| Table | Platform | What's stored | What's NOT stored |
|---|---|---|---|
aws_accounts | AWS | Account label, Role ARN, External ID, AWS Account ID (12-digit) | Secret keys — CloudFormation role uses temporary credentials only |
cf_accounts | Cloudflare | Account label, encrypted API token, CF Account ID | Plaintext token — encrypted with AES-256-GCM before writing |
gcp_accounts | GCP | Account label, encrypted service account JSON, project IDs list | Plaintext service account key — encrypted with AES-256-GCM before writing |
scans / gcp_scans / cf_scans | All | Scan timestamp, resource IDs, resource names, instance types, cost numbers, utilization metrics, recommendation flags | File contents, database data, function code, environment variables, secrets of any kind |
shared_reports | All | Report share token, expiry time (3 days), linked scan ID | — |
How your credentials are encrypted
The same encryption scheme applies to all three platforms — AWS role credentials, Cloudflare API tokens, and GCP service account keys.
AES-256-GCM — authenticated encryption, industry standard