Back to skill

Security audit

agent-teams

Security checks for vulnerabilities and agentic risk

Overview

This Teams skill is purpose-related but needs Review because it silently extracts Teams session tokens, stores sensitive data locally, and has inconsistent package installation instructions.

Install only if you are comfortable giving this skill user-equivalent Teams access through a desktop session token. Verify the npm package name and provenance before installing, avoid granting terminal Full Disk Access, inspect or disable local snapshot and memory files, and treat the credentials file as an account secret that can send/read Teams as you until the token expires or is revoked.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
Findings (4)

T08 · Insecure Dependencies

Error
Location
templates/team-summary.sh:52
Finding
Conflicting and unpinned npm installation instructions create a dependency-substitution risk<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:8-13`, `SKILL.md:391-398`, `templates/team-summary.sh:52-59`, `templates/monitor-channel.sh:171-178`, `templates/post-message.sh:155-162` **Vulnerability Type**: T08: Insecure Dependencies **Risk Level**: High ### Vulnerable Code `SKILL.md:8-13`: ```yaml metadata: openclaw: requires: bins: - agent-teams install: - kind: node package: agent-messenger bins: [agent-teams] ``` `SKILL.md:391-398`: ```markdown **`agent-teams` is NOT the npm package name.** The npm package is `agent-messenger`. If the package is installed globally, use `agent-teams` directly: ```bash agent-teams team list ``` If the package is NOT installed, use `bunx agent-messenger teams`: ``` `templates/team-summary.sh:52-59`: ```bash if ! command -v agent-teams &> /dev/null; then echo -e "${RED}Error: agent-teams not found${NC}" >&2 echo "" >&2 echo "Install it with:" >&2 echo " bun install -g agent-teams" >&2 exit 1 fi ``` The same conflicting `bun install -g agent-teams` recommendation appears in `templates/monitor-channel.sh:171-178` and `templates/post-message.sh:155-162`. ### Technical Analysis The Skill manifest requests the npm package `agent-messenger`, but each runnable template tells users to install `agent-teams` globally. The Skill documentation expressly states that `agent-teams` is not the correct npm package name and may install the wrong package. This inconsistency creates a package-substitution or typosquatting opportunity. Neither installation path pins an exact package version or integrity digest. Consequently, the effective code can change after the Skill has been reviewed. npm-compatible package installations can also execute lifecycle scripts with the privileges of the invoking user. This is particularly dangerous here because the resulting CLI is expected to handle a reusable Microsoft Teams session token. The repository does not contain evid ...[truncated 1360 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace every `bun install -g agent-teams` instruction with the verified package name `agent-messenger`. 2. Pin an exact reviewed version rather than accepting the latest release. 3. Use a lockfile and package integrity hash where the execution environment supports them. 4. Avoid global installation; install into an isolated project environment with minimal filesystem access. 5. Verify publisher identity, package provenance, signatures, and registry source before installation. 6. Disable or strictly control package lifecycle scripts during installation where feasible. 7. Make the manifest and all templates use one consistent installation path. 8. Add automated tests that fail if documentation or templates reference an unapproved package name. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
references/authentication.md:34
Finding
Automatic extraction and plaintext persistence of a user-equivalent Teams session token<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:24-36`, `SKILL.md:328-341`, `references/authentication.md:34-48`, `references/authentication.md:89-121`, `references/authentication.md:225-232` **Vulnerability Type**: T05: Unauthorized Access and Privilege Escalation **Risk Level**: High ### Vulnerable Code `SKILL.md:24-36`: ```markdown Credentials are extracted automatically from the Teams desktop app on first use. No manual setup required — just run any command and authentication happens silently in the background. Teams tokens expire in 60-90 minutes. The CLI automatically re-extracts a fresh token when the current one expires, so you don't need to manage token lifecycle manually. **IMPORTANT**: NEVER guide the user to open a web browser, use DevTools, or manually copy tokens from a browser. Always use `agent-teams auth extract` to obtain tokens from the desktop app. ``` `references/authentication.md:34-48`: ```markdown This command: 1. Detects your operating system (macOS, Linux, Windows) 2. Locates the Teams desktop app data directory 3. Reads the **Cookies SQLite database** containing session data 4. Extracts `skypetoken_asm` cookie value 5. Validates token against Teams API before saving 6. Discovers ALL joined teams 7. Stores credentials securely in `~/.config/agent-messenger/teams-credentials.json` ``` `references/authentication.md:89-121`: ```markdown ### Location Credentials are stored in: ``` ~/.config/agent-messenger/teams-credentials.json ``` ### Format ```json { "token": "skypetoken_asm_value_here", "token_extracted_at": "2024-01-15T10:00:00.000Z", "current_team": "team-uuid-1", "teams": { "team-uuid-1": { "team_id": "team-uuid-1", "team_name": "Engineering" }, "team-uuid-2": { "team_id": "team-uuid-2", "team_name": "Marketing" } } } ``` ### Security - File permissions: `0600` (owner read/write only) - Tokens are stored in plaintext (same as Teams desktop app) - Keep thi ...[truncated 2958 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace desktop-cookie extraction with Microsoft's supported OAuth authorization flow. 2. Request only the delegated scopes required for the specific operation and display them before consent. 3. Require explicit user approval before initial authentication or token refresh; do not authenticate silently. 4. Store refresh and access tokens in the operating system's credential vault rather than a plaintext JSON file. 5. Never recommend terminal-wide Full Disk Access. If local desktop integration is unavoidable, use a narrowly scoped helper with explicit authorization. 6. Separate read, send, file, and administrative operations so users can grant only needed capabilities. 7. Clearly identify the service endpoints used for token validation and Teams API calls. 8. Add token revocation, logout, audit logging, and short retention controls. 9. Independently review and pin the external CLI implementation before allowing it to handle session credentials. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
templates/team-summary.sh:199
Finding
Comprehensive Teams snapshots containing messages and email addresses are saved to plaintext files by default<![CDATA[ ## Vulnerability Details **File Location**: `templates/team-summary.sh:85-117`, `templates/team-summary.sh:147-176`, `templates/team-summary.sh:199-202` **Vulnerability Type**: T09: Insecure Skill Coding Practices **Risk Level**: Medium ### Vulnerable Code `templates/team-summary.sh:85-117`: ```bash echo -e "${YELLOW}Fetching team snapshot...${NC}" >&2 echo -e "Token age: ${TOKEN_AGE} minutes" >&2 SNAPSHOT=$(agent-teams snapshot 2>&1) # Handle token expiry during snapshot if echo "$SNAPSHOT" | grep -Eqi "expired|401|unauthorized" 2>/dev/null; then echo -e "${YELLOW}Token expired during snapshot, refreshing...${NC}" >&2 agent-teams auth extract >&2 SNAPSHOT=$(agent-teams snapshot 2>&1) fi if echo "$SNAPSHOT" | jq -e '.error' > /dev/null 2>&1; then echo -e "${RED}Failed to get snapshot${NC}" >&2 ERROR_MSG=$(echo "$SNAPSHOT" | jq -r '.error // "Unknown error"') echo -e "${RED}Error: $ERROR_MSG${NC}" >&2 exit 1 fi if [ "$OUTPUT_JSON" = true ]; then echo "$SNAPSHOT" exit 0 fi TEAM_NAME=$(echo "$SNAPSHOT" | jq -r '.team.name // "Unknown"') TEAM_ID=$(echo "$SNAPSHOT" | jq -r '.team.id // "Unknown"') CHANNELS=$(echo "$SNAPSHOT" | jq '.channels // []') CHANNEL_COUNT=$(echo "$CHANNELS" | jq 'length') STANDARD_COUNT=$(echo "$CHANNELS" | jq '[.[] | select(.type == "standard")] | length') PRIVATE_COUNT=$(echo "$CHANNELS" | jq '[.[] | select(.type == "private")] | length') MEMBERS=$(echo "$SNAPSHOT" | jq '.members // []') MEMBER_COUNT=$(echo "$MEMBERS" | jq 'length') MESSAGES=$(echo "$SNAPSHOT" | jq '.recent_messages // []') MESSAGE_COUNT=$(echo "$MESSAGES" | jq 'length') ``` `templates/team-summary.sh:147-176`: ```bash echo -e "${BOLD}${CYAN}Sample Members:${NC}" echo "$MEMBERS" | jq -r ' .[0:10] | .[] | " \(.displayName) \(if .email then "(\(.email))" else "" end)" ' if [ "$MEMBER_COUNT" -gt 10 ]; then echo " ... and $((MEMBER_COUNT - 10)) more" fi echo "" echo -e "${BOLD}${CYAN}Recent Activity (${MESSAGE_COUNT} messages) ...[truncated 2417 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not save snapshots by default; make persistence opt-in through an explicit `--save` option. 2. Fetch only fields required for the requested summary and avoid retrieving full message bodies or member email addresses unless explicitly requested. 3. Apply redaction before output or storage, particularly for message content, email addresses, user IDs, and private-channel metadata. 4. Set `umask 077` before creating any sensitive output and explicitly apply mode `0600`. 5. Write to a user-selected destination rather than the current directory. 6. Warn before writing and identify exactly which categories of data will be stored. 7. Offer automatic deletion or a configurable retention period. 8. Prevent accidental repository commits through a documented ignore pattern such as `team-snapshot-*.json`. 9. If durable storage is necessary, use encryption backed by an operating-system credential store. ]]>

T02 · Agent Memory Poisoning

Warning
Location
SKILL.md:51
Finding
Mandatory cross-session memory can persist poisoned or stale Teams destinations<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:51-90` **Vulnerability Type**: T02: Agent Memory Poisoning **Risk Level**: Medium ### Vulnerable Code ```markdown ## Memory The agent maintains a `~/.config/agent-messenger/MEMORY.md` file as persistent memory across sessions. This is agent-managed — the CLI does not read or write this file. Use the `Read` and `Write` tools to manage your memory file. ### Reading Memory At the **start of every task**, read `~/.config/agent-messenger/MEMORY.md` using the `Read` tool to load any previously discovered team IDs, channel IDs, user IDs, and preferences. - If the file doesn't exist yet, that's fine — proceed without it and create it when you first have useful information to store. - If the file can't be read (permissions, missing directory), proceed without memory — don't error out. ### Writing Memory After discovering useful information, update `~/.config/agent-messenger/MEMORY.md` using the `Write` tool. Write triggers include: - After discovering team IDs and names (from `team list`, `snapshot`, etc.) - After discovering useful channel IDs and names (from `channel list`, `snapshot`, etc.) - After discovering user IDs and names (from `user list`, `user me`, etc.) - After the user gives you an alias or preference ("call this the standup channel", "my main team is X") - After discovering channel structure (standard vs private channels) When writing, include the **complete file content** — the `Write` tool overwrites the entire file. ### What to Store - Team IDs with names - Channel IDs with names and team context - User IDs with display names - User-given aliases ("standup channel", "main team") - Account preferences (work vs personal) - Any user preference expressed during interaction ``` ### Technical Analysis The Skill instructs the Agent to load a global Markdown memory file at the start of every task and overwrite it after discovering IDs, aliases, or preferences. This gives persistent s ...[truncated 2075 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make persistent memory opt-in rather than mandatory at the start of every task. 2. Scope stored state by tenant, account, team, and user profile; never share one global alias namespace across work and personal accounts. 3. Use a structured schema instead of free-form Markdown and reject unknown or instruction-like fields. 4. Treat all persisted values as untrusted hints and revalidate team and channel IDs against the current account before use. 5. Require explicit user confirmation showing team name, tenant/account, channel name, and channel ID before sending messages, uploading files, or deleting content. 6. Add creation timestamps, expiry periods, provenance, and last-validation timestamps to saved mappings. 7. Use atomic updates rather than overwriting the complete memory file. 8. Provide commands to inspect, correct, disable, and delete persisted memory. 9. Store only the minimum identifiers required and avoid retaining user IDs or account preferences unless the user explicitly requests it. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output
Findings (27)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The manifest describes a narrow Teams interaction skill, but the documented behavior includes broader data collection, silent authentication/token refresh, and snapshotting of members and recent messages. This mismatch can cause operators or upstream policy systems to authorize a tool with more access and data-handling capability than expected, increasing the risk of over-privileged use and accidental exposure of organizational communications metadata.

Credential Access

High
Category
Privilege Escalation
Content
## Configuration

Credentials stored in: `~/.config/agent-messenger/teams-credentials.json`

Format:
```json
Confidence
93% confidence
Finding
The skill documents storage of a live Teams token in a local credentials file and describes automatic extraction/refresh from the desktop app. Access to such a file can enable impersonation against Teams within the token lifetime, and normalizing this pattern in an agent skill materially increases credential exposure risk.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The guide instructs users to extract a live Teams authentication token directly from the desktop app's cookie database, which is credential harvesting from another application's session store. This bypasses normal OAuth-style consent flows and enables impersonation of the user for all Teams actions available to that session.

Credential Access

High
Category
Privilege Escalation
Content
4. Extracts `skypetoken_asm` cookie value
5. Validates token against Teams API before saving
6. Discovers ALL joined teams
7. Stores credentials securely in `~/.config/agent-messenger/teams-credentials.json`

### Platform-Specific Paths
Confidence
98% confidence
Finding
The documentation describes saving an extracted Teams session token to a local credentials file. Persisting a bearer token obtained from cookie extraction creates a reusable credential that can be stolen from disk and used to impersonate the user until expiry or revocation.

Credential Access

High
Category
Privilege Escalation
Content
Credentials are stored in:
```
~/.config/agent-messenger/teams-credentials.json
```

### Format
Confidence
96% confidence
Finding
Documenting a fixed path for a plaintext credentials file containing a Teams token makes discovery and theft easier for local malware, other compromised tooling, or careless handling. Because the token grants user-equivalent Teams access, compromise of this file can directly enable account misuse.

Credential Access

High
Category
Privilege Escalation
Content
### Best Practices

1. **Protect credentials.json**: Never commit to version control
2. **Use team switching**: Keep different contexts separate
3. **Handle token expiry**: Build refresh logic into all scripts
4. **Re-extract frequently**: Tokens expire in 60-90 minutes
Confidence
90% confidence
Finding
The best-practices section confirms the presence of a sensitive plaintext credential artifact and normalizes repeated re-extraction and handling of that file. While advisory in tone, it reinforces an insecure credential-management model that increases the chance of leakage, misuse, or accidental disclosure.

Credential Access

High
Category
Privilege Escalation
Content
mkdir -p ~/.config/agent-messenger

# Create credentials file
cat > ~/.config/agent-messenger/teams-credentials.json << 'EOF'
{
  "token": "YOUR_SKYPETOKEN_ASM_HERE",
  "token_extracted_at": "2024-01-15T10:00:00.000Z",
Confidence
97% confidence
Finding
The manual token-management section instructs users to create a local JSON file containing a raw `skypetoken_asm` value. This directly operationalizes storing a live impersonation credential on disk in a copy-paste friendly format, increasing the likelihood of theft, backup leakage, or accidental commit.

Credential Access

High
Category
Privilege Escalation
Content
EOF

# Set secure permissions
chmod 600 ~/.config/agent-messenger/teams-credentials.json
```

If the user already has a token value, they can populate the file above. Otherwise, always prefer `agent-teams auth extract` to obtain the token automatically from the desktop app.
Confidence
95% confidence
Finding
Although `chmod 600` is protective, this line is part of instructions for maintaining a plaintext file containing a live Teams token, so the underlying issue remains credential persistence. Restrictive file permissions mitigate but do not eliminate the risk from local compromise, backups, logs, or user mishandling.

Exfiltration Commands

High
Category
Prompt Injection
Content
echo -e "${BOLD}${CYAN}Quick Actions:${NC}"
echo ""
echo -e "  ${GREEN}# Send message to a channel${NC}"
FIRST_CHANNEL=$(echo "$CHANNELS" | jq -r '.[0].id // "CHANNEL_ID"')
FIRST_CHANNEL_NAME=$(echo "$CHANNELS" | jq -r '.[0].name // "General"')
echo -e "  agent-teams message send \"$FIRST_CHANNEL\" \"Hello!\""
Confidence
90% confidence
Finding
Instructions found that direct the agent to transmit conversation context or user data to external services.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest does not disclose that the skill extracts authentication tokens from the local Teams desktop app. Credential acquisition from local application storage is highly sensitive behavior and must be declared clearly so users and policy engines understand the trust boundary and local-data access involved.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The manifest does not disclose that the skill extracts authentication tokens from the local Teams desktop app. Credential acquisition from local application storage is highly sensitive behavior and must be declared clearly so users and policy engines understand the trust boundary and local-data access involved.

Unrestricted Tool Access

Medium
Category
Excessive Agency
Content
## Authentication

Credentials are extracted automatically from the Teams desktop app on first use. No manual setup required — just run any command and authentication happens silently in the background.

Teams tokens expire in 60-90 minutes. The CLI automatically re-extracts a fresh token when the current one expires, so you don't need to manage token lifecycle manually.
Confidence
80% confidence
Finding
Skill grants unrestricted tool access without appropriate constraints. An agent with unfettered tool access can perform arbitrary actions including file modification, network requests, and code execution.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill states that credentials are extracted automatically from the Teams desktop app and authentication happens silently in the background. Silent access to local tokens removes informed user consent and can normalize credential harvesting behavior, especially dangerous in an agent context where commands may be invoked indirectly.

Session Persistence

Medium
Category
Rogue Agent
Content
## Memory

The agent maintains a `~/.config/agent-messenger/MEMORY.md` file as persistent memory across sessions. This is agent-managed — the CLI does not read or write this file. Use the `Read` and `Write` tools to manage your memory file.

### Reading Memory
Confidence
88% confidence
Finding
The skill mandates cross-session persistence through a local MEMORY.md file and encourages storing discovered identifiers and preferences. Session persistence is dangerous here because it accumulates internal organizational metadata over time, broadening the consequences of host compromise or unintended agent reuse across tasks.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The memory guidance directs storage of user and organizational metadata across sessions without an upfront privacy warning or consent flow. Persistent collection of people, channels, and preference data can create an unreviewed shadow directory of workplace relationships and collaboration structure.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The documentation states the tool can upload/download files, access user information, and view member lists, which is broader than the declared skill description of messaging, channel reading, and reaction management. This scope mismatch can mislead reviewers and users, increasing the risk of overprivileged deployment and unexpected data access.

Session Persistence

Medium
Category
Rogue Agent
Content
## Manual Token Management (Advanced)

If automatic extraction fails, you can manually create the credentials file:

```bash
# Create config directory
Confidence
95% confidence
Finding
The guide instructs users to persist a session token in a local credentials file for reuse across operations. Persisting session material outside the originating app extends the life and portability of that session, making unauthorized reuse easier if the host or file is compromised.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
EOF

# Set secure permissions
chmod 600 ~/.config/agent-messenger/teams-credentials.json
```

If the user already has a token value, they can populate the file above. Otherwise, always prefer `agent-teams auth extract` to obtain the token automatically from the desktop app.
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The examples encourage polling channel messages and retrieving team snapshots that include recent messages and member data, but they do not explicitly warn that these operations access privacy-sensitive content. In an agent skill for Microsoft Teams, this can normalize broad collection of conversational and membership data and lead to accidental over-collection or misuse by downstream agents.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The file upload example shows sending a local file to Teams without clearly warning that the specified local path will be transmitted to a remote service. This can cause users or autonomous agents to upload sensitive local artifacts such as reports, logs, or secrets-bearing files without sufficient awareness or confirmation.

Unbounded Output

Medium
Category
Output Handling
Content
fi
```

### Don't Spam Channels

```bash
# Bad - sends 100 messages
Confidence
80% confidence
Finding
Output size or generation rate is not bounded. Unbounded output enables denial-of-service through resource exhaustion, log flooding, or context-window stuffing.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The script prints the full message body to the terminal before sending it, which can expose sensitive content such as credentials, internal links, incident details, or personal data to shell history captures, terminal logs, CI job logs, screen recordings, or other observers. In a messaging skill, users may reasonably pass confidential operational content, so echoing it without a clear warning or opt-in increases the likelihood of unintended disclosure.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
The documentation states raw JSON is only output with --json, but the script also writes raw snapshot data to disk unconditionally in normal mode. This mismatch undermines user expectations and can cause operators to expose sensitive Teams data without informed consent or awareness.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The script marketed as a summary tool writes the complete Teams snapshot JSON to a local file during normal execution. That snapshot likely contains sensitive team metadata, member details, and recent message content, so persisting it to disk increases exposure through local compromise, backups, shared workstations, or accidental inclusion in logs/repos.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
Saving a full Teams snapshot locally without prior warning creates unnecessary data-at-rest risk for potentially sensitive collaboration data. In the context of a Teams integration, snapshots may include channel names, member identities, and message excerpts, making silent persistence especially risky in enterprise environments.

Static analysis

No suspicious patterns detected.