Surface Scan - baeziy/AWSault GitHub Wiki

Surface Scan

The surface scan is Phase 1 of AWSault. It runs by default (no flags needed) and is the foundation for everything else.

What it does

AWSault fires read-only, parameterless API calls (List, Get, Describe) across 120+ AWS services and records which ones succeed vs. which ones get denied. Think of it as a bulk permission check.

# run a surface scan
awsault

# surface scan with specific services only
awsault --services iam,s3,ec2,lambda

# surface scan across all regions
awsault --all-regions

How it works

Execution flow

  1. Load the service registry — 120+ services, 500+ API calls
  2. Filter to requested services (if --services is used)
  3. Spin up a thread pool (default 10 threads, configurable with --threads)
  4. Fire every API call concurrently
  5. Classify each response as OK, DENIED, or ERROR
  6. Save results to ~/.awsault/last_scan.json
  7. Display summary table

Concurrency

Each API call runs as a separate task in a ThreadPoolExecutor. The default is 10 concurrent threads. Increase for faster scans on high-bandwidth connections:

awsault --threads 20

Pagination

For API calls that support pagination (e.g., list_users can return thousands of users), AWSault uses boto3's built-in paginators. It collects all pages before reporting the total count.

If a paginator isn't available for a given API, it falls back to a direct call.

Error classification

Status What it means Examples
OK Call succeeded, data was returned list_buckets returned 5 buckets
DENIED Permission error — you don't have access AccessDenied, UnauthorizedAccess, ForbiddenException
ERROR Real failure unrelated to permissions Network timeout, invalid region, service not available

Denied error codes (classified as permission issues, not failures):

  • AccessDenied
  • AccessDeniedException
  • UnauthorizedAccess
  • AuthorizationError
  • UnauthorizedOperation
  • ForbiddenException
  • InvalidClientTokenId
  • AuthorizationException

Permissions vs resources

IAM permissions are region-independent. If an API call succeeds in us-east-1, it will succeed in every other region too. What changes across regions is which resources exist (instances, snapshots, buckets, etc.).

The surface scan checks permissions, so it only needs to run once regardless of how many regions you're scanning. The --all-regions flag affects deep enumeration (Phase 2+), which checks each region for actual resources.

When --all-regions is used, AWSault:

  1. Runs the surface scan once to map permissions (since they're the same everywhere)
  2. Runs deep enumeration, security audit, and loot extraction per-region to discover resources
  3. Shows combined findings across all regions at the end

Output

The surface scan produces a table showing each service with:

  • Service name (uppercase)
  • OK count — how many API calls succeeded
  • Denied count — how many were blocked by IAM
  • Error count — how many had non-permission errors
  • Total calls — total API calls attempted

Services with at least one OK call are highlighted — these are your entry points for deeper enumeration. After the scan, AWSault also generates Suggested Next Steps with ready-to-copy AWS CLI commands for every service that returned OK.

Verbose mode

awsault --verbose

With --verbose, AWSault prints the actual API response data for each successful call during the scan. Useful for quick manual inspection without needing --show.

Data persistence

Results are automatically saved to ~/.awsault/last_scan.json. This allows you to:

  • Browse results later with --show (see Browsing Results)
  • Export to different formats with --output (see Output Formats)
  • Skip rescanning when you just want to look at old data

What happens next

If you ran with --godeep, the surface scan results feed into: