Back to skill

Security audit

qwe

Security checks for vulnerabilities and agentic risk

Overview

This Facebook publishing skill is mostly purpose-aligned, but it handles powerful Facebook tokens unsafely and directs users to a hard-coded OAuth app ID.

Install only if you are comfortable reviewing and editing the helper first. Replace the hard-coded Facebook app ID with your own configured FB_APP_ID, avoid printing or saving full tokens, add fb_tokens_output.json and .env to git ignores, store tokens in a secret manager or protected environment, and rotate any token that was already printed, logged, or committed.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
agents/fb_token_helper.py:99
Finding

Facebook Access Tokens Are Printed and Persisted in Plaintext

Content
View full analysis

Vulnerability Details

File Location: agents/fb_token_helper.py, lines 99 and 127-138
Vulnerability Type: Plaintext disclosure and insecure storage of authentication credentials
Risk Level: High

Vulnerable Code

python
long_token = exchange_to_long_lived(short_token)
console.print(f"[green]✅ Long-lived User Token:[/green]\n{long_token}\n")
python
# Save to .env hint
console.print("\n[bold green]✅ XONG! Cập nhật .env:[/bold green]")
for page in pages:
    console.print(f"\nPage: [bold]{page.get('name')}[/bold] (ID: {page.get('id')})")
    console.print(f"FB_USER_ACCESS_TOKEN={long_token}")
    console.print(f"FB_PAGE_ACCESS_TOKEN={page.get('access_token')}")
    console.print(f"FB_PAGE_ID={page.get('id')}")

# Save to file
output_path = "fb_tokens_output.json"
with open(output_path, "w", encoding="utf-8") as f:
    json.dump({
        "long_lived_user_token": long_token,
        "pages": pages
    }, f, ensure_ascii=False, indent=2)
console.print(f"\n[dim]Token đã lưu vào {output_path} (đừng commit file này!)[/dim]")

Technical Analysis

The helper prints the complete long-lived user token and every Page access token to the terminal. It also stores those credentials in fb_tokens_output.json as unencrypted JSON using the process's default file permissions.

Access tokens are bearer credentials: possession of a token is generally sufficient to exercise its authorized Facebook Graph API capabilities. Printing them exposes the credentials to terminal history, session recording, CI logs, remote-support tooling, and centralized log collection. Persisting them in a predictable plaintext file additionally exposes them through shared workspaces, backups, artifacts, and accidental source-control commits.

