✓ Human-authored analysis; AI used for formatting and proofreading.
Chris Farris published a post in December 2024 titled "How AWS needs to change." It's complaints about AWS's security culture, ranging from inconsistent IAM action naming to the lack of free security telemetry. It's informed and comes from an experienced cloud security professional's work at the coalface.
Every practitioner complaint describes a configuration state the customer can observe is a specification waiting to be written.
Farris has thirteen complaints. Seven require AWS to change — pricing decisions, API design, release culture. Those are advocacy, which is valuable. But a customer can't verify whether AWS has acted on it. The other six describe configuration states that exist in the customer's own environment and can be checked from a snapshot today. Those aren't complaints. Those are invariants.
The transformation
An invariant is a property that must always be true. When a practitioner says "AWS shouldn't let customers do X," the invariant is: "X is not true in my environment." When they say "AWS should enable Y by default," the invariant is: "Y is enabled." The complaint names the property. The invariant states it. The control checks it.
The transformation is mechanical: take the complaint, strip the "AWS should," replace it with "my environment does," and you have a verifiable property. The question is whether the verification can be done from configuration data you already have.
Walk through six of Farris's thirteen and watch the transformation happen.
1. Not all features are for all customers
Farris references kms:ImportKeyMaterial as an example of a feature most customers shouldn't have access. He links to his ransomware research showing that an attacker who can import external key material into KMS can encrypt your data with a key only they control. The data is not recoverable without the attacker's key material. AWS makes this action available to every account by default.
The complaint: AWS should restrict dangerous actions by default.
The invariant: kms:ImportKeyMaterial is denied by SCP at the organization root.
This is a single predicate evaluated against a single document. Does any SCP in the hierarchy contain an explicit Deny for this action? The answer is yes or no. The consequence of "no" has a documented precedent with a dollar figure.
The same transformation applies to every action Farris lists: organizations:LeaveOrganization (an attacker escapes all organizational controls in one API call), account:CloseAccount (destructive and irreversible), iam:CreateUser (permanent credentials in a world that should use session-based roles). Each one is a complaint about AWS's defaults. Each one is a verifiable invariant about your own SCP coverage.
2. Security services should be a promise
Farris documents that AWS launched the Stockholm region (eu-north-1) in December 2018 without GuardDuty. GuardDuty became available 95 days later. During those 95 days, any customer who deployed to that region had no managed threat detection.
The complaint: AWS shouldn't launch regions without security services.
The invariant: every region with active resources has a GuardDuty detector enabled.
This requires two facts from a configuration snapshot: the set of regions where resources exist, and the set of regions where GuardDuty detectors are active. The gap between those two sets is the blind spot. The customer can't control when AWS adds GuardDuty to a region. But they can verify that they haven't deployed resources to a region without it.
The same pattern applies to CloudTrail. Farris's point #12 says all IAM actions must be logged. The invariant: no CloudTrail trail has exclusion selectors filtering management events, and every active region is covered by at least one trail. These are configuration properties. They're observable from a snapshot. Their violation creates a logging blind spot that an attacker can exploit.
3. Secure defaults are critical
Farris notes that the EC2 Launch Wizard defaults to 0.0.0.0/0 for security group ingress. Every cloud security tool checks for open security groups. That's the obvious invariant and it's been in every scanner since 2015.
The less obvious invariant came from a different announcement in the same month: VPC Block Public Access. AWS shipped a declarative control that prevents resources in public subnets from receiving internet traffic and restricts outbound to specific NAT gateways. The invariant isn't "no open security groups." The invariant is: VPC Block Public Access is enabled at the account level, the mode is bidirectional, and any exclusions are scoped to specific subnets rather than entire VPCs.
That's a three-part predicate, and each part catches a different failure mode. Account-level enablement is the baseline. Bidirectional mode prevents data exfiltration via egress (ingress-only BPA still allows outbound). Subnet-scoped exclusions prevent a VPC-level exception from defeating the entire control.
There's a fourth invariant hiding behind BPA: is it enforced via a declarative policy at the organizational level, or just set per-account? Per-account settings can be changed by any account administrator. Organizational declarative policies can't. The invariant is: a declarative policy enforces VPC BPA organization-wide.
4. Stop hiding behind Shared Responsibility
Farris's most pointed critique is about IMDSv2 and the Capital One breach. AWS knew IMDSv1 was exploitable. They shipped IMDSv2 as an opt-in. Capital One didn't opt in. 100 million records were exfiltrated.
The invariant exists and has existed since 2019: every EC2 instance requires IMDSv2. Every scanner checks it. But the invariant alone isn't the interesting thing. What's interesting is what happens when you combine it with other invariants that weren't being checked.
The Capital One breach required three conditions: IMDSv1 enabled, public IP on the instance, and an IAM role with permissions reaching sensitive data. Each condition is an invariant violation. The compound finding — all three true simultaneously is a named incident shape. Checking whether two of the three are true while one is holding is a distance-one finding: you are one configuration change away from the exact pattern that cost $300 million.
This is where individual invariants become compound invariants, and where the transformation from complaint to specification gets its leverage. Farris's complaint about Shared Responsibility is about one invariant violation (IMDSv1). The compound finding is about three invariant violations intersecting. The distance-one finding is about two violations plus one gate. Each layer requires the previous one to exist.
5. Customers don't know how their cloud works
Farris asks AWS for Audit-Allow and Audit-Deny IAM effects. The ability to see what an SCP would do before applying it in production. He shouldn't need Splunk or Chronicle to figure out whether a new SCP will break his company.
AWS hasn't built it. But the invariant underneath Farris's request is built. Before applying an organizational policy, the customer knows which currently-permitted actions it would deny.
That's a satisfiability problem. Given a proposed SCP deny statement, and the set of IAM policies in the organization, which currently-permitted actions would become denied? You translate the SCP into a formal representation, translate the IAM policies into the same representation, and compute the intersection. The answer is the set of actions that the SCP would break.
This is a what-if analysis. But it's derived from the same transformation: Farris states a need ("I need to know what this SCP would do"), and the specification is the formal property that answers it. The fact that AWS hasn't built the feature doesn't mean the analysis is impossible. It means the customer needs a tool that can reason about policy interactions formally rather than waiting for AWS to add a button.
6. The false positive that erodes trust
The most subtle invariant in Farris's posts isn't stated as a complaint. It's a parenthetical in his discussion of centralized root management: "We just need the CSPM community to catch up and not report missing MFA on accounts without credentials."
AWS shipped centralized root access management in November 2024. It removes root credentials from member accounts entirely, replacing them with sts:AssumeRoot from the management account. When this feature is enabled, member accounts have no root user, no root password, no root access keys. Flagging "missing root MFA" on these accounts is a false positive.
Every CSPM tool on the market generates this false positive today. The invariant isn't "root user has MFA configured." The invariant is: "root user has MFA configured OR centralized root management is enabled for this account." The existing check is incomplete. The false positive erodes trust in the tool, which means that when the tool flags something real, the operator is more likely to ignore it.
This is the inverse of the SILENT_RISK pattern. SILENT_RISK is a false negative: the control passes because the data to detect the violation was missing. This is a false positive: the control fails because the data to recognize the exemption is missing. Both are failures of context. Both corrode signal quality. Both are fixed by the same discipline: write the predicate to account for the full condition, not just the obvious one.
The pattern
Every one of these transformations followed the same steps:
The practitioner states a complaint about how cloud security should work. Inside the complaint is a property that must always be true. The property can be expressed as a predicate over configuration data. The predicate can be evaluated against a snapshot.
The practitioner's value is naming the property. The engineering value is making it checkable. Neither is sufficient without the other. Farris's 95-day GuardDuty gap in Stockholm is meaningless as an invariant if nobody writes the predicate. The predicate is meaningless without the domain knowledge to know that GuardDuty's absence in an active region is a problem.
This is why the best security control catalogs are derived from practitioner complaints, not from compliance frameworks. Compliance frameworks tell you what categories to care about. Practitioners tell you what specific configuration states cause incidents. The framework says "enable logging." The practitioner says "CloudTrail exclusion selectors filtering IAM actions will get you breached." The first is a checkbox. The second is an invariant.
Converting Complaints to Invariants
Next time you read a cloud security post that says "AWS should" or "customers need to" or "this is a failure of Shared Responsibility," try the transformation:
Strip the "should." State the property. Check whether it's observable from a configuration snapshot. If it is, you have an invariant. Write it down. Make it checkable. If the post names an incident, connect the invariant to the incident shape, because that connection turns a compliance checkbox into a risk forecast.
The best invariants are hiding in the complaints of practitioners who have seen enough incidents to know what goes wrong. They just haven't been written as specifications yet.
Every rant is an unwritten invariant. Write it down.
Top comments (0)