ZERO WRITE PERMISSIONS
Read-only. Always.
Here's the proof.
CostPatrol connects via a CloudFormation-deployed IAM role with zero write permissions. We observe and report. We never modify your infrastructure. Below is every permission we request and why.
Three steps. Zero credentials stored.
You deploy a CloudFormation template
One-click deployment in your AWS account. Creates a read-only IAM role with an external ID unique to your account. No agents, no long-term credentials.
Takes under 2 minutesCostPatrol assumes the role temporarily
1-hour STS session tokens. No stored credentials. External ID prevents confused deputy attacks.
MaxSessionDuration: 3600 secondsWe scan and report. That's it.
Read-only API calls to describe and list resources. Results packaged as savings actions and delivered to Slack.
No state changes. Ever.Every permission we request
These are the exact IAM actions in our CloudFormation template. Nothing more. Nothing hidden.
The Deny is what actually enforces this
The table above is what the role asks for. What stops it doing anything else is a second statement in the same template: an explicit Deny on every action not named Get, Describe, List or BatchGet. An explicit Deny wins in IAM whatever the rest of the policy says, so nothing named Create, Put, Update, Modify or Delete can reach this role, whatever the Allow list asks for.
That is a strong default. It is not a proof, and you should have the limit from us rather than find it yourself. The Deny matches NAMES, and AWS does not name its write actions consistently. glue:GetStorage is a write, and AWS classifies it as permission management too. redshift:GetClusterCredentials mints database credentials. Both are a Get, so a rail built on read verbs would let either one past.
So the proof is not the Deny. AWS publishes a Service Reference that records, for every action in every service, whether that action writes. We keep a dated copy of it in the repo, and a test fails the build if any action this role requests is classified as a write, as permission management, or as tagging. Every action in the table above is clear on all three, against a copy captured on 2026-08-20, which the build re-checks on every change we ship and which we recapture at least every 180 days.
5 of the actions above are reads AWS did not name that way, so that Deny would block them too. The template excepts each one by name, with the reason next to it. This is the whole of the role's reach beyond the read verbs.
-
apigateway:GETAPI Gateway v1 authorizes reads by HTTP verb, not by operation name. IAM matching is case sensitive, so GET is not Get. -
budgets:ViewBudgetThe only read action AWS Budgets defines. There is no budgets:DescribeBudgets. -
cassandra:SelectAmazon Keyspaces authorizes under the cassandra prefix, and Select is its read verb. -
iam:SimulatePrincipalPolicyEvaluates this role's own policy documents so CostPatrol can tell you which checks a missing permission is blocking. It calls none of the services it names. -
logs:StartQueryStarts a CloudWatch Logs Insights query. It reads log data and writes nothing.
What we CANNOT do
The explicit Deny described above blocks every action not named Get, Describe, List or BatchGet, and it beats any Allow. Every action the role does hold is verified non-write against AWS's own Service Reference. The following operations are impossible with our permissions.
- Create, modify, or delete any AWS resource
- Access S3 object contents or log data contents
- Modify IAM roles, policies, or permissions
- Access secrets, parameters, or credentials in your account
- Make any API call that changes state
Data protection
Every layer of our stack is designed with defense in depth. Here is how we protect the data we collect.
Encryption in transit
All traffic encrypted with TLS 1.2+ (TLS 1.3 preferred). No plaintext connections accepted.
Encryption at rest
Data at rest encrypted with AES-256. DynamoDB server-side encryption enabled on all tables.
Multi-tenant isolation
Composite DynamoDB keys ensure strict tenant isolation. No customer can access another customer's data.
Security headers
HSTS headers enforced. CORS restricted to costpatrol.io. Content Security Policy applied.
WAF protection
AWS WAF active with rate limiting, SQL injection, and XSS protection rules.
Short-lived credentials
1-hour STS session tokens only. No long-term AWS credentials stored anywhere in our infrastructure.
Standards and certifications
SOC 2 Type II
Working toward SOC 2 Type II certification covering security, availability, and confidentiality trust service criteria.
GDPR
Data processing agreement available on request. We process only infrastructure metadata, not personal data.
Data retention
Retention is configurable. All data deleted on account disconnection. No data held after offboarding.
Audit logging
All access and operations logged with 2-year retention in immutable storage for forensic analysis.
See exactly what we deploy. Then start your free scan.
Review the CloudFormation template yourself. Every permission is documented above. Read-only access, deployed in your account, under your control.