MCP server for scanning AWS IAM identities and identifying Non-Human Identities (NHIs) such as service accounts, automation users, and machine identities.
This tool scans AWS IAM users and roles to distinguish between human users and non-human identities. It analyzes naming patterns, authentication methods, access keys, MFA configuration, and IAM tags to classify identities with a confidence score. Optionally includes detailed permission analysis to assess access levels and identify potentially dangerous permissions.
- Scans all IAM users and roles in an AWS account
- Classifies identities as human or non-human with confidence scoring
- Categorizes NHIs by type (service roles, machine users, Lambda execution roles, etc.)
- Optional permission analysis with access level assessment
- Identifies dangerous permissions and potential security risks
- Python 3.10 or higher
- AWS credentials with IAM read permissions
Clone the repository and install dependencies:
git clone https://github.com/yourusername/NHI-scan-mcp.git
cd NHI-scan-mcp
pip install -r requirements.txtFor development mode:
pip install -e .Add the NHI Scan MCP server to your Claude Desktop configuration file:
MacOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"nhi-scan": {
"command": "python",
"args": ["-m", "nhi_scan_mcp"],
"cwd": "/absolute/path/to/NHI-scan-mcp",
"env": {
"AWS_ACCESS_KEY_ID": "your-key-id",
"AWS_SECRET_ACCESS_KEY": "your-secret-key",
"AWS_DEFAULT_REGION": "us-east-1"
}
}
}
}After configuration, restart Claude Desktop. The NHI scanning tools will be available for Claude to use automatically when you ask questions about AWS IAM security.
Add the MCP server to your Cursor configuration:
- Open Cursor Settings
- Navigate to Features → MCP
- Add a new MCP server with the following configuration:
{
"mcpServers": {
"nhi-scan": {
"command": "python",
"args": ["-m", "nhi_scan_mcp"],
"cwd": "/absolute/path/to/NHI-scan-mcp",
"env": {
"AWS_ACCESS_KEY_ID": "your-key-id",
"AWS_SECRET_ACCESS_KEY": "your-secret-key",
"AWS_DEFAULT_REGION": "us-east-1"
}
}
}
}Or create/edit .cursor/mcp_settings.json in your project root:
{
"mcpServers": {
"nhi-scan": {
"command": "python",
"args": ["-m", "nhi_scan_mcp"],
"cwd": "/absolute/path/to/NHI-scan-mcp"
}
}
}After configuration, restart Cursor. You can now ask the AI assistant to scan your AWS IAM for NHIs.
Once configured, you can ask Claude or Cursor:
- "Scan my AWS IAM and show me all non-human identities"
- "List all service accounts in my AWS account with high confidence"
- "Analyze the permissions for my current AWS credentials"
- "Show me human users vs non-human identities with security recommendations"
- "Get detailed information about the IAM user named 'jenkins-automation'"
python -m nhi_scan_mcpAlternatively:
python src/nhi_scan_mcp/server.pyThe server exposes five tools for IAM scanning and analysis:
Main scanning tool that lists all IAM identities, classifies NHIs, and optionally analyzes permissions.
Parameters:
aws_access_key_id(string, optional) - AWS access key IDaws_secret_access_key(string, optional) - AWS secret access keyaws_session_token(string, optional) - Session token for temporary credentialsregion(string, optional) - AWS region, defaults to us-east-1include_permissions(boolean, optional) - Include permission analysis, defaults to false
Example:
{
"aws_access_key_id": "AKIA...",
"aws_secret_access_key": "...",
"region": "us-west-2",
"include_permissions": true
}Returns: Complete scan results including all identities, NHI classifications, confidence scores, and optional permission analysis.
Returns only non-human identities filtered by confidence threshold.
Parameters:
aws_access_key_id(string, optional)aws_secret_access_key(string, optional)aws_session_token(string, optional)region(string, optional)min_confidence(float, optional) - Minimum confidence threshold (0.0-1.0), defaults to 0.5
Returns: Filtered list of NHIs meeting the confidence threshold with classification details.
Analyzes permissions for the AWS credentials being used to run the scan.
Parameters:
aws_access_key_id(string, optional)aws_secret_access_key(string, optional)aws_session_token(string, optional)region(string, optional)
Returns: Permission analysis for the caller including access level and dangerous permissions.
Retrieves detailed information for a specific IAM user or role.
Parameters:
identity_name(string, required) - Name of the IAM user or roleidentity_type(string, optional) - Either "user" or "role", defaults to useraws_access_key_id(string, optional)aws_secret_access_key(string, optional)aws_session_token(string, optional)region(string, optional)
Returns: Complete identity details including NHI classification and permission analysis.
Provides a breakdown separating human users from non-human identities with statistics and recommendations.
Parameters:
aws_access_key_id(string, optional)aws_secret_access_key(string, optional)aws_session_token(string, optional)region(string, optional)
Returns: Summary statistics, user lists by category, and security recommendations.
Credentials can be provided in the following order of precedence:
- Explicit parameters (
aws_access_key_id,aws_secret_access_key) - Environment variables (
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY) - AWS credentials file (
~/.aws/credentials) - IAM role (when running on EC2/ECS)
The AWS credentials must have the following permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:ListUsers",
"iam:ListRoles",
"iam:ListUserTags",
"iam:ListRoleTags",
"iam:ListAccessKeys",
"iam:ListMFADevices",
"iam:GetUser",
"iam:GetRole",
"iam:ListAttachedUserPolicies",
"iam:ListAttachedRolePolicies",
"iam:ListUserPolicies",
"iam:ListRolePolicies",
"iam:GetPolicy",
"iam:GetPolicyVersion",
"iam:GetUserPolicy",
"iam:GetRolePolicy",
"iam:ListGroupsForUser",
"sts:GetCallerIdentity"
],
"Resource": "*"
}
]
}The tool evaluates multiple signals to determine if a user is non-human:
- Name patterns - Matches against common prefixes like
svc-,app-,bot-,api-,lambda-,ci-,cd-,terraform-,ansible-, etc. - Password usage - Users with no password login history
- Access keys - Presence of active programmatic access keys
- MFA status - Absence of MFA devices (expected for human users)
- Tags - Explicit tags marking service accounts, bots, or automation
Each signal contributes to a confidence score from 0.0 to 1.0. Users with confidence ≥ 0.5 are classified as NHIs.
All roles are inherently non-human, but are further classified by analyzing their assume role policy:
- Service roles - Trusted by AWS services (Lambda, EC2, ECS, etc.)
- Lambda execution roles - Specifically for Lambda functions
- EC2 instance profiles - For EC2 instances
- Cross-account roles - Trust relationships with other AWS accounts
- Federated roles - SAML or OIDC federation
- Application roles - General application service roles
You can also use the modules directly in your own Python scripts:
from nhi_scan_mcp.aws_scanner import AWSIAMScanner
from nhi_scan_mcp.nhi_identifier import NHIIdentifier
# Initialize scanner (uses default AWS credential chain)
scanner = AWSIAMScanner()
# Or with explicit credentials:
# scanner = AWSIAMScanner(
# aws_access_key_id="YOUR_KEY",
# aws_secret_access_key="YOUR_SECRET",
# region_name="us-east-1"
# )
# Get caller identity
caller = scanner.get_caller_identity()
print(f"Account: {caller['Account']}")
# List all IAM users and roles
users = scanner.list_users()
roles = scanner.list_roles()
print(f"Found {len(users)} users and {len(roles)} roles")
# Identify NHIs
identifier = NHIIdentifier()
identifications = identifier.identify_all(users, roles)
# Display results
for identification in identifications:
if identification.is_nhi and identification.identity.identity_type == "user":
print(f"🤖 {identification.identity.name}")
print(f" Category: {identification.nhi_category}")
print(f" Confidence: {identification.confidence:.2f}")from nhi_scan_mcp.aws_scanner import AWSIAMScanner
from nhi_scan_mcp.permission_analyzer import PermissionAnalyzer
# Initialize scanner and analyzer
scanner = AWSIAMScanner()
analyzer = PermissionAnalyzer(scanner)
# Analyze your own permissions
caller_analysis = analyzer.analyze_caller_permissions()
print(f"Permission Level: {caller_analysis.permission_level}")
print(f"Admin Access: {caller_analysis.admin_access}")
if caller_analysis.dangerous_permissions:
print("⚠️ Dangerous Permissions:")
for perm in caller_analysis.dangerous_permissions:
print(f" - {perm}")
# Analyze specific user permissions
users = scanner.list_users()
for user in users:
analysis = analyzer.analyze_user_permissions(user)
print(f"{user.name}: {analysis.permission_level}")from nhi_scan_mcp.aws_scanner import AWSIAMScanner
from nhi_scan_mcp.nhi_identifier import NHIIdentifier
scanner = AWSIAMScanner()
identifier = NHIIdentifier()
# Scan and identify
users = scanner.list_users()
roles = scanner.list_roles()
identifications = identifier.identify_all(users, roles)
# Separate human users from NHIs
human_users = []
nhi_users = []
uncertain_users = []
for identification in identifications:
if identification.identity.identity_type != "user":
continue
if identification.nhi_category.value == "human_user":
human_users.append(identification)
elif identification.nhi_category.value == "uncertain":
uncertain_users.append(identification)
else:
nhi_users.append(identification)
print(f"Human Users: {len(human_users)}")
print(f"NHI Users: {len(nhi_users)}")
print(f"Uncertain Users: {len(uncertain_users)}")
# Generate security recommendations
no_mfa_humans = [i for i in human_users if not i.identity.mfa_devices]
if no_mfa_humans:
print(f"\n⚠️ {len(no_mfa_humans)} human users lack MFA!")
for i in no_mfa_humans:
print(f" - {i.identity.name}")MIT License - see LICENSE file for details.
Built with FastMCP for Model Context Protocol server implementation and boto3 for AWS API interactions.