Back to skill

Security audit

Slk

Security checks for vulnerabilities and agentic risk

Overview

This Slack skill is transparent about acting as your user, but it uses local Slack session credentials and stores a session token in a way that needs careful review before installation.

Install only if you intentionally want an agent-capable CLI to read and write Slack as your own user. Prefer one-time Keychain approval over 'Always Allow', avoid shared or managed machines, review the exact npm version before installing, and treat the token cache as sensitive credential material.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (4)

T01 · Skill Instruction Hijacking

Error
Location
AGENTS.md:99
Finding

Repository Instructions Direct Agents to Publish Code and Modify External Skill State

Content
View full analysis
.npmrc npm publish rm .npmrc # Clean up — don't commit the token! ``` The `NPM_PUBLISH_TOKEN` env var is set in `~/.local/keys/env.sh`. ### 8. Update Local Moltbot Skill ```bash cp SKILL.md ~/moltbot/skills/slk/SKILL.md ``` ``` `CLAUDE.md:15-28`: ```markdown ## Adding a Feature 1. Add function in `src/commands.js` (export async) 2. If new API needs POST → add to `writeMethods` in `src/api.js` 3. Add case + alias in `bin/slk.js` switch block 4. Add to HELP string in `bin/slk.js` 5. Update `README.md` (commands table, examples, flags if any) 6. Update `SKILL.md` (commands list) 7. `npm version patch --no-git-tag-version` 8. `git add -A && git commit -m "feat: ..." && git push` 9. `echo "//registry.npmjs.org/:_authToken=${NPM_PUBLISH_TOKEN}" > .npmrc && npm publish && rm .npmrc` 10. `cp SKILL.md ~/moltbot/skills/slk/SKILL.md` ``` `CLAUDE.md:48-50`: ```markdown ## npm Publish Token `NPM_PUBLISH_TOKEN` env var from `~/.local/keys/env.sh`. Use `.npmrc` trick (create before publish, delete after). ``` ### Technical Analysis The repository-level agent instructions turn an ordinary local development task into a mandatory release workflow. They direct an AI coding agent to: - Commit all working-tree changes. - Push changes to a remote Git repository. - Retrieve or use a locally stored npm publication credential. - Publish the package to npm. - Copy `SKILL.md` into an external agent Skill directory. These operations are not necessary for implementing, testing, or auditing a local code change. In particular, package publication and ...[truncated 1700 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/auth.js:197
Finding

Slack User Session Token Is Cached in Plaintext Without Enforced Private Permissions

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/auth.js:66
Finding

Predictable Shared Temporary Files Are Used for Slack Authentication Material

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:6
Finding

Credential-Handling Package Is Installed and Executed Without Version or Integrity Pinning

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (50)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · AGENTS.md (reported line 12)May include surrounding context.

md
├── bin/slk.js          # CLI entry point — command routing, help text, aliases
├── src/
│   ├── api.js          # Slack API wrapper — fetch, auth headers, pagination
│   ├── auth.js         # Credential extraction — Keychain, LevelDB, token cache
│   ├── commands.js     # All command implementations (read, send, saved, etc.)
│   └── drafts.js       # Draft-specific commands (create, list, drop)
├── package.json        # Version, bin mapping, metadata

Credential Access

High
Category
Privilege Escalation
Confidence
89% confidence
Finding

The documentation instructs creating a project-local .npmrc containing ${NPM_PUBLISH_TOKEN}, which places sensitive publishing credentials into a file in the working directory. Even though it is deleted afterward, this creates exposure risk through shell history, accidental commit, backup/indexing tools, permissive filesystem permissions, or interrupted execution leaving the file behind.

Content

Scanner excerpt · AGENTS.md (reported line 102)May include surrounding context.

7. Publish to npm

bash
# Create .npmrc with publish token
echo "//registry.npmjs.org/:_authToken=${NPM_PUBLISH_TOKEN}" > .npmrc
npm publish
rm .npmrc   # Clean up — don't commit the token!

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · AGENTS.md (reported line 103)May include surrounding context.

bash
# Create .npmrc with publish token
echo "//registry.npmjs.org/:_authToken=${NPM_PUBLISH_TOKEN}" > .npmrc
npm publish
rm .npmrc   # Clean up — don't commit the token!

Credential Access

High
Category
Privilege Escalation
Confidence
86% confidence
Finding

Stating that NPM_PUBLISH_TOKEN is set in ~/.local/keys/env.sh discloses the likely location of locally stored secrets. In context, this gives an attacker or unsafe automation a concrete file to target for credential harvesting if they gain any file-read capability.

Content

Scanner excerpt · AGENTS.md (reported line 105)May include surrounding context.

Create .npmrc with publish token

echo "//registry.npmjs.org/:_authToken=${NPM_PUBLISH_TOKEN}" > .npmrc npm publish rm .npmrc # Clean up — don't commit the token!

text

The `NPM_PUBLISH_TOKEN` env var is set in `~/.local/keys/env.sh`.

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

The one-liner repeats the risky pattern of creating a token-bearing .npmrc inline and publishing immediately. One-line chained commands are more dangerous because failures can be overlooked, cleanup may not occur as intended, and users may run them without reviewing the secret-handling implications.

