Back to skill

Security audit

Xint

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real X/Twitter research CLI, but it has broad long-lived account permissions and unsafe installation/server patterns that users should review before installing.

Install only after reviewing the installer or using a more controlled path such as Homebrew or manual source checkout. Use least-privilege X/xAI credentials, avoid authorizing tweet.write unless the app removes that scope, set XINT_INSTALL_REQUIRE_CHECKSUM=1 if using install.sh, and do not enable webhooks, SSE MCP, or the package API server outside a trusted local environment with explicit auth and host controls.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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)

T03 · Remote Payload Retrieval and Execution

Error
Location
README.md:34
Finding
Mutable Remote Installer Is Piped Directly into a Shell<![CDATA[ ## Vulnerability Details **File Location**: `README.md:34-41` **Vulnerability Type**: Remote payload retrieval and execution **Risk Level**: Critical ### Vulnerable Code ```bash curl -fsSL https://raw.githubusercontent.com/0xNyk/xint/main/install.sh | bash ``` The documented pinned-version alternative still retrieves the installer from the mutable `main` branch: ```bash XINT_INSTALL_VERSION=<version-tag> \ curl -fsSL https://raw.githubusercontent.com/0xNyk/xint/main/install.sh | bash ``` ### Technical Analysis The installation instructions stream a script from the repository's mutable `main` branch directly into Bash. The script is executed without first being saved, inspected, pinned to an immutable commit, or independently authenticated. Setting `XINT_INSTALL_VERSION` only controls which release archive the downloaded installer subsequently selects. It does not pin or authenticate the installer itself. Consequently, the effective code executed by this command may change at any time after the Skill has been reviewed. This creates a remote code-execution channel controlled by the GitHub repository and its account, branch, and release infrastructure. A compromise of the maintainer account, repository permissions, branch protections, or upstream delivery path could convert the documented installation command into arbitrary command execution. ### Attack Path 1. An attacker compromises the repository owner, a maintainer account, or another mechanism capable of modifying `main/install.sh`. 2. The attacker inserts credential theft, persistence, or other arbitrary commands into the installer. 3. A user follows the README and runs the documented `curl ... | bash` command. 4. Bash executes the streamed content immediately with the invoking user's privileges. 5. The payload can access the user's environment, files, API credentials, shell configuration, and any resources available to that account. The same path applies to the nominally pinned example ...[truncated 705 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove all pipe-to-shell installation instructions. 2. Publish the installer as a versioned, immutable release artifact rather than retrieving it from `main`. 3. Require users to download the artifact before execution: ```bash curl -fSLo install.sh https://github.com/0xNyk/xint/releases/download/<version>/install.sh ``` 4. Publish a SHA-256 digest or cryptographic signature through a separately protected release manifest. 5. Require verification before execution: ```bash sha256sum -c install.sh.sha256 less install.sh bash install.sh ``` 6. Prefer a trusted package manager with immutable versioning and package-signing support. 7. If a convenience bootstrap command is retained, pin it to an immutable commit hash and clearly disclose that direct remote execution remains risky. ]]>

T08 · Insecure Dependencies

Error
Location
install.sh:49
Finding
Installer Proceeds When Release Integrity Verification Is Unavailable<![CDATA[ ## Vulnerability Details **File Location**: `install.sh:49-86` **Vulnerability Type**: Fail-open release integrity verification **Risk Level**: High ### Vulnerable Code ```bash local checksums_url="https://github.com/${OWNER}/${REPO}/releases/download/${version}/checksums.txt" local checksums_file="${tmpdir}/checksums.txt" if curl -fsSL "$checksums_url" -o "$checksums_file" 2>/dev/null; then local asset_name asset_name="$(basename "$tarball_url")" local expected expected="$(awk -v name="$asset_name" '$0 ~ name {print $1; exit}' "$checksums_file" || true)" if [[ -n "$expected" ]]; then local actual="" if command -v sha256sum >/dev/null 2>&1; then actual="$(sha256sum "$tarball" | awk '{print $1}')" elif command -v shasum >/dev/null 2>&1; then actual="$(shasum -a 256 "$tarball" | awk '{print $1}')" fi if [[ -n "$actual" ]]; then if [[ "$actual" != "$expected" ]]; then echo "error: checksum mismatch for $asset_name" >&2 exit 1 fi echo "==> Checksum verified" else if [[ "${XINT_INSTALL_REQUIRE_CHECKSUM:-0}" == "1" ]]; then echo "error: checksum required but neither sha256sum nor shasum is available" >&2 exit 1 fi echo "==> Checksum tool unavailable; skipping verification" fi else if [[ "${XINT_INSTALL_REQUIRE_CHECKSUM:-0}" == "1" ]]; then echo "error: checksum required but no entry found in checksums.txt" >&2 exit 1 fi echo "==> Checksums file present but no entry for $asset_name; skipping verification" fi else if [[ "${XINT_INSTALL_REQUIRE_CHECKSUM:-0}" == "1" ]]; then echo "error: checksum required but checksums.txt not found in release" >&2 exit 1 fi echo "==> No checksums.txt in release; skipping checksum verification" fi ``` After these fail-open branches, the installer extracts the source and installs its dependencies: ```bash tar -xzf "$tarball" -C "$tmpdir" ... cp -R "${src_dir}/." "$re ...[truncated 2036 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make checksum or signature verification mandatory by default; remove the fail-open behavior. 2. Abort installation if: - The verification manifest cannot be downloaded. - No exact archive entry exists. - No supported verification tool is available. - The expected digest has an invalid format. 3. Use exact filename matching instead of the broad `awk '$0 ~ name'` regular-expression match. 4. Validate `XINT_INSTALL_VERSION` against an expected tag format before interpolating it into URLs and paths. 5. Sign release manifests with Sigstore, GPG, or another verifiable signing mechanism. 6. Publish the trusted public key or identity policy separately from the release artifacts. 7. Verify the archive before extraction and before running any package-manager operation. 8. Consider distributing a prebuilt, signed artifact so installation does not need to execute a dependency installation step. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
lib/collections.ts:178
Finding
xAI Bearer Credentials Are Exposed Through Child-Process Arguments<![CDATA[ ## Vulnerability Details **File Location**: `lib/collections.ts:178-262` **Vulnerability Type**: Sensitive credential exposure through process arguments **Risk Level**: High ### Vulnerable Code The management API credential is included directly in the curl argument vector: ```typescript const proc = Bun.spawn([ "curl", "-s", "-X", "POST", `${MGMT_BASE}/collections/${collectionId}/documents`, "-H", `Authorization: Bearer ${key}`, "-F", `document_id=${documentId}`, ], { stdout: "pipe", stderr: "pipe" }); ``` The same pattern is used when uploading a document: ```typescript const proc = Bun.spawn([ "curl", "-s", "-X", "POST", `${MGMT_BASE}/collections/${collectionId}/documents`, "-H", `Authorization: Bearer ${key}`, "-F", `file=@${filePath}`, "-F", `data=@${filePath}`, "-F", `name=${name}`, "-F", `content_type=${contentType}`, ], { stdout: "pipe", stderr: "pipe" }); ``` It is also used for the xAI Files API credential: ```typescript const proc = Bun.spawn([ "curl", "-s", "-X", "POST", `${API_BASE}/files`, "-H", `Authorization: Bearer ${key}`, "-F", `file=@${filePath};filename=${filename}`, "-F", `purpose=${purpose}`, ], { stdout: "pipe", stderr: "pipe" }); ``` ### Technical Analysis Although `Bun.spawn` is invoked with an argument array and therefore avoids ordinary shell metacharacter expansion, the bearer token becomes part of curl's operating-system process argument vector. Depending on operating-system configuration, process arguments can be visible through process inspection tools, `/proc` interfaces, endpoint monitoring, debugging utilities, telemetry agents, audit logs, or crash diagnostics. A local account or monitoring service able to inspect the curl process may capture the complete authorization header. The management credential is particularly sensitive because it is used for collection administration and document attachment. Exposure is avoidable because Bun provides native `fetch` and `FormD ...[truncated 1330 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace curl subprocesses with native `fetch` and `FormData`: ```typescript const form = new FormData(); form.append("document_id", documentId); const response = await fetch(endpoint, { method: "POST", headers: { Authorization: `Bearer ${key}`, }, body: form, }); ``` 2. For file uploads, create a `Blob` from the file content and append it to `FormData`. 3. Keep credentials in process memory and HTTP headers rather than command-line arguments. 4. Ensure errors never include request headers or bearer credentials. 5. Rotate existing xAI and management keys if these operations have been used on multi-user or heavily monitored systems. 6. Apply the narrowest available xAI-side permissions to management and upload keys. 7. Add automated tests that assert secrets are never passed to `Bun.spawn` or included in logged command representations. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
lib/oauth.ts:23
Finding
OAuth Flow Requests Write Permissions Beyond the Declared Functional Requirements<![CDATA[ ## Vulnerability Details **File Location**: `lib/oauth.ts:23-25` **Vulnerability Type**: Excessive OAuth authorization scope **Risk Level**: Medium ### Vulnerable Code ```typescript const SCOPES = "bookmark.read bookmark.write like.read like.write follows.read follows.write list.read list.write block.read block.write mute.read mute.write tweet.read tweet.write users.read offline.access"; ``` The Skill declaration states: ```text Non-goals: Not for posting tweets, not for DMs, not for enterprise features. ``` ### Technical Analysis The OAuth setup requests one broad, fixed set of read and write scopes for every authenticated user. In particular, it requests `tweet.write` even though posting tweets is explicitly identified as a non-goal. It also requests bookmark, like, follow, list, block, and mute write permissions together. Users who only require read-only bookmark retrieval, follower analysis, or another limited operation must still authorize unrelated account-modification permissions. The inclusion of `offline.access` enables long-lived access through refresh tokens. When combined with excessive write scopes, theft of the locally stored refresh token or compromise of the CLI creates a larger account-modification blast radius than necessary. The repository does protect the token file with mode `0600` and validates PKCE state, which reduces local disclosure and OAuth CSRF risk. Those controls do not eliminate the least-privilege violation. ### Attack Path 1. A user runs `xint auth setup`. 2. The authorization request asks for the entire fixed scope set, including `tweet.write` and multiple unrelated write permissions. 3. The user approves the request, and the resulting access and refresh tokens are stored locally. 4. An attacker later compromises the CLI process, installer, user account, backup, or token file. 5. The attacker reuses the token or refresh token. 6. The attacker performs any X account action permitted by the excessive scop ...[truncated 745 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `tweet.write` unless an explicitly documented and user-visible feature requires it. 2. Split OAuth authorization into least-privilege profiles, such as: - Read-only research. - Bookmark management. - Likes and follows. - List management. - Moderation. 3. Request write scopes only when the user explicitly enables the related feature. 4. Display the exact requested scopes and their effects before opening the authorization URL. 5. Prefer incremental authorization where supported. 6. Store distinct tokens for separate permission profiles so read-only workflows do not use broadly privileged credentials. 7. Provide a reauthorization or downgrade workflow when permissions are reduced. 8. Add tests that compare requested scopes with the documented capabilities and reject undeclared permissions. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (192)

Tainted flow: 'req' from os.environ.get (line 183, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
req = urllib.request.Request(url, data=data, method=method.upper(), headers=headers)
    try:
        with urllib.request.urlopen(req, timeout=timeout_s) as resp:
            txt = resp.read().decode("utf-8", errors="replace")
            return (json.loads(txt) if txt else {}), plan
    except urllib.error.HTTPError as e:
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'req' from os.environ.get (line 183, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
req = urllib.request.Request(url, data=data, method=method.upper(), headers=headers)
    try:
        with urllib.request.urlopen(req, timeout=timeout_s) as resp:
            txt = resp.read().decode("utf-8", errors="replace")
            return (json.loads(txt) if txt else {}), plan
    except urllib.error.HTTPError as e:
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Chaining Abuse

High
Category
Tool Misuse
Content
## Install

```bash
curl -fsSL https://raw.githubusercontent.com/0xNyk/xint/main/install.sh | bash
```

Optional pinned version:
Confidence
97% confidence
Finding
The `| bash` construct is the risky element that turns a remote fetch into immediate shell execution, enabling command-chaining abuse and eliminating any review step. In this skill’s context, such a pattern is especially unsafe because it normalizes high-trust execution for a tool that also handles API tokens, OAuth credentials, and network operations.

Chaining Abuse

High
Category
Tool Misuse
Content
```bash
XINT_INSTALL_VERSION=<version-tag> \
curl -fsSL https://raw.githubusercontent.com/0xNyk/xint/main/install.sh | bash
```

Homebrew (lightweight prebuilt binary on Apple Silicon):
Confidence
97% confidence
Finding
The version-pinned install still uses command chaining to execute fetched content immediately, so the security issue remains. If the remote content or distribution path is compromised, users can be induced to run attacker-controlled code with no inspection barrier.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Repository ruleset and branch-protection changes are privileged GitHub write actions far outside the stated X intelligence use case. Such hidden admin capabilities materially increase the blast radius of misuse, including disruption of development workflows and governance settings.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
Repository ruleset and branch-protection changes are privileged GitHub write actions far outside the stated X intelligence use case. Such hidden admin capabilities materially increase the blast radius of misuse, including disruption of development workflows and governance settings.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Repository ruleset and branch-protection changes are privileged GitHub write actions far outside the stated X intelligence use case. Such hidden admin capabilities materially increase the blast radius of misuse, including disruption of development workflows and governance settings.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
Repository ruleset and branch-protection changes are privileged GitHub write actions far outside the stated X intelligence use case. Such hidden admin capabilities materially increase the blast radius of misuse, including disruption of development workflows and governance settings.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
Repository ruleset and branch-protection changes are privileged GitHub write actions far outside the stated X intelligence use case. Such hidden admin capabilities materially increase the blast radius of misuse, including disruption of development workflows and governance settings.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
Repository ruleset and branch-protection changes are privileged GitHub write actions far outside the stated X intelligence use case. Such hidden admin capabilities materially increase the blast radius of misuse, including disruption of development workflows and governance settings.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
Repository ruleset and branch-protection changes are privileged GitHub write actions far outside the stated X intelligence use case. Such hidden admin capabilities materially increase the blast radius of misuse, including disruption of development workflows and governance settings.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
Repository ruleset and branch-protection changes are privileged GitHub write actions far outside the stated X intelligence use case. Such hidden admin capabilities materially increase the blast radius of misuse, including disruption of development workflows and governance settings.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
Repository ruleset and branch-protection changes are privileged GitHub write actions far outside the stated X intelligence use case. Such hidden admin capabilities materially increase the blast radius of misuse, including disruption of development workflows and governance settings.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
Repository ruleset and branch-protection changes are privileged GitHub write actions far outside the stated X intelligence use case. Such hidden admin capabilities materially increase the blast radius of misuse, including disruption of development workflows and governance settings.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Repository ruleset and branch-protection changes are privileged GitHub write actions far outside the stated X intelligence use case. Such hidden admin capabilities materially increase the blast radius of misuse, including disruption of development workflows and governance settings.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
Repository ruleset and branch-protection changes are privileged GitHub write actions far outside the stated X intelligence use case. Such hidden admin capabilities materially increase the blast radius of misuse, including disruption of development workflows and governance settings.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Repository ruleset and branch-protection changes are privileged GitHub write actions far outside the stated X intelligence use case. Such hidden admin capabilities materially increase the blast radius of misuse, including disruption of development workflows and governance settings.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
Repository ruleset and branch-protection changes are privileged GitHub write actions far outside the stated X intelligence use case. Such hidden admin capabilities materially increase the blast radius of misuse, including disruption of development workflows and governance settings.

Scope Creep

High
Confidence
96% confidence
Finding
The skill explicitly supports posting data to arbitrary HTTPS webhook destinations, which is a strong exfiltration vector when combined with search results, OAuth-derived data, or local exports. Even with optional allowlisting, the default design permits sending collected data outside the declared endpoint set.

External Script Fetching

High
Category
Supply Chain
Content
- Webhook delivery is opt-in (`--webhook`) and disabled by default

### Installation
- For Bun: prefer OS package managers over `curl | bash` when possible
- Verify any installer scripts before running

### MCP Server (Optional)
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Ae1

High
Category
analysis-evasion
Content
python3 scripts/xai_x_search_scan.py --help
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Scope Creep

High
Confidence
96% confidence
Finding
The documented external services exceed the declared network endpoints in the security manifest, which means actual outbound connections may occur to destinations the operator is not told to expect. In a credentialed skill with file and network access, undeclared endpoints are dangerous because they obscure data flows and hamper policy enforcement.

Ae1

High
Category
analysis-evasion
Content
python3 scripts/xai_collections.py --help
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

External Script Fetching

High
Category
Supply Chain
Content
local api_url="https://api.github.com/repos/${OWNER}/${REPO}/releases/latest"
  local tag
  tag="$(curl -fsSL "$api_url" | python3 -c 'import json,sys; print(json.load(sys.stdin)["tag_name"])')"
  printf '%s' "$tag"
}
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Credential Access

High
Category
Privilege Escalation
Content
// Try env first
  if (process.env.X_BEARER_TOKEN) return process.env.X_BEARER_TOKEN;

  // Try .env in project directory
  try {
    const envFile = readFileSync(
      join(import.meta.dir, "..", ".env"),
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Static analysis

Detected: suspicious.env_credential_access, suspicious.exposed_secret_literal, suspicious.potential_exfiltration

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
lib/api.ts:14

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
lib/article.ts:52

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
lib/billing.ts:9

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
lib/collections.ts:68

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
lib/grok.ts:78

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
lib/health.ts:107

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
lib/mcp.ts:38

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
lib/oauth.ts:92

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
lib/trends.ts:144

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
lib/x_search.ts:70

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
xint.ts:1285

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
lib/oauth.ts:186

Sensitive-looking file read is paired with a network send.

Warn
Code
suspicious.potential_exfiltration
Location
lib/api.ts:1

Sensitive-looking file read is paired with a network send.

Warn
Code
suspicious.potential_exfiltration
Location
lib/article.ts:55

Sensitive-looking file read is paired with a network send.

Warn
Code
suspicious.potential_exfiltration
Location
lib/grok.ts:82

Sensitive-looking file read is paired with a network send.

Warn
Code
suspicious.potential_exfiltration
Location
lib/oauth.ts:74

Sensitive-looking file read is paired with a network send.

Warn
Code
suspicious.potential_exfiltration
Location
lib/trends.ts:1

Sensitive-looking file read is paired with a network send.

Warn
Code
suspicious.potential_exfiltration
Location
lib/x_search.ts:73