{"id":"s3-connect-and-list-buckets","version":"1.0.0","primitive":"code_execution","description":"AWS region","registry_refs":["boto3"],"tags":[],"solves":[],"auth_required":true,"verified":false,"last_verified":"null","next_check":"2026-07-30","eval_result":"null","eval_env":"null","mast":[],"ref":"https://arxiv.org/abs/2503.13657","inputs":[{"name":"AWS_ACCESS_KEY_ID","required":true,"description":"AWS access key ID"},{"name":"AWS_SECRET_ACCESS_KEY","required":true,"description":"AWS secret access key"},{"name":"AWS_REGION","default":"us-east-1","required":false,"description":"AWS region"}],"executable":"# ============================================\n# checklist:     s3-connect-and-list-buckets\n# version:       1.0.0\n# primitive:     code_execution\n# description:   Connect to AWS S3 and list buckets, verify credentials, and surface the exact error if authentication fails\n# registry_refs: boto3\n# auth_required: true\n# verified:      false\n# last_verified: null\n# next_check:    2026-07-30\n# eval_result:   null\n# eval_env:      null\n#\n# inputs:\n#   - name: AWS_ACCESS_KEY_ID\n#     required: true\n#     description: AWS access key ID\n#   - name: AWS_SECRET_ACCESS_KEY\n#     required: true\n#     description: AWS secret access key\n#   - name: AWS_REGION\n#     required: false\n#     default: \"us-east-1\"\n#     description: AWS region\n#\n# OUTPUTS:\n#   connected     — true if credentials are valid\n#   bucket_count  — number of buckets accessible\n#   buckets       — list of bucket names\n#   error         — exact error message if connection failed\n#\n# MAST FAILURE MODES ADDRESSED:\n# FM-2.4 Information Withholding           — exact error surfaced, not swallowed\n# FM-3.2 No or Incomplete Verification     — bucket count verified after connect\n# FM-3.3 Incorrect Verification            — ClientError caught and classified\n#\n# ref: https://arxiv.org/abs/2503.13657\n# ============================================\n\nimport sys\nimport os\nimport subprocess\nimport time\nimport urllib.request\nimport json\n\n# ─────────────────────────────────────────\n# PRE_EXECUTION\n# ─────────────────────────────────────────\n\nfor attempt in range(2):\n    try:\n        req = urllib.request.Request(\n            \"https://checklist.day/api/registry/boto3\",\n            headers={\"User-Agent\": \"checklist-agent/1.0\"}\n        )\n        with urllib.request.urlopen(req, timeout=10) as resp:\n            registry = json.loads(resp.read())\n            break\n    except Exception as e:\n        if attempt == 1:\n            print(f\"ABORT: registry unreachable — {e}\")\n            sys.exit(1)\n        time.sleep(2)\n\nwarnings = registry.get(\"warnings\", [])\nif warnings:\n    print(\"[boto3] WARNINGS:\")\n    for w in warnings if isinstance(warnings, list) else [warnings]:\n        print(f\"  ⚠ {w}\")\n\n# ─────────────────────────────────────────\n# EXECUTION\n# ─────────────────────────────────────────\n\nsubprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"-q\", \"boto3>=1.26.0\"])\n\nimport boto3\nfrom botocore.exceptions import ClientError, NoCredentialsError\n\nAWS_ACCESS_KEY_ID     = os.environ.get(\"AWS_ACCESS_KEY_ID\")\nAWS_SECRET_ACCESS_KEY = os.environ.get(\"AWS_SECRET_ACCESS_KEY\")\nAWS_REGION            = os.environ.get(\"AWS_REGION\", \"us-east-1\")\n\nif not AWS_ACCESS_KEY_ID:\n    print(\"ABORT: AWS_ACCESS_KEY_ID env var not set\")\n    sys.exit(1)\nif not AWS_SECRET_ACCESS_KEY:\n    print(\"ABORT: AWS_SECRET_ACCESS_KEY env var not set\")\n    sys.exit(1)\n\nconnected    = False\nbucket_count = 0\nbuckets      = []\nerror        = None\n\ntry:\n    # FOOTGUN: always pass credentials explicitly — don't rely on ~/.aws/credentials in agents\n    client = boto3.client(\n        \"s3\",\n        aws_access_key_id=AWS_ACCESS_KEY_ID,\n        aws_secret_access_key=AWS_SECRET_ACCESS_KEY,\n        region_name=AWS_REGION,\n    )\n\n    response     = client.list_buckets()\n    buckets      = [b[\"Name\"] for b in response.get(\"Buckets\", [])]\n    bucket_count = len(buckets)\n    connected    = True\n    print(f\"  connected — {bucket_count} bucket(s) accessible\")\n    for b in buckets[:5]:\n        print(f\"    - {b}\")\n    if bucket_count > 5:\n        print(f\"    ... and {bucket_count - 5} more\")\n\nexcept NoCredentialsError as e:\n    error = f\"NoCredentialsError: {e}\"\n    print(f\"  auth failed: {error}\")\nexcept ClientError as e:\n    error = f\"{e.response['Error']['Code']}: {e.response['Error']['Message']}\"\n    print(f\"  client error: {error}\")\n\n# ─────────────────────────────────────────\n# POST_EXECUTION\n# ─────────────────────────────────────────\n\nresult = {\n    \"connected\":    connected,\n    \"bucket_count\": bucket_count,\n    \"buckets\":      buckets[:10],\n    \"error\":        error,\n}\nprint(json.dumps(result, indent=2))\n\nif not connected:\n    print(f\"FAIL: {error}\")\n    sys.exit(1)\n\nassert connected, \"FAIL: not connected\"\nprint(\"PASS\")\n"}