Content

Scanner excerpt · AGENTS.md (reported line 125)May include surrounding context.

... make changes ...

npm version patch --no-git-tag-version git add -A && git commit -m "feat: description" && git push echo "//registry.npmjs.org/:_authToken=${NPM_PUBLISH_TOKEN}" > .npmrc && npm publish && rm .npmrc cp SKILL.md ~/moltbot/skills/slk/SKILL.md

text

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

The documentation instructs creating a .npmrc file containing ${NPM_PUBLISH_TOKEN} and then publishing. Even though it deletes the file afterward, writing a live registry token to disk risks credential exposure through shell history, process observation, accidental commits, backup/sync tooling, or failure before cleanup; in this skill context, the same file also documents other sensitive Slack auth material, which increases the danger of normalizing credential handling in agent-accessible instructions.

Content

Scanner excerpt · CLAUDE.md (reported line 25)May include surrounding context.

md
6. Update `SKILL.md` (commands list)
7. `npm version patch --no-git-tag-version`
8. `git add -A && git commit -m "feat: ..." && git push`
9. `echo "//registry.npmjs.org/:_authToken=${NPM_PUBLISH_TOKEN}" > .npmrc && npm publish && rm .npmrc`
10. `cp SKILL.md ~/moltbot/skills/slk/SKILL.md`

## Testing

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

This line explicitly documents that NPM_PUBLISH_TOKEN is sourced from ~/.local/keys/env.sh and recommends the .npmrc token-writing trick. That materially increases exposure by revealing secret storage location and a workflow that persists credentials to disk, which could be abused by an agent or attacker with file access to locate and misuse publishing credentials.

Content

Scanner excerpt · CLAUDE.md (reported line 50)May include surrounding context.

md
## npm Publish Token

`NPM_PUBLISH_TOKEN` env var from `~/.local/keys/env.sh`. Use `.npmrc` trick (create before publish, delete after).

Credential Access

High
Category
Privilege Escalation
Confidence
98% confidence
Finding

This section states that slk uses credentials already stored by the Slack desktop app and describes Keychain access. Accessing and reusing local session credentials is a high-risk capability because compromise of the tool, its execution environment, or an attached agent effectively grants access as the user to Slack without a normal authorization flow.

Content

Scanner excerpt · README.md (reported line 165)May include surrounding context.

md
`slk` uses the credentials already stored by the Slack desktop app. No OAuth flows, no manual token management.

### Keychain access prompt

On first run, macOS will show a Keychain dialog asking whether to allow access to "Slack Safe Storage":

Credential Access

High
Category
Privilege Escalation
Confidence
99% confidence
Finding

The README details direct decryption of Slack cookies and extraction of xoxc- session tokens from LevelDB, including fallback parsing methods. This is effectively credential harvesting from local application storage; in the context of an agent skill, it materially increases the blast radius because any agent-command execution can obtain reusable session artifacts and act as the user.

Content

Scanner excerpt · README.md (reported line 177)May include surrounding context.

md
### How it works

1. **Cookie decryption** — Reads the encrypted `d` cookie from Slack's SQLite cookie store (`Cookies` file). Decrypts it using the "Slack Safe Storage" key from the macOS Keychain via PBKDF2 + AES-128-CBC. Supports both direct-download and Mac App Store keychain account names.

2. **Token extraction** — Scans Slack's LevelDB storage (`Local Storage/leveldb/`) for `xoxc-` session tokens. Uses both direct regex scanning and a Python fallback for Snappy-compressed entries. The Slack data directory is auto-detected (direct download or App Store sandbox).

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

The notes confirm the tool depends on Keychain access and Slack storage paths, reinforcing that host secret access is a core capability. In a personal agent skill, that makes the skill substantially more dangerous than a normal Slack client because it couples messaging actions with local credential extraction and filesystem inspection.

Content

Scanner excerpt · README.md (reported line 272)May include surrounding context.

md
## Notes

- **macOS only** — uses Keychain and Electron storage paths specific to macOS.
- **Both Slack variants supported** — works with the direct download (`~/Library/Application Support/Slack/`) and the Mac App Store version (`~/Library/Containers/com.tinyspeck.slackmacgap/.../Slack/`). The correct path is auto-detected at runtime.
- **Slack desktop app required** — must be installed and logged in. The app does not need to be running for cached tokens.
- **Zero dependencies** — uses only Node.js built-in modules (`crypto`, `fs`, `child_process`, `fetch`).

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The description presents the skill as a normal Slack interaction tool, but the auth model relies on extracting session credentials from Slack desktop storage, reading Keychain material, and recovering user auth tokens. That is security-sensitive credential access behavior and materially riskier than a typical Slack client, so understating it can mislead users and policy systems into granting access they would otherwise deny.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The description presents the skill as a normal Slack interaction tool, but the auth model relies on extracting session credentials from Slack desktop storage, reading Keychain material, and recovering user auth tokens. That is security-sensitive credential access behavior and materially riskier than a typical Slack client, so understating it can mislead users and policy systems into granting access they would otherwise deny.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · AGENTS.md (reported line 140)May include surrounding context.

