Back to skill

Security audit

Agent Teams

Security checks for vulnerabilities and agentic risk

Overview

This Teams skill is review-worthy because it silently extracts Teams session cookies, stores a usable token locally, and has inconsistent install guidance, even though its core Teams purpose is coherent.

Install only after reviewing the credential model. This skill can act as you in Teams, reads Teams desktop cookie storage, stores a plaintext token locally, may retain team/user/channel identifiers across sessions, and includes templates that save or print Teams data. Verify the intended package is agent-messenger, avoid the conflicting agent-teams install command, and do not use it on highly sensitive Teams accounts or shared/automated machines unless you accept those risks.

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/monitor-channel.sh:171
Finding
Incorrect and Unpinned Package Installation Creates Dependency-Confusion Risk<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:8-13`; `templates/monitor-channel.sh:171-176`; `templates/post-message.sh:155-160`; `templates/team-summary.sh:43-47` **Vulnerability Type**: Supply-chain dependency confusion and unpinned dependency installation **Risk Level**: High ### Vulnerable Code The Skill manifest declares `agent-messenger` as the package providing the `agent-teams` executable: ```yaml metadata: openclaw: requires: bins: - agent-teams install: - kind: node package: agent-messenger bins: [agent-teams] ``` However, all three runnable templates recommend installing a different package name. For example: ```bash if ! command -v agent-teams &> /dev/null; then echo -e "${RED}Error: agent-teams not found${NC}" echo "" echo "Install it with:" echo " bun install -g agent-teams" exit 1 fi ``` The same conflicting installation instruction appears in: ```bash echo " bun install -g agent-teams" ``` The project documentation itself states that `agent-teams` is not the npm package name and warns against installing it: ```markdown **`agent-teams` is NOT the npm package name.** The npm package is `agent-messenger`. **NEVER run `bunx agent-teams`** — it will fail or install a wrong package since `agent-teams` is not the npm package name. ``` ### Technical Analysis The templates contradict the package identity declared by the manifest and documented in `SKILL.md`. A user who runs a template without the expected executable installed is instructed to globally install `agent-teams`, even though the expected package is `agent-messenger`. This creates a dependency-confusion or package-substitution opportunity. The audit does not establish that any currently published package is malicious; the vulnerability is that an unintended package can occupy the recommended name and be executed as a trusted Teams client. Neither installation path pins a reviewed package version or integrit ...[truncated 1507 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace every incorrect installation instruction with the verified package identity: ```bash bun install -g agent-messenger@<reviewed-version> ``` 2. Pin the dependency to a specific reviewed version rather than accepting the latest release. 3. Use lockfiles and registry integrity hashes where the runtime supports them. 4. Verify that the installed executable resolves to the expected package before requesting authentication. 5. Remove duplicated installation logic from templates and maintain one authoritative installation procedure. 6. Include the external CLI implementation in the security review, especially its cookie access, credential storage, and network destinations. 7. Prefer a signed release artifact or trusted package registry namespace with publisher verification. 8. Add an automated test that fails if templates reference a package name different from the manifest. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
references/authentication.md:40
Finding
Silent Extraction and Plaintext Storage of a Broadly Privileged Teams Session Token<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:25-35`; `references/authentication.md:40-53`; `references/authentication.md:118-143`; `references/authentication.md:243-252`; `references/authentication.md:275-287` **Vulnerability Type**: Excessive credential access and violation of least privilege **Risk Level**: High ### Vulnerable Code and Instructions The Skill instructs the CLI to authenticate silently: ```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. ``` The authentication guide describes direct access to the Teams cookie database: ```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` ``` The credential is stored as plaintext JSON: ```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" } } } ``` The documented troubleshooting procedure recommends expanding terminal permissions: ```markdown ### "Permission denied reading ...[truncated 3170 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace cookie-database scraping with Microsoft's documented OAuth authorization flow. 2. Request only the scopes needed for the selected operation and resource. 3. Require explicit user consent before authentication, token refresh, team discovery, or account switching. 4. Do not silently authenticate as a side effect of ordinary commands. 5. Never recommend granting the terminal Full Disk Access; fail safely if the required resource cannot be accessed with narrowly scoped permissions. 6. Store refresh and access tokens in the operating system's credential vault rather than a plaintext JSON file. 7. Restrict operations to user-approved teams and channels instead of automatically discovering and retaining all joined teams. 8. Display the active account, destination team, requested action, and privilege scope before sensitive operations. 9. Provide token revocation, logout, expiry, and audit-log controls. 10. Review and verify all network destinations used by the external CLI before deployment. ]]>

T02 · Agent Memory Poisoning