The code does not explicitly create the output file with owner-only permissions. The reviewed project structure also contains no .gitignore that protects `fb_tokens_outpu ...[truncated 1625 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove all output that prints complete user or Page access tokens.
  2. If token identification is necessary, display only a masked value, such as the final four characters.
  3. Do not persist tokens by default. Require explicit user consent before writing any credential to disk.
  4. Prefer an operating-system credential store, dedicated secrets manager, or protected environment-variable configuration.
  5. If file storage is unavoidable:
    • Create the file atomically with owner-only permissions such as 0600.
    • Use a user-selected secure location rather than a predictable project-root filename.
    • Avoid retaining tokens longer than operationally required.
    • Add fb_tokens_output.json and other secret-bearing files to .gitignore.
  6. Warn users that terminal output may be recorded by CI systems, shell logging, or remote administration tools.
  7. Revoke and rotate any token that has already appeared in logs, artifacts, repositories, or shared files.
  8. Add automated secret scanning and a regression test that verifies complete tokens are never emitted to console output.

T09 · Insecure Skill Coding Practices

Warning
Location
agents/fb_token_helper.py:76
Finding

Hard-Coded OAuth Application ID Can Cause Authorization of the Wrong Application

Content
View full analysis

Vulnerability Details

File Location: agents/fb_token_helper.py, line 76
Vulnerability Type: OAuth application confusion caused by inconsistent application identity
Risk Level: Medium

Vulnerable Code

python
console.print("\n[bold yellow]BƯỚC 1:[/bold yellow] Lấy Short-lived User Token")
console.print(
    "→ Mở link sau trong trình duyệt:\n"
    f"[link]https://developers.facebook.com/tools/explorer[/link]\n\n"
    "Chọn App [bold]4348763312075291[/bold], click [bold]Generate Access Token[/bold]\n"
    "Tích chọn permissions:\n"
    "  ✅ pages_manage_posts\n"
    "  ✅ pages_read_engagement\n"
    "  ✅ pages_show_list\n"
    "  ✅ public_profile\n"
)

The subsequent exchange uses a potentially different application identity:

python
params = {
    "grant_type": "fb_exchange_token",
    "client_id": config.FB_APP_ID,
    "client_secret": config.FB_APP_SECRET,
    "fb_exchange_token": short_token,
}

Technical Analysis

The interactive instructions tell every user to select the fixed Facebook application ID 4348763312075291. However, the token exchange is performed with config.FB_APP_ID and config.FB_APP_SECRET, which are supplied through environment variables.

OAuth access tokens are associated with the application for which authorization was granted. Directing the user to one application while processing the token as though it belongs to another creates an application-identity mismatch. At minimum, this can cause token exchange failures. More importantly, a user following the displayed instructions may grant Page-management permissions to an application other than the application they intended to configure and trust.

The fixed application identity is also inconsistent with SKILL.md, which describes FB_APP_ID as a required user-controlled environment variable.

Attack Path

  1. A user configures their own FB_APP_ID and FB_APP_SECRET.
  2. The u ...[truncated 1463 chars]
Remediation
View remediation

Remediation Suggestions

  1. Replace the hard-coded identifier with config.FB_APP_ID:
    python
    f"Select App [bold]{config.FB_APP_ID}[/bold], then click Generate Access Token\n"
    
  2. Validate that FB_APP_ID and FB_APP_SECRET are present before starting the interactive authorization flow.
  3. Display the configured App ID and require the user to confirm that it belongs to the application they intend to authorize.
  4. Tell users to verify the application's name, owner, and App ID in Meta for Developers before granting Page permissions.
  5. Reject or clearly explain tokens whose application identity does not match the configured App ID.
  6. Remove documentation or prompts that encourage users to authorize an application they do not own or have not independently verified.
  7. Request only the minimum permissions required for the selected operation and explain why each permission is needed.
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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (26)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill description emphasizes posting, while the content also documents credential validation, token testing, and page metadata reads. These are not inherently unsafe, but the mismatch broadens the operational scope beyond what the declared purpose suggests and can lead to excessive trust or permissions being granted.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill description emphasizes posting, while the content also documents credential validation, token testing, and page metadata reads. These are not inherently unsafe, but the mismatch broadens the operational scope beyond what the declared purpose suggests and can lead to excessive trust or permissions being granted.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
81% confidence
Finding

The skill description emphasizes posting, while the content also documents credential validation, token testing, and page metadata reads. These are not inherently unsafe, but the mismatch broadens the operational scope beyond what the declared purpose suggests and can lead to excessive trust or permissions being granted.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The skill description emphasizes posting, while the content also documents credential validation, token testing, and page metadata reads. These are not inherently unsafe, but the mismatch broadens the operational scope beyond what the declared purpose suggests and can lead to excessive trust or permissions being granted.

Content

No source excerpt is available for this finding.

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 · SKILL.md (reported line 42)May include surrounding context.

md
"""
agents/fb_token_helper.py
──────────────────────────
Tiện ích lấy và exchange Facebook Access Token.

Chạy trực tiếp:
    python agents/fb_token_helper.py

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/fb_token_helper.py (reported line 4)May include surrounding context.

python
"""
agents/fb_token_helper.py
──────────────────────────
Tiện ích lấy và exchange Facebook Access Token.

Chạy trực tiếp:
    python agents/fb_token_helper.py

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/fb_token_helper.py (reported line 13)May include surrounding context.

python
"""
agents/fb_token_helper.py
──────────────────────────
Tiện ích lấy và exchange Facebook Access Token.

Chạy trực tiếp:
    python agents/fb_token_helper.py

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/fb_token_helper.py (reported line 74)May include surrounding context.

python
"""
agents/fb_token_helper.py
──────────────────────────
Tiện ích lấy và exchange Facebook Access Token.

Chạy trực tiếp:
    python agents/fb_token_helper.py

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/fb_token_helper.py (reported line 82)May include surrounding context.

python
"""
agents/fb_token_helper.py
──────────────────────────
Tiện ích lấy và exchange Facebook Access Token.

Chạy trực tiếp:
    python agents/fb_token_helper.py

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 · test_fb_connection.py (reported line 38)May include surrounding context.

python
"""
agents/fb_token_helper.py
──────────────────────────
Tiện ích lấy và exchange Facebook Access Token.

Chạy trực tiếp:
    python agents/fb_token_helper.py

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 · test_fb_connection.py (reported line 39)May include surrounding context.

python
"""
agents/fb_token_helper.py
──────────────────────────
Tiện ích lấy và exchange Facebook Access Token.

Chạy trực tiếp:
    python agents/fb_token_helper.py

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/fb_token_helper.py (reported line 50)May include surrounding context.

python
def get_page_tokens(long_lived_user_token: str) -> list[dict]:
    """
    Lấy danh sách Pages + Page Access Tokens từ long-lived user token.
    """
    url = f"{config.FB_BASE_URL}/me/accounts"
    params = {"access_token": long_lived_user_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/fb_token_helper.py (reported line 107)May include surrounding context.

python
def get_page_tokens(long_lived_user_token: str) -> list[dict]:
    """
    Lấy danh sách Pages + Page Access Tokens từ long-lived user token.
    """
    url = f"{config.FB_BASE_URL}/me/accounts"
    params = {"access_token": long_lived_user_token}

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script writes the long-lived user token and page access tokens to fb_tokens_output.json on disk, creating a plaintext secret store. Local files are commonly exposed through backups, logs, malware, shared machines, or accidental commits, enabling account/page takeover for the token lifetime.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

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

md
"""
config.py — Centralized configuration loaded from .env
"""
import os
from dotenv import load_dotenv

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · agents/fb_token_helper.py (reported line 13)May include surrounding context.

python
"""
config.py — Centralized configuration loaded from .env
"""
import os
from dotenv import load_dotenv

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · agents/fb_token_helper.py (reported line 131)May include surrounding context.

python
"""
config.py — Centralized configuration loaded from .env
"""
import os
from dotenv import load_dotenv

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · config.py (reported line 2)May include surrounding context.

python
"""
config.py — Centralized configuration loaded from .env
"""
import os
from dotenv import load_dotenv

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · config.py (reported line 50)May include surrounding context.

python
if missing:
        raise EnvironmentError(
            f"❌ Thiếu biến môi trường: {', '.join(missing)}\n"
            "→ Kiểm tra file .env"
        )

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill declares access to sensitive capabilities through its described behavior and environment variables, but does not explicitly scope or constrain those capabilities with a permissions or allowed-tools declaration. In an agent environment, this increases the risk of over-privileged execution, especially because network access and secret-bearing environment access are central to the skill's operation.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest says the skill is a 'Facebook Publisher Skill (Automate Page Posts via Graph API)', which implies creating posts. The method get_post_insights adds a read/analytics capability for reactions, comments, and shares that is not part of publishing itself.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This helper explicitly collects a short-lived user token, exchanges it for a long-lived user token, enumerates page access tokens, and then displays/persists them. For a publisher skill, that expands from posting functionality into credential acquisition and handling, increasing the blast radius if the script, terminal session, or workstation is compromised.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script performs a sensitive file write containing Facebook tokens without obtaining explicit consent immediately before doing so. Users may believe the tool only displays values, while it silently creates a reusable credential artifact on disk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring and all user-facing console messages are written in Vietnamese, which imposes a specific language on users without any opt-in or alternative locale support. This matches the policy category for language/locale constraints that are not user-selectable or explicitly justified as region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The file's docstrings and interactive console text consistently require Vietnamese comprehension, but there is no indication that the skill is region-specific or that users can choose another language. This is a natural-language policy issue because the skill effectively forces a locale/language by default.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.