The AI Offboarding Problem: Finding Orphaned Agents in Your Cloud
I just came across the article on Hacker News about 'Orphaned AI Agents,' and it perfectly articulates a gap we’ve been struggling with. The core issue is the administrative debt left behind by the rush to deploy internal AI tools—specifically, what happens when the creator leaves but the agent remains.
We’re seeing a surge in custom bots built on frameworks like LangChain or AutoGPT that interact with core APIs (GitHub, Jira, AWS). These are often spun up with individual user API keys or service principals that are granted excessive standing privileges. When the employee offboards, the revocation process often misses these non-human identities, leaving an autonomous agent with valid credentials floating around the network.
To tackle this, we've started auditing our cloud providers for 'ghost' access keys. For AWS, we check for IAM users who are inactive in the IdP but still have active Access Keys that haven't been rotated in >90 days.
Here is a quick Python snippet we use to identify potential orphans by checking the LastUsedDate of access keys:
import boto3
from datetime import datetime, timedelta
def find_stale_keys():
iam = boto3.client('iam')
users = iam.list_users()['Users']
threshold = datetime.now() - timedelta(days=90)
for user in users:
username = user['UserName']
access_keys = iam.list_access_keys(UserName=username)['AccessKeyMetadata']
for key in access_keys:
if key['Status'] == 'Active':
# Check last used information
last_used = iam.get_access_key_last_used(AccessKeyId=key['AccessKeyId'])
last_used_date = last_used['AccessKeyLastUsed'].get('LastUsedDate')
if last_used_date and last_used_date < threshold:
print(f"STALE KEY FOUND: User {username}, KeyID {key['AccessKeyId']}, Last Used: {last_used_date}")
find_stale_keys()
We are also correlating this with Microsoft Sentinel logs to flag when a 'terminated' user ID is generating authentication events for AI endpoints like OpenAI or Azure Cognitive Services.
How are you guys handling the lifecycle management for these autonomous agents? Are you treating them as standard service accounts or do you have a specific policy for AI workloads?
This is a huge issue right now. We're treating all AI agents as standard Service Principals in Entra ID, but enforcing a strict 90-day secret rotation via API. The problem is the 'Shadow AI' where devs spin up agents on their local machines using personal API keys.
We started using a KQL query in Sentinel to detect source IPs associated with AI tool usage that haven't authenticated via MFA recently.
SigninLogs
| where AppDisplayName in ("OpenAI", "AzureOpenAI")
| where ResultType == 0
| join kind=anti IdentityInfo on $left.AccountObjectId == $right.AccountObjectId
| where isnull(IdentityInfo.AccountEnabled) or IdentityInfo.AccountEnabled == false
It catches the accounts that are technically disabled or deleted but are still leveraging cached tokens or API keys.
From a pentester's perspective, these orphaned agents are gold mines. During the last engagement for a SaaS company, I found a hard-coded API key for a custom support bot in a public GitHub repo. The repo was three years old, but the key still had read-write access to their internal knowledge base because no one ever rotated it or linked it to an automated offboarding script.
My advice? Don't just rely on IAM checks. You need to scan your code repos (including those old archived ones) for secrets and validate them against your cloud provider to ensure they are actually dead.
We implemented an Infrastructure as Code (IaC) requirement for all internal AI agents. If it's not defined in Terraform and managed by a central pipeline, it gets shut down.
This forces standing privileges into code where they can be reviewed. We also tag every resource with the Owner and Department tags. A nightly Lambda function checks for resources with the AI_Agent tag and verifies if the corresponding Owner email is still active in HR. If the owner is gone, the resource is auto-quarantined.
In ICS, we obsess over asset inventory because unmanaged devices are dangerous. The same logic applies here: you can't secure what you can't see. Beyond just IaC, we use network traffic analysis to spot 'zombie' agents. We run a nightly query to flag API calls from IPs or User-Agents not registered in our CMDB.
AWSCloudTrail
| where ServiceName == "bedrock.amazonaws.com"
| where SourceIpAddress !in (ip_list)
| project SourceIpAddress, UserIdentityType, EventName
This helps catch the agents that were spun up manually and fell through the cracks.
To supplement the inventory and IaC strategies, implementing automated 'last-used' audits is effective for catching stragglers. We run a weekly job to identify credentials inactive for over 30 days. For AWS environments, this CLI snippet helps pinpoint specific keys:
aws iam get-access-key-last-used --access-key-id AKIAEXAMPLE
Integrating this output into HR offboarding workflows ensures we immediately flag API keys associated with departing employees. Has anyone successfully automated this trigger directly within their identity provider?
Beyond just inventory, look at the underlying identities. These agents often rely on specific IAM roles or service principals that go dark when the creator leaves. We run a scan in AWS to flag roles unused for 90 days, which usually points to an abandoned agent or script.
import boto3, datetime
iam = boto3.client('iam')
cutoff = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=90)
for r in iam.list_roles()['Roles']:
last = r.get('RoleLastUsed', {}).get('LastUsedDate', datetime.datetime.min.replace(tzinfo=datetime.timezone.utc))
if last < cutoff:
print(f"Potential Orphan: {r['RoleName']}")
Verified Access Required
To maintain the integrity of our intelligence feeds, only verified partners and security professionals can post replies.
Request Access