AntFleet

Disagreement · 4c349ef3-anthropic-6

`bucket.grant_read(fn)` grants Lambda read on the entire bucket while only `dashboard/*` is public — fine, but `grant_put` scoped only to `dashboard/*` means feedback.csv writes will be denied

mismatch
repo 703f69ec·PR #3·reviewed 5 days ago

Primary finding

`bucket.grant_read(fn)` grants Lambda read on the entire bucket while only `dashboard/*` is public — fine, but `grant_put` scoped only to `dashboard/*` means feedback.csv writes will be denied

highbugmedium
  • infra/stack.py:138-141
  • infra/stack.py:101-102
The Lambda env declares `S3_FEEDBACK_KEY=geo-signals/feedback.csv`, implying the agent writes feedback CSV under the `geo-signals/` prefix. However, `grant_put` is scoped only to `dashboard/*`, so any `PutObject` to `geo-signals/feedback.csv` will be denied with AccessDenied at runtime. Unless the feedback file is only ever read (never written) by Lambda, this is a runtime authorization bug.

Recommendation

If Lambda writes feedback, add `bucket.grant_put(fn, "geo-signals/*")` (or use `grant_read_write` scoped appropriately). If Lambda only reads feedback, document that and remove the misleading env var implication.

Counterpart finding

Lambda granted read access to entire bucket (over-privileged)

mediumsecurityhigh
  • infra/stack.py:99-101
  • infra/stack.py:131-133
The function appears to only need to read geo-signals/feedback.csv and write to dashboard/*, yet it is granted read on the whole bucket (and likely ListBucket). Over-broad permissions increase blast radius if the function is compromised.

Recommendation

Replace bucket.grant_read(fn) with bucket.grant_read(fn, "geo-signals/feedback.csv") (or a tighter prefix) and, if ListBucket is required, scope it with a condition on s3:prefix to the used keys. Keep bucket.grant_put(fn, "dashboard/*") as-is.

Why this didn't post

This finding didn't meet AntFleet's unanimous agreement threshold. Both frontier models review every PR independently; only findings they both flag with the same severity and category are posted to the PR. This one fell through.

read the methodology →