Data Perimeter
A data perimeter is the set of guardrails that keep your data reachable only by trusted identities, from expected networks, to trusted resources (AWS data perimeter whitepaper). cloud-audit's data perimeter checks read your resource-based policies and flag the boundary failures you can detect from a single account, read-only, without AWS Organizations access.
cloud-audit scan --categories security # data perimeter runs as part of a normal scan
cloud-audit list-checks # see all aws-dp-* checks
Why this matters
Most scanners evaluate a resource policy as raw API output and never look at the condition keys that AWS recommends for the data perimeter. That produces two problems: blind spots (a wildcard grant that should be flagged isn't analyzed in context) and false positives (a grant that is scoped by aws:PrincipalOrgID gets flagged anyway). The dominant open-source scanner tracks this as an open feature request - Prowler issue #7114, "Integrating SCP/RCP Policy Awareness", open since March 2025.
cloud-audit reads the condition keys directly and reports the absence of a guardrail without guessing about organization-level policy.
What it detects
| Dimension | Trigger | Severity |
|---|---|---|
| Confused deputy | An Allow statement grants an AWS service principal without aws:SourceAccount / aws:SourceArn / aws:SourceOrgID / aws:SourceOwner |
MEDIUM |
| Cross-org exposure (wildcard) | An Allow statement grants Principal: "*" (any AWS account) without an organization-boundary condition |
HIGH |
| Cross-org exposure (external account) | An Allow statement grants a named external account without an organization-boundary condition |
LOW |
The confused deputy problem is when a service acting on behalf of another account is coerced into operating on your resource. AWS recommends aws:SourceArn, aws:SourceAccount, aws:SourceOrgID, or aws:SourceOrgPaths "wherever an AWS service principal is granted permission to access one of your resources."
A grant is treated as scoped (no finding) when it carries any organization or account binding: aws:PrincipalOrgID, aws:PrincipalOrgPaths, aws:ResourceOrgID, aws:SourceOrgID, aws:SourceOrgPaths, aws:SourceAccount, aws:SourceOwner, aws:PrincipalAccount, or aws:SourceArn. Condition key names are matched case-insensitively, and the default SNS/SQS policies that rely on aws:SourceOwner are correctly recognized as account-scoped.
Checks
| Check | Service | Resource policy |
|---|---|---|
aws-dp-001 |
S3 | bucket policy |
aws-dp-002 |
SNS | topic policy |
aws-dp-003 |
SQS | queue policy |
aws-dp-004 |
Secrets Manager | secret resource policy (cross-org escalated: CRITICAL wildcard / MEDIUM external) |
aws-dp-005 |
Lambda | function resource policy |
aws-dp-001 complements aws-s3-001 (public access block): PAB governs anonymous public access, while aws-dp-001 governs the organization boundary and confused-deputy posture of the bucket policy itself.
Every finding ships copy-paste CLI + Terraform remediation and a breach-cost estimate.
Remediation example
A bucket policy that lets CloudTrail write logs without scoping the source is a confused deputy:
{
"Effect": "Allow",
"Principal": { "Service": "cloudtrail.amazonaws.com" },
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-logs/*"
}
Add a source condition so the service can only act for your account:
Scope and limitations
- In scope: resource-based policies readable by any account-local principal (S3, SNS, SQS, Secrets Manager, Lambda).
- Out of scope: SCP/RCP enforcement, which lives at the AWS Organizations level and requires management-account access. These checks report the absence of a resource-level guardrail; they do not assume an org-wide RCP closes the gap.
- Condition values are evaluated, not just key presence: a guardrail (
aws:SourceAccount/aws:SourceOwner/aws:PrincipalAccount/aws:SourceArn) scoped to a foreign account is still flagged. Organization keys (aws:PrincipalOrgID, ...) are treated as a guardrail when present, since the org id is not locally verifiable without AWS Organizations access (documented trade-off favoring zero false positives). - Federated provider ARNs in a foreign account are flagged as external grants. Federated URL IdPs (e.g.
accounts.google.com) andCanonicalUserprincipals are not account-parseable and are out of scope. NotPrincipalstatements are not analyzed (uncommon; treated as a known limitation rather than guessed at).- Scoping is heuristic, not a full IAM policy evaluation (operator semantics and per-request key presence are not simulated) - a deliberate choice to avoid the maintenance trap that killed PMapper.
- A condition key under an
...IfExistsoperator is counted as present. This favors fewer false positives; verify intent on highly sensitive resources.
The detection taxonomy follows the AWS data perimeter whitepaper and AWS cross-service confused deputy prevention guidance.