API

v1

The whole archive as JSON. No key and no sign-up - these are static files on the same CloudFront distribution that serves the site, regenerated on every deploy. Use them in a script, a dashboard, or a CI check that fails when a policy you depend on changes.

Base URL: https://iamtrail.com/api/v1

Resources

Service index

/api/v1/index.json

Contract version, generation timestamp, archive counts and the URL of every other resource. Start here and follow the links rather than hard-coding paths, so a future v2 can move files without breaking you.

Every tracked AWS managed policy with its ARN, current version, creation and last-modified dates, version count, action count and deprecation date.

Policy detail

/api/v1/policies/{policyName}.json

One policy: its current IAM document plus the full commit history, each entry carrying what that version changed when the change index reaches back that far.

Change timeline

/api/v1/changes.json

The most recent policy changes, newest first, each naming the actions added and removed, any never-before-seen actions or service prefixes, and any permissions management actions gained.

Every literal IAM action seen in a managed policy, mapped to the policies that allow, deny or NotAction it, with the date it was first seen anywhere in the archive. wildcardGrants lists every Allow wildcard such as s3:Get* by service prefix, so you can find the policies that grant an action without naming it.

Service prefixes and actions that appeared for the first time anywhere in the archive, newest first. AWS usually ships the IAM component before the SDK and the docs.

re:Invent seasons

/api/v1/reinvent.json

October 1 through December 31 of each year: new AWS services, never-before-seen actions, new policies, endpoint changes and GuardDuty announcements, plus major What's New posts in whatsNewPosts. A post with timing "before" is pre-re:Invent. Regional rollouts are omitted. whatsNewPosts.available is false when that feed could not be loaded. editions[0] is the newest season.

Risk assessment

/api/v1/risk.json

Every policy that carries a risk signal, with its level (critical, high or medium), its signals and the pathfinding.cloud escalation paths it covers, each marked unrestricted or scoped. A policy absent from the list carries no signal. Levels are data: they move when AWS changes a policy, and signal ids may be added as the assessment grows. The methodology is on the Security findings page.

Examples

What changed in the last day, as one line per policy:

curl -s --compressed https://iamtrail.com/api/v1/changes.json \
  | jq -r '.changes[]
      | select(.date > (now - 86400 | todate))
      | "\(.policyName) \(.versionId): \(.summary)"'

Every never-before-seen action AWS has shipped recently, which is usually the first public sign of an unannounced service:

curl -s --compressed https://iamtrail.com/api/v1/changes.json \
  | jq -r '.changes[] | select(.newActions | length > 0)
      | "\(.date[0:10]) \(.policyName): \(.newActions | join(", "))"'

New AWS services in the latest re:Invent season:

curl -s --compressed https://iamtrail.com/api/v1/reinvent.json \
  | jq -r '.editions[0].services[] | "\(.firstSeen) \(.prefix) \(.name // "")"'

Pre-re:Invent What's New posts in the latest season:

curl -s --compressed https://iamtrail.com/api/v1/reinvent.json \
  | jq -r '.editions[0].whatsNewPosts.items[]
      | select(.timing == "before")
      | "\(.date) \(.headline)"'

Which managed policies grant a given action:

curl -s --compressed https://iamtrail.com/api/v1/actions.json \
  | jq -r '.actions["kms:Decrypt"].actionAllowPolicies[]'

Most broad policies grant through wildcards instead. Those live in wildcardGrants, keyed by service prefix, with "*" holding patterns whose prefix is itself a wildcard. Match them the way IAM does, case-insensitively:

curl -s --compressed https://iamtrail.com/api/v1/actions.json \
  | jq -r --arg a "kms:Decrypt" '
      .wildcardGrants as $g
      | ($g[$a | split(":")[0] | ascii_downcase] // {}) + ($g["*"] // {})
      | to_entries[]
      | .key as $p
      | select($a | test("^" + ($p | gsub("\\*"; ".*") | gsub("\\?"; ".")) + "$"; "i"))
      | "\($p): \(.value | join(", "))"'

Fail a pipeline when the account has a critical AWS managed policy attached:

attached=$(aws iam list-policies --scope AWS --only-attached \
  --query 'Policies[].PolicyName' --output json)
critical=$(curl -s --compressed https://iamtrail.com/api/v1/risk.json \
  | jq -r --argjson mine "$attached" \
      '.policies[] | select(.level == "critical" and (.name | IN($mine[]))) | .name')
[ -z "$critical" ] || { echo "Critical AWS managed policies attached: $critical"; exit 1; }

Watch only the policies you actually have attached:

aws iam list-attached-role-policies --role-name my-role \
  | jq -r '.AttachedPolicies[].PolicyName' \
  | while read -r name; do
      curl -s --compressed "https://iamtrail.com/api/v1/policies/${name}.json" \
        | jq -r '"\(.name) \(.versionId) last changed \(.lastModified)"'
    done

Stability and fair use

  • Fields are added, never removed or repurposed, within a version. A breaking change means a new path under /api/v2/.
  • Files under /api/v1/ are regenerated on every deploy and served with a short cache lifetime. The scraper runs hourly, every day, so polling more than a few times an hour buys you nothing.
  • There is a rate limit of 500 requests per five minutes per IP address, which is roughly ten times what any normal use of this API needs. Exceed it and you get 429 with a JSON body until the window clears. If you need bulk access, mirror the files rather than fetching them in a loop.
  • Always send Accept-Encoding: gzip, which is what --compressed does above. Plain curl omits it, and actions.json is 4.5 MB uncompressed against 256 KB gzipped.
  • changes.json covers the recent window that the archive replay indexes. For anything older, read a policy's own history, which goes back to 2019.
  • This is an unofficial archive, not an AWS service, and it carries no uptime guarantee. If you need a hard dependency, mirror the files.
  • The data is GPL-3.0, same as the repository. Attribution to IAMTrail is appreciated.

Prefer a feed?

If you want to read changes rather than process them, the RSS feeds carry the same information in the same words, and email digests can be narrowed to specific policies.