If auth fails (token rotated, Slack logged out):

bash
rm ~/.local/slk/token-cache.json
slk auth

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
85% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · SKILL.md (reported line 64)May include surrounding context.

If auth fails (token rotated, Slack logged out):

bash
rm ~/.local/slk/token-cache.json
slk auth

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

The skill's documented reliance on Keychain and Electron storage paths indicates credential-access behavior tied to recovering Slack session secrets. Access to local secret stores and session material can enable account impersonation beyond the immediate task and expands the blast radius if the skill or surrounding agent is abused.

Content

Scanner excerpt · SKILL.md (reported line 93)May include surrounding context.

md
## Limitations

- **macOS only** — uses Keychain + Electron storage paths
- **Session-based** — acts as your user, not a bot. Be mindful of what you send
- **Draft drop** may fail with `draft_has_conflict` if Slack has that conversation open
- **Session token** expires on logout — keep Slack app running or rely on cached token

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The file’s own header explicitly states it extracts Slack session credentials from macOS Keychain, cookies, and LevelDB rather than using normal Slack APIs or an expected OAuth flow. This is highly inconsistent with the declared skill purpose of reading and sending Slack messages via a CLI and enables covert account/session takeover using locally harvested secrets.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
99% confidence
Finding

The comment documents a workflow for recovering Slack credentials from Keychain, encrypted cookies, and LevelDB, which directly maps to credential access behavior. In this skill context, that capability is unrelated to the stated benign messaging task and indicates deliberate design for unauthorized secret extraction.

Content

Scanner excerpt · src/auth.js (reported line 4)May include surrounding context.

js
/**
 * Slack auth — extracts session credentials from the Slack desktop app on macOS.
 *
 * 1. Keychain → "Slack Safe Storage" password
 * 2. Cookies SQLite → encrypted `d` cookie → AES-128-CBC decrypt
 * 3. LevelDB files → `xoxc-` token (string scan)
 */

Credential Access

High
Category
Privilege Escalation
Confidence
99% confidence
Finding

The getKeychainKey function actively queries macOS Keychain for Slack Safe Storage secrets needed to decrypt local Slack data. Accessing these secrets enables reconstruction of authenticated session material and can lead to full Slack account/session compromise.

Content

Scanner excerpt · src/auth.js (reported line 45)May include surrounding context.

js
let cachedCreds = null;

function getKeychainKey() {
  // Mac App Store Slack uses account "Slack App Store Key", direct download uses "Slack" or "Slack Key"
  const accounts = SLACK_DIR === SLACK_DIR_APPSTORE
    ? ["Slack App Store Key", "Slack Key", "Slack"]

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This code enumerates Keychain entries, decrypts Slack cookies, scans local LevelDB data for xoxc tokens, and assembles reusable credentials. That is credential harvesting behavior, not normal client-side Slack interaction, and it can grant unauthorized access to a user’s Slack workspace and data.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill accesses macOS Keychain and Slack local stores to obtain authentication material without any user-facing warning, prompt, or clear necessity for the advertised function. Hidden collection of session credentials is especially dangerous here because the skill context suggests ordinary Slack assistance, making users less likely to suspect credential theft.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
92% confidence
Finding

The error path confirms the program expects and depends on finding Slack secrets in Keychain, reinforcing that credential access is a core feature rather than incidental behavior. This supports unauthorized secret harvesting and demonstrates intent to obtain protected authentication material from the host.

Content

Scanner excerpt · src/auth.js (reported line 62)May include surrounding context.

js
} catch {}
  }

  console.error("Could not find Slack Safe Storage key in Keychain.");
  process.exit(1);
}

Credential Access

High
Category
Privilege Escalation
Confidence
99% confidence
Finding

This code derives an AES key from the Keychain secret and uses it to decrypt Slack’s encrypted cookie data, directly converting protected local state into reusable authentication material. That is a concrete credential-access primitive that can bypass expected user authentication boundaries and enable account takeover.

Content

Scanner excerpt · src/auth.js (reported line 85)May include surrounding context.

js
}

    const data = encrypted.subarray(3);
    const aesKey = pbkdf2Sync(getKeychainKey(), "saltysalt", 1003, 16, "sha1");
    const iv = Buffer.alloc(16, " ");

    // Decrypt via openssl using spawnSync for clean binary output

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code writes a harvested Slack token to a local JSON cache without any visible consent flow, protection checks, or indication of file permissions hardening. Persisting bearer tokens on disk increases the blast radius of compromise because any local process or user with access to that file may reuse the token.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

After extracting credentials, the code silently sends them to Slack’s API to test validity, which confirms account access without informing the user. Even though the destination is Slack, transmitting stolen or undisclosed credentials operationalizes the compromise and verifies that the harvested secrets can be abused.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · AGENTS.md (reported line 24)May include surrounding context.

md
## The Full Loop: Adding a New Feature

### 1. Write the Code

Add your command implementation in `src/commands.js`:
- Export an async function

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
src/auth.js:54