Warning
Location
SKILL.md:55
Finding
Mandatory Persistent Memory Stores Organizational Identifiers and Creates a Cross-Session Influence Channel<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:55-105` **Vulnerability Type**: Persistent memory poisoning and unbounded organizational metadata retention **Risk Level**: Medium ### Vulnerable Instructions The Skill requires persistent memory to be read at the start of every task: ```markdown ### 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. ``` It also mandates updates after discovering information or receiving preferences: ```markdown ### 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. ``` The retained data includes organizational topology and user-derived preferences: ```markdown ### 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 memory file is a persistent cross-session state channel. The instructions require it to be ...[truncated 1925 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make persistent memory opt-in rather than mandatory. 2. Ask for explicit user approval before storing team, channel, user, account, or preference data. 3. Isolate memory by tenant, account, and user profile. 4. Store only inert, schema-validated identifiers; do not persist arbitrary instructions or behavioral rules as preferences. 5. Record provenance, creation time, last verification time, and expiry for every entry. 6. Revalidate account, team, and channel identifiers before any message, upload, deletion, or other consequential action. 7. Require destination confirmation when remembered data crosses accounts or has not been verified recently. 8. Apply restrictive file permissions and integrity protection to the memory file. 9. Provide commands to inspect, remove, and disable retained memory. 10. Define a short retention period and automatically delete stale entries. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
templates/team-summary.sh:199
Finding
Teams Messages, Member Data, and Channel Metadata Are Persisted or Logged in Plaintext<![CDATA[ ## Vulnerability Details **File Location**: `templates/team-summary.sh:91-109`, `templates/team-summary.sh:151-180`, `templates/team-summary.sh:199-201`; `templates/post-message.sh:214-218`; `templates/monitor-channel.sh:143-153` **Vulnerability Type**: Plaintext sensitive-data persistence, log disclosure, and unsafe terminal rendering **Risk Level**: Medium ### Vulnerable Code The summary template retrieves a comprehensive snapshot: ```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 ``` It prints member email addresses and recent message content: ```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)${NC}" echo "" if [ "$MESSAGE_COUNT" -gt 0 ]; then echo -e "${BOLD}${CYAN}Latest Messages:${NC}" echo "$MESSAGES" | jq -r ' .[0:5] | .[] | " [#\(.channel_name)] \(.author): \(.content[0:50])\(if (.content | length) > 50 then "..." else "" end)" ' echo "" fi ``` It then writes the complete raw snapshot to the current directory without establishing restrictive permissions: ```bash SNAPSHOT_FILE="team-snapshot-$(date +%Y%m%d-%H%M%S).json" echo "$SNAPSHOT" > "$SNAPSHOT_FILE" ...[truncated 3841 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not save a raw snapshot by default. 2. Require an explicit `--output` option and user confirmation before persisting Teams data. 3. Set restrictive permissions before file creation: ```bash umask 077 ``` 4. Create output files atomically with `mktemp` in a user-controlled secure directory. 5. Redact message bodies, member email addresses, user IDs, and private-channel details unless explicitly requested. 6. Add retention controls and securely delete temporary snapshots after use. 7. Avoid printing outgoing or incoming message content by default; provide a clearly documented verbose mode instead. 8. Replace `echo -e` for untrusted fields with safe rendering: ```bash printf '%s\n' "$CONTENT" ``` 9. Strip or encode terminal control characters before displaying remote content. 10. Warn users when output may be captured by CI logs, terminal recording, backups, or synchronization services. 11. Separate raw JSON export from human-readable summaries and apply least-data defaults to both modes. ]]>
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
96% confidence
Finding
The code is clearly Teams-related and does read channel/message data, so it partially aligns with the declared description. However, the declared purpose is a broad interaction summary focused on sending messages, reading channels, and managing reactions, while the actual code’s primary purpose is specifically long-running monitoring of a channel for new messages. It also performs authentication status inspection and automatic token refresh, which are undeclared capabilities. The commented-out auto-response example is not active and should not be counted. Overall, this is a meaningful description-behavior mismatch because the implemented behavior is narrower in some ways but also includes materially different operational capabilities not stated in the description.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The code clearly interacts with Microsoft Teams, so the general domain is accurate. However, the declared description suggests a broader capability set: send messages, read channels, and manage reactions. This code chunk only posts messages and, secondarily, lists channels to resolve a channel name to an ID. It does not implement reaction management at all. It also performs authentication status checks and token refresh operations, which are material operational capabilities not reflected in the description. Because the declared description overstates some implemented functions (reaction management) and omits the authentication/token-handling behavior, this is a description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
The declared description suggests a general Teams interaction skill focused on sending messages, reading channels, and managing reactions. The code instead implements a reporting/export utility: it checks authentication, refreshes tokens, retrieves a comprehensive team snapshot, summarizes channels/members/recent activity, and writes the raw snapshot to disk. While reading Teams data is consistent in a broad sense, the primary purpose is team summarization rather than interactive messaging. Also, key declared capabilities are absent in the code: it does not actually send messages or manage reactions; those appear only as printed example commands. The undeclared local snapshot export and auth-refresh behavior are additional capabilities beyond the description.

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, which represents credential material that can be stolen by local compromise, logs, backups, or overly broad tooling access. Even with 0600 permissions, plaintext bearer tokens on disk materially raise account takeover risk on multi-tool agent systems.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
Accessing local Teams cookies to recover authentication tokens is a credential-access behavior not justified by the stated messaging functionality. It bypasses normal consent and token issuance controls, and if abused gives the skill the same effective access as the signed-in user.

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 guide describes extracting a live Teams session token and storing it in `~/.config/agent-messenger/teams-credentials.json`. Persisting a bearer token in plaintext creates a reusable credential target for malware, local attackers, or accidental disclosure, and the token grants direct access as the user until expiry.

Credential Access

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

### Format
Confidence
95% confidence
Finding
This section documents the location of a plaintext credential store containing the Teams token. Publicly documenting the path and structure lowers the barrier for theft by other local processes or users and normalizes insecure storage of a sensitive session credential.

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
89% confidence
Finding
The best-practices section confirms the existence of `credentials.json` as a sensitive artifact and instructs users to protect it, which indirectly acknowledges the skill relies on a locally stored reusable secret. While the line itself is advisory, in context it reinforces an insecure credential model based on harvested bearer tokens.

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 instructions tell users to create a JSON file containing `YOUR_SKYPETOKEN_ASM_HERE`, which is direct handling of a live bearer credential. Encouraging manual placement of a session token into a file substantially increases the chance of leakage, misuse, or copying into unsafe environments.

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
93% confidence
Finding
Although the line sets restrictive permissions, it is still part of a workflow that persists a sensitive Teams token in a predictable local file. The permissions reduce exposure but do not address theft by the same user context, malware, backups, logs, or accidental file handling.

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
95% confidence
Finding
Automatic credential/token extraction from the Teams desktop app is highly privacy- and security-sensitive behavior. Failing to disclose it in the manifest can mislead users into invoking a skill that accesses authentication material and account context they did not knowingly approve.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
Automatic credential/token extraction from the Teams desktop app is highly privacy- and security-sensitive behavior. Failing to disclose it in the manifest can mislead users into invoking a skill that accesses authentication material and account context they did not knowingly approve.

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
84% confidence
Finding
The phrase 'just run any command' combined with silent authentication encourages broad invocation without least-privilege guardrails or command-risk distinctions. In practice, low-friction execution can cause an agent to trigger sensitive operations like token extraction, snapshots, or message/file actions without meaningful user awareness.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
Silent automatic credential extraction from a desktop app without a prominent warning undermines informed consent and can lead to unexpected access to a user's Teams account. In an agent setting, this is particularly dangerous because simply running a seemingly harmless command can trigger access to authentication artifacts and account data.

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
86% confidence
Finding
Cross-session persistence of discovered teams, channels, users, and preferences creates a durable knowledge base that may outlive the user's intent and expand the blast radius of later compromise. In agent contexts, persistent memory can also silently influence future actions using stale or sensitive workspace metadata.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The instructions encourage persistent storage of team IDs, channel IDs, user IDs, names, and preferences across sessions without an explicit privacy warning or retention policy. Persistent identity/workspace mapping can become sensitive organizational metadata and may be misused or exposed later.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The snapshot feature aggregates recent messages, member identities, and emails into machine-consumable JSON without an explicit privacy warning. This materially increases the risk of bulk collection, oversharing, or downstream exfiltration of organizational communications and directory data.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The documentation explicitly instructs the tool to locate the local Teams desktop data directory, read the Cookies SQLite database, and extract the `skypetoken_asm` session token. That is credential harvesting from another application's local storage and materially expands capability beyond ordinary Teams messaging, enabling account access as the user if the token is obtained or mishandled.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The file states the skill can upload/download files, access user information, and view team member lists, which exceeds the narrow manifest description of sending messages, reading channels, and managing reactions. Capability expansion increases the blast radius of compromise and suggests the skill may process more data than users expect.

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
91% confidence
Finding
The manual credential-file workflow establishes local session persistence by storing the token and metadata for reuse across operations. Persistent storage of a user session token increases the window for unauthorized reuse and makes compromise more durable than in-memory-only handling.

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.

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.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
The header and usage text describe the script as generating a summary, but its behavior also includes exporting the complete raw snapshot to disk. This mismatch can mislead users into running a broader data export than expected, undermining informed consent around sensitive Teams data handling.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The script marketed as a summary tool writes the full Teams snapshot to a local JSON file, which can include channel metadata, member identities, and recent message content. Persisting this raw dataset increases exposure beyond the immediate terminal output and creates a recoverable local artifact that may be accessed by other users, backups, or malware.

Static analysis

No suspicious patterns detected.