Skip to main content

No External Write Access

ID: CTL.S3.ACCESS.003 Category: Access Control Severity: Critical

What This Checks​

S3 buckets must not grant write or delete permissions to external AWS accounts. While cross-account read access may be acceptable for analytics or auditing, write access from external accounts creates data integrity and supply chain risks.

Why It Matters​

External write access is the highest-severity form of cross-account oversharing. An external account with s3:PutObject on acme-firmware-releases can inject tampered artifacts into your build pipeline. An external account with s3:DeleteObject can destroy audit logs or backups. An external account with s3:PutBucketPolicy can grant itself additional permissions, escalating a scoped grant into full bucket takeover. These are not theoretical risks -- supply chain attacks via writable S3 buckets have been documented in public breach disclosures.

What A Violation Looks Like​

$ stave apply --controls controls/s3 --observations ./observations --max-unsafe 0s --eval-time 2026-01-15T00:00:00Z
{
"control_id": "CTL.S3.ACCESS.003",
"control_name": "No External Write Access",
"resource_id": "acme-firmware-releases",
"resource_type": "aws_s3_bucket",
"resource_vendor": "aws",
"evidence": {
"matched_properties": [
{
"path": "properties.storage.access.has_external_write",
"value": true
},
{
"path": "properties.storage.kind",
"value": "bucket"
}
],
"first_unsafe_at": "2026-01-05T00:00:00Z",
"last_seen_unsafe_at": "2026-01-15T00:00:00Z",
"unsafe_duration_hours": 240,
"threshold_hours": 0,
"why_now": "Resource has been unsafe for 240 hours (threshold: 0 hours). Unsafe since 2026-01-05T00:00:00Z."
},
"mitigation": {
"description": "Control violation detected.",
"action": "Review the unsafe configuration and remediate."
}
}

Correct Configuration​

A safe bucket does not grant write or delete actions to external accounts:

{
"storage": {
"kind": "bucket",
"access": {
"has_external_write": false
}
}
}

To remediate: Remove bucket policy statements granting s3:PutObject, s3:DeleteObject, or s3:PutBucketPolicy to external accounts. If cross-account write is genuinely required, restrict to specific account IDs with condition keys such as aws:PrincipalOrgID and scope the grant to a narrow resource prefix.

  • CTL.S3.ACCESS.001 -- No Unauthorized Cross-Account Access (flags any cross-account access, including read)
  • CTL.S3.WRITE.SCOPE.001 -- S3 Signed Upload Must Bind To Exact Object Key (flags overly broad write scope in signed upload policies)
  • CTL.S3.TENANT.ISOLATION.001 -- Shared-Bucket Tenant Isolation Must Enforce Prefix (flags missing prefix enforcement on shared buckets)