Back to skill

Security audit

X Bookmarks

Security checks for vulnerabilities and agentic risk

Overview

The skill is genuinely about X bookmark workflows, but it handles account credentials in ways that are overbroad or unsafe enough to require review before use.

Review this skill carefully before installing. Prefer the official X API path with read-only scopes, avoid `source .env.bird`, do not use `--print-token`, and do not grant browser-cookie access to an unpinned global `bird-cli` unless you have independently verified that package and accept the account-session risk.

Vulnerability Patterns
  • 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
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (5)

T08 · Insecure Dependencies

Error
Location
references/auth-setup.md:7
Finding

Unpinned Global Dependency Is Granted Access to Browser Session Credentials

Content
View full analysis

Vulnerability Details

File Location: references/auth-setup.md, lines 7-13
Vulnerability Type: Unsafe third-party dependency installation and privileged browser-cookie access
Risk Level: High

Vulnerable Code

bash
Easiest if you have bird installed (`npm i -g bird-cli`).

### A1. Chrome Cookie Extraction (Recommended)

```bash
bird --chrome-profile "Default" bookmarks --json
text

Equivalent unpinned installation and browser-cookie instructions also appear in `README.md` and `SKILL.md`.

### Technical Analysis

The Skill instructs users or agents to install the latest available `bird-cli` package globally without a pinned version, lockfile, integrity hash, or publisher verification. It then grants that executable access to a browser profile containing an authenticated X session.

Global installation increases the potential effect of a dependency compromise because package installation scripts and the resulting executable run with the user's privileges and affect system-wide user tooling. Browser-cookie extraction is particularly sensitive: a compromised or malicious package release could read and disclose reusable session credentials rather than merely retrieve bookmarks.

No evidence was found that the currently referenced package is malicious. The vulnerability is the unsafe trust and installation model combined with immediate access to high-value browser credentials.

### Attack Path

1. An attacker compromises the package publisher, registry account, or a future package release.
2. The user or agent runs `npm install -g bird-cli`, retrieving the unreviewed latest release.
3. Package installation hooks or the installed executable run with the user's local privileges.
4. The Skill invokes the executable with a Chrome or Firefox profile.
5. The compromised dependency reads X cookies or other accessible browser data and transmits them to the attacker.
6. The attacker reuses the stolen sessi
...[truncated 447 chars]
Remediation
View remediation

Remediation Suggestions

  • Pin bird-cli to a specifically reviewed version rather than installing the latest release.
  • Document the expected package publisher, source repository, package digest, and verification procedure.
  • Use a project-local installation with a committed lockfile instead of a global installation.
  • Disable dependency lifecycle scripts during installation where feasible.
  • Prefer the official OAuth API backend, which grants narrowly scoped tokens without exposing the browser cookie database to a third-party CLI.
  • If browser-cookie access remains supported, clearly warn users that the CLI receives account-equivalent session credentials.
  • Execute the CLI in a restricted environment with minimal filesystem and network access where practical.

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:85
Finding

Untrusted Environment File Is Executed as Shell Code

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 85-87
Vulnerability Type: Arbitrary command execution through unsafe shell sourcing
Risk Level: High

Vulnerable Code

bash
If user has a `.env.bird` file or env vars `AUTH_TOKEN`/`CT0`, source them first: `source .env.bird`

Technical Analysis

The source shell built-in executes a file in the current shell process. It does not restrict the file to passive environment-variable declarations. A .env.bird file may therefore contain command substitutions, function definitions, redirections, external command invocations, or arbitrary shell statements.

The instruction uses a relative path and does not require ownership, permission, content, or provenance validation. An agent following this instruction in an attacker-controlled repository or writable working directory could execute a malicious .env.bird before retrieving any bookmarks.

Attack Path

  1. An attacker places a .env.bird file in a repository, archive, or working directory processed by the agent.
  2. The file includes apparently legitimate token assignments followed by a shell payload, or embeds a payload in command substitution.
  3. The user requests bookmark retrieval.
  4. The agent follows the Skill instruction and executes source .env.bird.
  5. The payload runs in the current shell with the agent's or user's privileges.
  6. The payload can access local files, environment variables, credentials, and network resources available to that process.

Impact Assessment

Exploitation provides arbitrary command execution with the privileges of the process running the Skill. This may expose X credentials, API tokens, SSH keys, workspace data, and other user files. It may also allow modification of local files or installation of persistence if the affected account has sufficient permissions.

Remediation
View remediation

Remediation Suggestions

  • Do not use source to load credential files.
  • Parse the file as data and allow only the exact keys AUTH_TOKEN and CT0.
  • Reject shell metacharacters, command substitutions, additional keys, multiline values, and malformed assignments.
  • Resolve the credential file to an expected absolute path instead of using the current working directory.
  • Verify that the file is owned by the current user and is not group- or world-writable.
  • Store the file with mode 0600, or use the operating system's credential store instead.
  • Update all documentation to use the safe parser rather than advising direct shell evaluation.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/x_api_auth.py:35
Finding

OAuth Flow Requests Bookmark Write Access Despite Declared Read-Only Functionality

Content
View full analysis

Vulnerability Details

File Location: scripts/x_api_auth.py, line 35
Vulnerability Type: Excessive OAuth authorization scope
Risk Level: High

Vulnerable Code

python
SCOPES = "tweet.read users.read bookmark.read bookmark.write offline.access"

The Skill's declared API behavior is bookmark retrieval, and its security metadata describes X bookmark access as read-only. The implemented API fetcher performs only read requests.

Technical Analysis

The OAuth authorization request includes bookmark.write, although bookmark reading requires only the relevant read scopes. This violates least privilege and contradicts the Skill's declared remote permission model.

The inclusion of offline.access is functionally justified by documented automatic token refresh, but bookmark.write is not required by the implemented API backend. The documented unbookmark workflow uses the separate bird CLI rather than the OAuth API script.

Consequently, compromise or accidental disclosure of a generated token permits bookmark modification in addition to the advertised read-only access.

Attack Path

  1. The user runs x_api_auth.py and approves the requested OAuth scopes.
  2. X issues access and refresh tokens containing bookmark write authority.
  3. A token is disclosed through local file access, agent-visible output, logs, malware, or another compromised process.
  4. The attacker sends authenticated write or delete requests to the X API.
  5. The attacker alters or removes the victim's bookmarks even though the intended workflow only required reading them.

Impact Assessment

An attacker possessing the OAuth token can exercise the granted X permissions. In addition to reading the user's identity, tweets, and private bookmark collection as allowed by the scopes, the attacker may modify bookmark state. The refresh token can extend this exposure across access-token expiration until authorization is revoked or r ...[truncated 13 chars]

Remediation
View remediation

Remediation Suggestions

  • Change the default scope set to:
python
SCOPES = "tweet.read users.read bookmark.read offline.access"
  • Require a separate, explicit authorization flow before requesting bookmark.write.
  • Display the requested scopes to the user and explain why each scope is necessary.
  • Keep read-only and write-enabled tokens separate.
  • Add a regression test that rejects write scopes in the standard bookmark-fetching flow.
  • Update the security metadata and documentation so that declared and actual permissions remain consistent.
  • Advise existing users to revoke and reauthorize previously issued overprivileged tokens.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/x_api_auth.py:38
Finding

OAuth Client Secret Is Persisted Without Explicit Restrictive File Permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/x_api_auth.py, lines 38-46
Vulnerability Type: Insecure plaintext secret storage
Risk Level: Medium

Vulnerable Code

python
def save_config(client_id: str, client_secret: str = ""):
    TOKEN_DIR.mkdir(parents=True, exist_ok=True)
    config = {"client_id": client_id}
    if client_secret:
        config["client_secret"] = client_secret
    CONFIG_FILE.write_text(json.dumps(config, indent=2))
    print(f"Config saved to {CONFIG_FILE}")

By comparison, the token file is explicitly restricted elsewhere:

python
def save_tokens(tokens: dict):
    TOKEN_DIR.mkdir(parents=True, exist_ok=True)
    TOKEN_FILE.write_text(json.dumps(tokens, indent=2))
    os.chmod(TOKEN_FILE, 0o600)
    print(f"Tokens saved to {TOKEN_FILE}")

Technical Analysis

When a confidential OAuth application is used, save_config writes the client secret in plaintext to ~/.config/x-bookmarks/config.json. Unlike tokens.json, the configuration file is not explicitly changed to mode 0600.

Its accessibility therefore depends on the user's process umask and any pre-existing file permissions. write_text also does not guarantee secure atomic creation with a restrictive mode. If an existing file is overly permissive, rewriting it generally preserves that exposure.

Attack Path

  1. The user invokes the helper with --client-secret.
  2. The helper stores the supplied secret in config.json.
  3. The file is created or retained with permissions that allow another local account or process to read it.
  4. A local attacker reads the client ID and client secret.
  5. The attacker abuses the application credentials in OAuth operations supported by the provider and application configuration.

Impact Assessment

The direct impact is disclosure of the confidential OAuth application's client secret. The exact provider-side impact depends on the app configu ...[truncated 245 chars]

Remediation
View remediation

Remediation Suggestions

  • Avoid persisting the client secret when a public PKCE client is sufficient.
  • Store confidential client credentials in an operating-system keychain or dedicated secret manager.
  • Create ~/.config/x-bookmarks with mode 0700.
  • Create configuration and token files atomically with mode 0600.
  • Explicitly correct permissions on existing files before or after replacement.
  • Avoid following symbolic links when creating or replacing credential files.
  • Separate non-sensitive configuration from secrets.
  • Provide migration logic that secures existing config.json files and warns users if unsafe permissions are detected.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/x_api_auth.py:219
Finding

Live Bearer Token Can Be Printed to Agent-Visible Standard Output

Content
View full analysis

Vulnerability Details

File Location: scripts/x_api_auth.py, lines 219-229
Vulnerability Type: Sensitive token disclosure through standard output
Risk Level: High

Vulnerable Code

python
parser.add_argument("--print-token", action="store_true", help="Print current access token")

args = parser.parse_args()

if args.print_token:
    token = get_valid_token()
    if token:
        print(token)
    else:
        print("No valid token found. Run without --print-token to authorize.", file=sys.stderr)
        sys.exit(1)
    return

Technical Analysis

The --print-token option retrieves or refreshes a live OAuth access token and writes it directly to standard output. In an AI-agent execution environment, command output may be copied into tool results, conversation transcripts, debug logs, telemetry, shell history, or persistent task records.

The feature is not required for bookmark retrieval because fetch_bookmarks_api.py imports the token helper directly. Printing a bearer credential unnecessarily expands the number of systems and people that may gain access to it.

The Base64 encoding used for HTTP Basic authentication elsewhere in this script is not itself an output channel: those values are attached to HTTPS requests sent to the fixed official X token endpoint. The confirmed output exposure is the explicit print(token) behavior.

Attack Path

  1. A user, automation rule, or agent invokes x_api_auth.py --print-token.
  2. get_valid_token() loads or refreshes the OAuth credential.
  3. The script writes the raw bearer token to standard output.
  4. The execution platform captures the output in a transcript, log, or task record.
  5. A person or process with access to that record copies the token.
  6. The token is replayed against the X API until it expires or is revoked.

Impact Assessment

Disclosure permits use of every scope granted to the access token. With the cur ...[truncated 358 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove --print-token because the bookmark fetcher does not require token output.
  • Pass tokens internally or through a protected credential store rather than standard output.
  • If a diagnostic export is indispensable, require interactive confirmation and clearly warn that the output is a live secret.
  • Refuse token printing when standard output is not attached to a trusted interactive terminal.
  • Never include bearer tokens in agent tool output, application logs, telemetry, or error messages.
  • Redact token-like values in execution infrastructure and invalidate any tokens previously captured in logs.
  • Reduce the underlying token scopes so any future disclosure has a smaller impact.
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
  • Rogue AgentSelf-Modification, Session Persistence
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (23)

YARA rule 'info_stealer': Information stealer patterns (credential harvesting, browser data theft) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

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

md
ks older than a threshold (default: 30 days)
2. For each: extract the TL;DR and one actionable takeaway
3. Present: "Apply it today or clear it"
4. User can unbookmark via: `bird unbookmark <tweet-id>` (bird only)

## Error Handling

| Error | Cause | Fix |
|-------|-------|-----|
| `bird: command not found` | bird CLI not installed | Use X API path instead, or `npm i -g bird-cli` |
| "No Twitter cookies found" | Not logged into X in browser | Log into x.com in Chrome/Firefox, or use X API |
| EPERM on Safari cookies | macOS permissions | Use Chrome/Firefox or X API instead |
| Empty results | Cookies/token expired | Re-login or re-run `x_api_auth.py` |
| Rate limit (429) | Too many API requests | Wait and retry, use `--count` to limit |
| "No X API token found" | Haven't run auth setup | Run `x_api_auth.py --client-id YOUR_ID` |
| Token refresh failed | Refresh token expired | Re-run `x_api_auth.py` to re-authorize |

## Tips

- Start with `-n 20` for quick digests, `--all` for deep a

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 · references/auth-setup.md (reported line 22)May include surrounding context.

md
2. Look for "Profile Path" — the last folder name is your profile (e.g., "Default", "Profile 1")

**Troubleshooting:**
- macOS may prompt for Keychain access → click "Allow"
- Must be logged into x.com in that Chrome profile
- If cookie extraction fails, close Chrome first (locked DB)

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 · scripts/x_api_auth.py (reported line 114)May include surrounding context.

python
def get_valid_token() -> str | None:
    """Get a valid access token, refreshing if needed. Returns None if no tokens."""
    tokens = load_tokens()
    if not tokens:
        return None

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 · scripts/x_api_auth.py (reported line 208)May include surrounding context.

python
save_tokens(tokens)
    save_config(client_id, client_secret)

    print(f"✅ Authenticated! Access token expires in {tokens.get('expires_in', '?')}s")
    if tokens.get("refresh_token"):
        print("   Refresh token saved — will auto-refresh.")
    else:

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

The --print-token option emits the current access token directly to stdout. Access tokens are bearer credentials; printing them makes accidental disclosure likely through terminal history, shell logging, process capture, CI logs, or user copy/paste mistakes, especially dangerous in a skill that manages persistent bookmark access and refresh tokens.

Content

Scanner excerpt · scripts/x_api_auth.py (reported line 220)May include surrounding context.

python
parser.add_argument("--client-id", required=True, help="Your X API Client ID")
    parser.add_argument("--client-secret", default="", help="Client Secret (for confidential apps)")
    parser.add_argument("--refresh", action="store_true", help="Just refresh the existing token")
    parser.add_argument("--print-token", action="store_true", help="Print current access token")

    args = parser.parse_args()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README promotes scheduled daily or weekly bookmark digests but does not warn users that this creates recurring network access to private X/Twitter bookmark data. Because bookmarks can reveal sensitive interests, projects, or accounts, unattended periodic collection increases privacy and data-exposure risk, especially on shared machines or when users assume the access is one-time.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
81% confidence
Finding

The README instructs users to perform OAuth authentication and states that tokens are auto-detected from ~/.config/x-bookmarks/, which implies persistent credential storage without describing protections, scope minimization, or lifecycle handling. Persistent session material for a personal social-media account increases the risk of account misuse or private bookmark access if the local machine, config directory, or logs are exposed.

Content

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

Option 2: X API v2 (no bird needed)

bash
# One-time: create app at https://developer.x.com, then:
python3 scripts/x_api_auth.py --client-id "YOUR_CLIENT_ID"

# Fetch bookmarks

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill broadens its mission from bookmark retrieval into proposing and potentially executing arbitrary downstream actions. That scope creep can cause an agent to use bookmark content as a launch point for unrelated operations, increasing the chance of acting on malicious or untrusted content embedded in bookmarked posts.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This workflow explicitly suggests testing tools, setting up software, analyzing code, and implementing advice based on bookmarked tweets. Since bookmarked content is untrusted and may link to hostile code or social-engineering content, encouraging execution-oriented follow-on actions raises the risk of unsafe code execution or broader system changes.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The documentation encourages capabilities like software setup/testing and code analysis that are not justified by a bookmark-management skill. This creates an unnecessary trust boundary expansion where untrusted social content can influence higher-risk operations outside the skill's stated domain.

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 · references/auth-setup.md (reported line 26)May include surrounding context.

  • Must be logged into x.com in that Chrome profile
  • If cookie extraction fails, close Chrome first (locked DB)

Make it permanent — create ~/.config/bird/config.json5:

json5
{
  chromeProfile: "Default"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The document instructs users to manually extract highly sensitive session tokens (auth_token and ct0) from browser cookies and store them in shell environment files without prominent warnings or handling guidance. These tokens can enable full account session hijacking or unauthorized API actions if copied, logged, committed, or exposed to other local processes.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The setup steps say the minimum app permission is 'Read', which would not support a DELETE endpoint for unbookmarking. Later, the document states unbookmark is supported via API, creating an active contradiction between the documented required permissions and the claimed behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Automatically saving OAuth tokens to ~/.config/x-bookmarks/tokens.json without visible security guidance encourages plaintext local secret storage that may be readable by other users, backup tools, or malware on the host. Refresh tokens in particular can provide long-lived account access if the file is stolen.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/fetch_bookmarks_api.py (reported line 30)May include surrounding context.

python
sys.path.insert(0, str(Path(__file__).parent))
from x_api_auth import get_valid_token, load_tokens, load_config

BASE_URL = "https://api.x.com/2"
MAX_RESULTS_PER_PAGE = 100  # X API max

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/x_api_auth.py (reported line 33)May include surrounding context.

python
sys.path.insert(0, str(Path(__file__).parent))
from x_api_auth import get_valid_token, load_tokens, load_config

BASE_URL = "https://api.x.com/2"
MAX_RESULTS_PER_PAGE = 100  # X API max

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The helper requests the bookmark.write scope even though the described primary use is reading, summarizing, and analyzing bookmarks. Overbroad OAuth scopes violate least privilege and increase the blast radius if the stored token is exposed, allowing bookmark modification in addition to read access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script persists client_secret to ~/.config/x-bookmarks/config.json but does not restrict file permissions or warn the user that a long-lived secret is being stored on disk. On multi-user systems or misconfigured environments, this can expose application credentials and enable unauthorized token exchanges or refreshes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The markdown describes storing bookmark-processing state in memory/bookmark-state.json, which is a local data write affecting user workspace state. While the skill documents token storage elsewhere, this workflow section does not explicitly warn the user that recurring digests will persist tracking metadata in the workspace.

Content

No source excerpt is available for this finding.

Excessive Permissions

Low
Category
Privilege Escalation
Confidence
80% confidence
Finding

Skill requests more permissions than appear necessary for its stated functionality. Review if elevated access is justified.

Content

Scanner excerpt · references/auth-setup.md (reported line 78)May include surrounding context.

md
1. Go to [X Developer Console](https://developer.x.com/en/portal/petition/essential/basic-info)
2. Create a project + app
3. Under **User authentication settings**, configure:
   - **App permissions:** Read (minimum)
   - **Type of App:** Native App (public client) or Web App (confidential)
   - **Callback URL:** `http://localhost:8739/callback`
   - **Website URL:** anything (e.g., `https://example.com`)

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The bearer token override example presents a sensitive secret inline with no warning, making accidental disclosure through shell history, process listings, screenshots, or copied snippets more likely. A stolen bearer token can allow unauthorized API access within the token's scope.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The manifest frames the skill around fetching, summarizing, categorizing, searching, and digesting bookmarks, while this auth/setup document explicitly advertises an unbookmark/delete capability through both bird CLI and the API. Although 'manage' could be read broadly, deletion is a materially stronger action than the mostly read/analysis-oriented use cases described in the manifest.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.