{"id":45483385,"url":"https://github.com/cloud-copilot/iam-expand","last_synced_at":"2026-05-10T21:04:56.841Z","repository":{"id":255445973,"uuid":"850435671","full_name":"cloud-copilot/iam-expand","owner":"cloud-copilot","description":"Expand IAM Actions with Wildcards","archived":false,"fork":false,"pushed_at":"2026-02-14T18:09:03.000Z","size":685,"stargazers_count":34,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-02-15T02:25:21.082Z","etag":null,"topics":["aws","iam","iam-policy"],"latest_commit_sha":null,"homepage":"https://iam.cloudcopilot.io/tools/iam-expand","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cloud-copilot.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-08-31T19:01:19.000Z","updated_at":"2026-02-14T18:08:49.000Z","dependencies_parsed_at":null,"dependency_job_id":"f7972da6-db97-4234-a857-86f71fc48b3d","html_url":"https://github.com/cloud-copilot/iam-expand","commit_stats":null,"previous_names":["cloud-copilot/iam-expand"],"tags_count":54,"template":false,"template_full_name":null,"purl":"pkg:github/cloud-copilot/iam-expand","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-copilot%2Fiam-expand","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-copilot%2Fiam-expand/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-copilot%2Fiam-expand/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-copilot%2Fiam-expand/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cloud-copilot","download_url":"https://codeload.github.com/cloud-copilot/iam-expand/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-copilot%2Fiam-expand/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29718465,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-22T15:10:41.462Z","status":"ssl_error","status_checked_at":"2026-02-22T15:10:04.636Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","iam","iam-policy"],"created_at":"2026-02-22T16:35:53.211Z","updated_at":"2026-02-22T16:35:53.780Z","avatar_url":"https://github.com/cloud-copilot.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Expand IAM Actions\n\n[![NPM Version](https://img.shields.io/npm/v/@cloud-copilot/iam-expand.svg?logo=nodedotjs)](https://www.npmjs.com/package/@cloud-copilot/iam-expand) [![License: AGPL v3](https://img.shields.io/github/license/cloud-copilot/iam-expand)](LICENSE.txt) [![GuardDog](https://github.com/cloud-copilot/iam-expand/actions/workflows/guarddog.yml/badge.svg)](https://github.com/cloud-copilot/iam-expand/actions/workflows/guarddog.yml) [![Known Vulnerabilities](https://snyk.io/test/github/cloud-copilot/iam-expand/badge.svg?targetFile=package.json\u0026style=flat-square)](https://snyk.io/test/github/cloud-copilot/iam-expand?targetFile=package.json)\n\nBuilt in the Unix philosophy, this is a small tool that does one thing well: explain IAM actions with wildcards.\n\nUse this to:\n\n1. Expand wildcards when you are not allowed to use them in your policies.\n2. Get an exhaustive list of actions that are included in a policy to quickly search it for interesting actions.\n3. Investigate where interesting or dubious actions are being used in your policies.\n\n\u003c!-- Image of demo.svg --\u003e\n\n![Demo](assets/demo.svg)\n\nExtended demo [on YouTube](https://www.youtube.com/watch?v=357-uGru7300).\n\nPublished as an [npm package](#typescriptnodejs-usage) in ESM and CommonJS plus available as a [CLI](#cli).\n\nAll information is sourced from [@cloud-copilot/iam-data](https://github.com/cloud-copilot/iam-data) which is updated daily.\n\n## Only Valid Values\n\n`iam-expand` intends to only return valid, actual actions, if any invalid values are passed in such as an invalid format or a service/action that does not exist, they will be left out of the output. There are options to override this behavior.\n\n## Use In Browser\n\n[http://iam.cloudcopilot.io/tools/iam-expand](http://iam.cloudcopilot.io/tools/iam-expand)\n\n## CLI\n\nThere is a CLI! The [examples folder](examples/README.md) has examples showing how to use the CLI to find interesting actions in your IAM policies.\n\n### Global CLI Installation\n\nYou can install it globally. This also works in the default AWS CloudShell!\n\n```bash\nnpm install -g @cloud-copilot/iam-expand\n```\n\n_Depending on your configuration sudo may be required to install globally._\n\n### Install CLI In a Project\n\nYou can also install the CLI in a project and run it with `npx`.\n\n```bash\nnpm install @cloud-copilot/iam-expand\n# Run with npx inside your project\nnpx @cloud-copilot/iam-expand\n```\n\n### Expand Actions\n\nThe simplest usage is to pass in the actions you want to expand.\n\n```bash\niam-expand s3:Get*Tagging\n# Outputs all Get*Tagging actions\ns3:GetBucketTagging\ns3:GetJobTagging\ns3:GetObjectTagging\ns3:GetObjectVersionTagging\ns3:GetStorageLensConfigurationTaggin\n```\n\n```bash\niam-expand s3:Get*Tagging s3:Put*Tagging\n# Outputs the combination of Get*Tagging and Put*Tagging actions deduplicated and sorted\ns3:GetBucketTagging\ns3:GetJobTagging\ns3:GetObjectTagging\ns3:GetObjectVersionTagging\ns3:GetStorageLensConfigurationTagging\ns3:PutBucketTagging\ns3:PutJobTagging\ns3:PutObjectTagging\ns3:PutObjectVersionTagging\ns3:PutStorageLensConfigurationTaggin\n```\n\n### Inverting Actions\n\nUse this to find all actions that are not in a set of patterns\n\n```bash\niam-expand --invert s3:Get*Tagging s3:Put*Tagging\n#Outputs all actions that are not Get*Tagging or Put*Tagging\na2c:GetContainerizationJobDetails\na2c:GetDeploymentJobDetails\na2c:StartContainerizationJob\na2c:StartDeploymentJob\na4b:ApproveSkill\na4b:AssociateContactWithAddressBook\n...\n```\n\n### Help\n\nRun the command with no options to show usage:\n\n```bash\niam-expand\n```\n\n### Options\n\n#### `--expand-asterisk`\n\nBy default, a single `*` will not be expanded. If you want to expand a single `*` you can set this flag.\n\n```bash\niam-expand \"*\"\n# Returns the asterisk\n*\n\niam-expand --expand-asterisk \"*\"\n# Returns very many strings, very very fast. 📚 🚀\n```\n\n#### `--error-on-invalid-format`\n\nBy default, if an invalid format is passed in, such as:\n\n- `s3Get*Tagging` (missing a separator) or\n- `s3:Get:Tagging*` (too many separators)\n\nit will be silenty ignored and left out of the output. If you want to throw an error when an invalid format is passed in you can set this flag.\n\n```bash\niam-expand \"s3Get*Tagging\"\n# Returns nothing\n\niam-expand --error-on-invalid-format \"s3Get*Tagging\"\n# Throws an error and returns a non zero exit code\n# Invalid action format: s3Get*Tagging\n```\n\n#### `--error-on-invalid-service`\n\nBy default, if a service is passed in that does not exist in the IAM data, it will be silently ignored and left out of the output. If you want to throw an error when a service is passed in that does not exist you can set this flag.\n\n```bash\niam-expand \"r2:Get*Tagging\"\n# Returns nothing\n\niam-expand --error-on-invalid-service \"r2:Get*Tagging\"\n# Throws an error and returns a non zero exit code\n# Service not found: r2\n```\n\n#### `--invalid-action-behavior`\n\nBy default, if an action is passed in that does not exist in the IAM data, it will be silently ignored and left out of the output. There are two options to override this behavior: `error` and `include`.\n\n```bash\niam-expand \"ec2:DestroyAvailabilityZone\"\n# Returns nothing\n\niam-expand --invalid-action-behavior remove \"ec2:DestroyAvailabilityZone\"\n# Returns nothing\n\niam-expand --invalid-action-behavior error \"ec2:DestroyAvailabilityZone\"\n# Throws an error and returns a non zero exit code\n# Invalid action: ec2:DestroyAvailabilityZone\n\niam-expand --invalid-action-behavior include \"ec2:DestroyAvailabilityZone\"\n# Returns the invalid action\nec2:DestroyAvailabilityZone\n```\n\n#### `--invert`\n\nUse this to find all actions that are not in a set of patterns. Only works for actions passed as arguments, or unstructured content from stdin.\n\n```bash\niam-expand --invert s3:Get*Tagging s3:Put*Tagging\n#Outputs all actions that are not Get*Tagging or Put*Tagging\na2c:GetContainerizationJobDetails\na2c:GetDeploymentJobDetails\na2c:StartContainerizationJob\na2c:StartDeploymentJob\na4b:ApproveSkill\na4b:AssociateContactWithAddressBook\n...\n```\n\n#### `--invert-not-actions`\n\n_This operates only on JSON input_. It will recursively search the JSON document for any `NotAction` that is a string or an array of strings. The `NotAction` will be replaced with an `Action` key that is the inverse of the `NotAction` actions or patterns.\n\n```bash\ncat policy.json | iam-expand --invert-not-actions\n```\n\nSee [Read from Stdin](#read-from-stdin) for more details\n\n#### `--show-data-version`\n\nShow the version of the data that is being used to expand the actions and exit.\n\n```bash\niam-expand --show-data-version\n@cloud-copilot/iam-data version: 0.3.202409051\nData last updated: Thu Sep 05 2024 04:46:39 GMT+0000 (Coordinated Universal Time)\nUpdate with either:\n  npm update @cloud-copilot/iam-data\n  npm update -g @cloud-copilot/iam-data\n```\n\n#### `--read-wait-ms`\n\nWhen reading from stdin (see [below](#read-from-stdin)) the CLI will wait 10 seconds for the first byte to be read before timing out. This is enough time for most operations. If you want to wait longer you can set this flag to the number of milliseconds you want to wait.\n\n```bash\ncat policy.json | iam-expand\n# Will wait up to 10 seconds for input to start, which is plenty of time for a local file.\n\ncurl \"https://government-secrets.s3.amazonaws.com/secret-policy.json\" | iam-expand --read-wait-ms 20000\n# Will wait up to 20 seconds to receive first byte from curl before timing out. Adjust as needed\n```\n\n### Read from stdin\n\nIf no actions are passed as arguments, the CLI will read from stdin.\n\n#### Expanding JSON input\n\nIf the input is a valid json document, the CLI will find every instance of `Action` and `NotAction` that is a string or an array of strings and expand them. This is useful for finding all the actions in a policy document or set of documents.\n\nGiven `policy.json`\n\n```json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": \"s3:Get*Tagging\",\n      \"Resource\": \"*\"\n    },\n    {\n      \"Effect\": \"Deny\",\n      \"NotAction\": [\"s3:Get*Tagging\", \"s3:Put*Tagging\"],\n      \"Resource\": \"*\"\n    }\n  ]\n}\n```\n\n```bash\ncat policy.json | iam-expand \u003e expanded-policy.json\n```\n\nGives this file in `expanded-policy.json`\n\n```json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      // Was \"s3:Get*Tagging\"\n      \"Action\": [\n        \"s3:GetBucketTagging\",\n        \"s3:GetJobTagging\",\n        \"s3:GetObjectTagging\",\n        \"s3:GetObjectVersionTagging\",\n        \"s3:GetStorageLensConfigurationTagging\"\n      ],\n      \"Resource\": \"*\"\n    },\n    {\n      \"Effect\": \"Deny\",\n      // Was [\"s3:Get*Tagging\", \"s3:Put*Tagging\"]\n      \"NotAction\": [\n        \"s3:GetBucketTagging\",\n        \"s3:GetJobTagging\",\n        \"s3:GetObjectTagging\",\n        \"s3:GetObjectVersionTagging\",\n        \"s3:GetStorageLensConfigurationTagging\",\n        \"s3:PutBucketTagging\",\n        \"s3:PutJobTagging\",\n        \"s3:PutObjectTagging\",\n        \"s3:PutObjectVersionTagging\",\n        \"s3:PutStorageLensConfigurationTagging\"\n      ],\n      \"Resource\": \"*\"\n    }\n  ]\n}\n```\n\nYou can also invert the `NotAction` using `--invert-not-actions`. This will replace the `NotAction` element with an `Action` element that is the inverse of actions listed in the `NotAction`.\n\n```bash\ncat policy.json | iam-expand --invert-not-actions \u003e inverted-policy.json\n```\n\nGives this file in `inverted-policy.json`\n\n```json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      // Was \"s3:Get*Tagging\"\n      \"Action\": [\n        \"s3:GetBucketTagging\",\n        \"s3:GetJobTagging\",\n        \"s3:GetObjectTagging\",\n        \"s3:GetObjectVersionTagging\",\n        \"s3:GetStorageLensConfigurationTagging\"\n      ],\n      \"Resource\": \"*\"\n    },\n    {\n      \"Effect\": \"Deny\",\n      // Was NotAction: [\"s3:Get*Tagging\", \"s3:Put*Tagging\"]\n      // Now is Action: everything but the Get*Tagging and Put*Tagging actions\n      \"Action\": [\n        \"a2c:GetContainerizationJobDetails\",\n        \"a2c:GetDeploymentJobDetails\",\n        \"a2c:StartContainerizationJob\",\n        ...\n        \"xray:UntagResource\",\n        \"xray:UpdateGroup\",\n        \"xray:UpdateSamplingRule\",\n      ],\n      \"Resource\": \"*\"\n    }\n  ]\n }\n```\n\nYou can also use this to expand the actions from the output of commands.\n\n```bash\naws iam get-account-authorization-details --output json | iam-expand --read-wait-ms 20000 \u003e expanded-authorization-details.json\n# Now you can search the output for actions you are interested in\ngrep -n \"kms:DisableKey\" expanded-authorization-details.json\n```\n\n#### Expanding arbitrary input\n\nIf the input from stdin is not json, the content is searched for IAM actions then expands them. Throw anything at it and it will find all the actions it can and expand them.\n\nYou can echo content:\n\n```bash\necho \"s3:Get*Tagging\" | iam-expand\n```\n\nYou can pull out part of a json file and pipe it in:\n\n```bash\ncat policy.json | jq '.Statement[].Action' | iam-expand\n```\n\nOr some Terraform:\n\n```bash\ncat main.tf | iam-expand\n```\n\nOr some CloudFormation:\n\n```bash\ncat template.yaml | iam-expand\n```\n\nOr even some HTML:\n\n```bash\ncurl \"https://docs.aws.amazon.com/aws-managed-policy/latest/reference/ReadOnlyAccess.html\" | iam-expand\n```\n\nOr the output of any command.\n\nBecause of the likelyhood of finding an aseterik `*` in the input; if the value to stdin is not a valid json document the stdin option will not find or expand a single `*` even if `--expand-asterisk` is passed.\n\nPlease give this anything you can think of and open an issue if you see an opportunity for improvement.\n\n## Typescript/NodeJS Usage\n\n## Add to a project\n\n```bash\nnpm install @cloud-copilot/iam-expand\n```\n\n```typescript\nimport { expandIamActions } from '@cloud-copilot/iam-expand'\n\nexpandIamActions('s3:Get*Tagging')[\n  ('s3:GetBucketTagging',\n  's3:GetJobTagging',\n  's3:GetObjectTagging',\n  's3:GetObjectVersionTagging',\n  's3:GetStorageLensConfigurationTagging')\n]\n\nexpandIamActions(['s3:Get*Tagging', 's3:Put*Tagging'])[\n  ('s3:GetBucketTagging',\n  's3:GetJobTagging',\n  's3:GetObjectTagging',\n  's3:GetObjectVersionTagging',\n  's3:GetStorageLensConfigurationTagging',\n  's3:PutBucketTagging',\n  's3:PutJobTagging',\n  's3:PutObjectTagging',\n  's3:PutObjectVersionTagging',\n  's3:PutStorageLensConfigurationTagging')\n]\n```\n\n## API Reference\n\n## `expandIamActions`\n\n`expandIamActions(actionStringOrStrings: string | string[], overrideOptions?: Partial\u003cExpandIamActionsOptions\u003e)` is the main function that will expand the actions of the IAM policy. Takes a string or array of strings and returns an array of strings that the input matches.\n\n## Only Valid Values\n\n`expandIamActions` intends to only return valid actual actions, if any invalid values are passed in such as an invalid format or a service/action that does not exist, they will be left out of the output. There are options to override this behavior.\n\nAny escaped unicode characters will be converted to their original character as part of the process. So `s3:\\\\u0067et*` will be converted to `s3:Get*` before processing. Even something like `s3:\\\\u0067etBucket` will be converted to `s3:GetBucket` even though it has no wildcards..\n\n## Options\n\n`expandIamActions` an optional second argument that is an object with the following options:\n\n### `expandAsterisk`\n\nBy default, a single `*` will not be expanded. If you want to expand a single `*` you can set this option to `true`.\n\n```typescript\nimport { expandIamActions } from '@cloud-copilot/iam-expand';\n\n//Returns the unexpanded value\nexpandIamActions('*')\n['*']\n\n//Returns the expanded value\nexpandIamActions('*', { expandAsterisk: true })\n[\n  //Many many strings. 🫢\n]\n```\n\n### `errorOnInvalidFormat`\n\nBy default, if an invalid format is passed in, such as:\n\n- `s3Get*Tagging` (missing a separator) or\n- `s3:Get:Tagging*` (too many separators)\n\nit will be silenty ignored and left out of the output. If you want to throw an error when an invalid format is passed in you can set this option to `true`.\n\n```typescript\nimport { expandIamActions } from '@cloud-copilot/iam-expand';\n\n//Ignore invalid format\nexpandIamActions('s3Get*Tagging')\n[]\n\n//Throw an error on invalid format\nexpandIamActions('s3Get*Tagging', { errorOnInvalidFormat: true })\n//Uncaught Error: Invalid action format: s3Get*Tagging\n```\n\n### `errorOnInvalidService`\n\nBy default, if a service is passed in that does not exist in the IAM data, it will be silently ignored and left out of the output. If you want to throw an error when a service is passed in that does not exist you can set this option to `true`.\n\n```typescript\nimport { expandIamActions } from '@cloud-copilot/iam-expand';\n\n//Ignore invalid service\nexpandIamActions('r2:Get*Tagging')\n[]\n\n//Throw an error on invalid service\nexpandIamActions('r2:Get*Tagging', { errorOnInvalidService: true })\n//Uncaught Error: Service not found: r2\n```\n\n### `invalidActionBehavior`\n\nBy default, if an action is passed in that does not exist in the IAM data, it will be silently ignored and left out of the output. There are two options to override this behavior: `Error` and `Include`.\n\n```typescript\nimport { expandIamActions, InvalidActionBehavior } from '@cloud-copilot/iam-expand';\n\n//Ignore invalid action by default\nexpandIamActions('ec2:DestroyAvailabilityZone')\n[]\n\n//Ignore invalid action explicitly\nexpandIamActions('ec2:DestroyAvailabilityZone', { invalidActionBehavior: InvalidActionBehavior.Remove })\n[]\n\n//Throw an error on invalid action\nexpandIamActions('ec2:DestroyAvailabilityZone', { invalidActionBehavior: InvalidActionBehavior.Error })\n//Uncaught Error: Invalid action: ec2:DestroyAvailabilityZone\n\n//Include invalid action\nexpandIamActions('ec2:DestroyAvailabilityZone', { invalidActionBehavior: InvalidActionBehavior.Include })\n['ec2:DestroyAvailabilityZone']\n```\n\n## `invertIamActions`\n\n`invertIamActions(actionString: string): string` will take an action string and return all actions not matching . For example `s3:Get*Tagging` will return all actions from all services except those s3 actions that match the pattern `Get*Tagging`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloud-copilot%2Fiam-expand","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloud-copilot%2Fiam-expand","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloud-copilot%2Fiam-expand/lists"}