Back to skill

Security audit

Facebook Page

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent Facebook Page automation, but it asks an agent to handle long-lived Page credentials and broad Graph API actions with too little scoping for high-impact page changes.

Review before installing. Use this only for Pages where you are comfortable letting the agent perform publish, delete, moderation, and read operations allowed by the token. Grant the minimum Meta permissions, remove FB_APP_SECRET after setup, keep the credentials file out of backups and repositories, rotate/revoke tokens regularly, and manually confirm any destructive or public-facing action.

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 (1)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:38
Finding
OAuth Secrets Are Exposed in Request URLs and Unnecessarily Persisted<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 38–50 **Vulnerability Type**: Sensitive information exposure and unnecessary secret persistence **Risk Level**: Medium ### Vulnerable Code ```powershell # Provide: $appId, $appSecret, $shortToken (from Graph API Explorer), $pageId # 1. Exchange for long-lived user token $r1 = Invoke-RestMethod "https://graph.facebook.com/oauth/access_token?grant_type=fb_exchange_token&client_id=$appId&client_secret=$appSecret&fb_exchange_token=$shortToken" # 2. Get never-expiring Page token $r2 = Invoke-RestMethod "https://graph.facebook.com/v25.0/$pageId?fields=access_token&access_token=$($r1.access_token)" $pageToken = $r2.access_token # 3. Save — only these four fields, nothing else @{ FB_PAGE_ID = $pageId FB_PAGE_TOKEN = $pageToken FB_APP_ID = $appId FB_APP_SECRET = $appSecret } | ConvertTo-Json | Set-Content "$HOME/.config/fb-page/credentials.json" -Encoding UTF8 ``` ### Technical Analysis The token-exchange request places the Meta App Secret and short-lived access token directly in the URL query string. The subsequent request likewise places the long-lived user token in its URL. Although HTTPS encrypts the request in transit, query strings may be retained by PowerShell transcripts, command-history or diagnostic systems, exception records, monitoring products, or HTTP proxies. Consequently, sensitive credentials can escape the intended process boundary without any compromise of TLS. The setup then writes `FB_APP_SECRET` to the operational credential file even though the Skill explicitly states that only `FB_PAGE_TOKEN` and `FB_PAGE_ID` are required for ordinary API calls. The agent rules later instruct users to remove the App Secret, confirming that its long-term persistence is not necessary for the declared functionality. Saving it first and relying on later manual deletion expands the credential exposure window and violates least-secret-storage principles. The file-permiss ...[truncated 1861 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Do not persist one-time setup secrets.** Write only the fields needed during routine execution: ```powershell @{ FB_PAGE_ID = $pageId FB_PAGE_TOKEN = $pageToken } | ConvertTo-Json | Set-Content "$HOME/.config/fb-page/credentials.json" -Encoding UTF8 ``` 2. **Keep `FB_APP_SECRET`, `FB_APP_ID`, and the short-lived user token in memory only.** Clear the variables after exchange where practical, and never include them in the operational credential file. 3. **Avoid putting credentials in URLs.** Submit token-exchange parameters in a request body when supported by the Meta endpoint: ```powershell $r1 = Invoke-RestMethod ` -Uri "https://graph.facebook.com/oauth/access_token" ` -Method POST ` -Body @{ grant_type = "fb_exchange_token" client_id = $appId client_secret = $appSecret fb_exchange_token = $shortToken } ` -ErrorAction Stop ``` Use request bodies or authorization headers for subsequent access tokens wherever supported by the Graph API. 4. **Create and secure the credential directory before writing the file.** Apply restrictive directory permissions first, write through a securely permissioned temporary file, and atomically replace the destination to minimize exposure windows. 5. **Disable or redact sensitive logging during setup.** Ensure PowerShell transcription, verbose output, exception reporting, and proxy logging do not capture authorization headers, request bodies, or token-bearing URLs. 6. **Update all documentation and metadata consistently.** Remove `FB_APP_SECRET` and `FB_APP_ID` from the saved credential schema in `README.md`, `SKILL.md`, and `_meta.json`, documenting them only as transient setup inputs. 7. **Rotate potentially exposed credentials.** Users who previously followed the documented procedure should remove the stored App Secret, rotate or revoke the Page token, and inspect relevant transcripts, logs, and backups fo ...[truncated 25 chars]
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (22)

Hidden Instructions

High
Category
Prompt Injection
Content
# facebook-page

Facebook Page automation skill for [OpenClaw](https://github.com/openclaw/openclaw).
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Credential Access

High
Category
Privilege Escalation
Content
## How It Works

1. Loads your credentials from `~/.config/fb-page/credentials.json`
2. Figures out the right Graph API call from what you ask
3. Executes it inline — no script files required
4. If a permission is missing, tells you exactly which one to add and where
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## How It Works

1. Loads your credentials from `~/.config/fb-page/credentials.json`
2. Figures out the right Graph API call from what you ask
3. Executes it inline — no script files required
4. If a permission is missing, tells you exactly which one to add and where
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## How It Works

1. Loads your credentials from `~/.config/fb-page/credentials.json`
2. Figures out the right Graph API call from what you ask
3. Executes it inline — no script files required
4. If a permission is missing, tells you exactly which one to add and where
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## How It Works

1. Loads your credentials from `~/.config/fb-page/credentials.json`
2. Figures out the right Graph API call from what you ask
3. Executes it inline — no script files required
4. If a permission is missing, tells you exactly which one to add and where
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## How It Works

1. Loads your credentials from `~/.config/fb-page/credentials.json`
2. Figures out the right Graph API call from what you ask
3. Executes it inline — no script files required
4. If a permission is missing, tells you exactly which one to add and where
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## How It Works

1. Loads your credentials from `~/.config/fb-page/credentials.json`
2. Figures out the right Graph API call from what you ask
3. Executes it inline — no script files required
4. If a permission is missing, tells you exactly which one to add and where
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
## Setup (One Time)

You need: **Page ID**, **App ID**, **App Secret**, **short-lived User Access Token**.

The agent will exchange your short-lived token for a never-expiring Page token and save it to `~/.config/fb-page/credentials.json`. File permissions are restricted immediately after saving.
Confidence
87% confidence
Finding
Requiring users to provide an App Secret and short-lived User Access Token to the agent for one-time setup expands the set of highly sensitive secrets handled by the skill. If the agent mishandles prompts, logs, transcripts, or memory, these credentials could be disclosed or abused to obtain durable page access.

Credential Access

High
Category
Privilege Escalation
Content
You need: **Page ID**, **App ID**, **App Secret**, **short-lived User Access Token**.

The agent will exchange your short-lived token for a never-expiring Page token and save it to `~/.config/fb-page/credentials.json`. File permissions are restricted immediately after saving.

## Credentials File
Confidence
84% confidence
Finding
The documentation states the agent will exchange a short-lived token for a 'never-expiring' Page token and persist it locally. Persisting long-lived high-privilege tokens materially increases the blast radius of host compromise, prompt-triggered misuse, or accidental leakage from the agent environment.

Credential Access

High
Category
Privilege Escalation
Content
| Field | Description | Used when |
|---|---|---|
| `FB_PAGE_ID` | Your Facebook Page ID | All API calls |
| `FB_PAGE_TOKEN` | Never-expiring Page Access Token | All API calls |
| `FB_APP_ID` | Meta Developer App ID | One-time token exchange only |
| `FB_APP_SECRET` | Meta Developer App Secret | One-time token exchange only |
Confidence
81% confidence
Finding
The documented credential set includes a never-expiring page token and app secret, indicating the skill's steady-state design depends on powerful reusable secrets. In an agentic environment, long-lived reusable tokens are especially dangerous because unintended actions or local compromise can immediately translate into account-level impact.

Credential Access

High
Category
Privilege Escalation
Content
---
name: facebook-page
description: "Facebook Page manager: post, schedule, reply, get insights & more. Requires: powershell/pwsh. Reads ~/.config/fb-page/credentials.json (FB_PAGE_TOKEN, FB_PAGE_ID). FB_APP_SECRET for one-time setup only — delete afterward. Long-lived token; rotate periodically and immediately if host is compromised. Grant minimal permissions only. No data forwarded to third parties; all calls go to graph.facebook.com only."
metadata: {"openclaw":{"emoji":"[fb]","requires":{"anyBins":["powershell","pwsh"]}}}
---
Confidence
95% confidence
Finding
The skill explicitly documents reading long-lived credentials from a local JSON file, including a page access token and setup-time app secret. Storing and using persistent tokens from disk creates a real secret-exposure risk: any local compromise, overly broad file permissions, shell history leakage, backups, or accidental sync/commit can lead to takeover of the connected Facebook Page.

Credential Access

High
Category
Privilege Escalation
Content
## STEP 1 — Load Credentials

Credentials are stored in `~/.config/fb-page/credentials.json`.

```powershell
$cfg    = Get-Content "$HOME/.config/fb-page/credentials.json" -Raw | ConvertFrom-Json
Confidence
98% confidence
Finding
This line instructs the agent to load credentials directly from `~/.config/fb-page/credentials.json`, meaning the skill is designed to access sensitive authentication material from local storage. That is a genuine credential-handling risk because compromise of the host or file disclosure would expose tokens usable for posting, deleting, moderating, and reading page data.

Credential Access

High
Category
Privilege Escalation
Content
Credentials are stored in `~/.config/fb-page/credentials.json`.

```powershell
$cfg    = Get-Content "$HOME/.config/fb-page/credentials.json" -Raw | ConvertFrom-Json
$token  = $cfg.FB_PAGE_TOKEN
$pageId = $cfg.FB_PAGE_ID
```
Confidence
98% confidence
Finding
The code reads `FB_PAGE_TOKEN` into memory for direct API use. While necessary for functionality, this is still a true credential-access pattern because the skill handles a bearer token that grants significant control over the Facebook Page; bearer-token theft enables unauthorized API actions without additional authentication.

Credential Access

High
Category
Privilege Escalation
Content
| Field | Purpose |
|---|---|
| `FB_PAGE_TOKEN` | Never-expiring Page access token — used for all API calls |
| `FB_PAGE_ID` | Numeric Facebook Page ID |
| `FB_APP_ID` | Meta App ID — only needed during token exchange |
| `FB_APP_SECRET` | Meta App Secret — only needed during token exchange |
Confidence
94% confidence
Finding
The documentation specifies a never-expiring Page access token for all API calls. A non-expiring bearer token dramatically increases impact if disclosed, because an attacker can use it indefinitely to post content, delete posts, moderate comments, and query page data until manual revocation.

Credential Access

High
Category
Privilege Escalation
Content
FB_PAGE_TOKEN = $pageToken
    FB_APP_ID     = $appId
    FB_APP_SECRET = $appSecret
} | ConvertTo-Json | Set-Content "$HOME/.config/fb-page/credentials.json" -Encoding UTF8
```

**Restrict file permissions immediately after saving:**
Confidence
99% confidence
Finding
This line writes `FB_PAGE_TOKEN`, `FB_APP_ID`, and `FB_APP_SECRET` to disk in `credentials.json`. Persisting the app secret alongside the page token materially increases blast radius: an attacker who gains file access obtains both operational access and a higher-value application secret that should only be used transiently for token exchange.

Credential Access

High
Category
Privilege Escalation
Content
**Restrict file permissions immediately after saving:**
```powershell
# Windows
icacls "$HOME/.config/fb-page/credentials.json" /inheritance:r /grant:r "$($env:USERNAME):(R,W)"
# macOS / Linux
# chmod 600 ~/.config/fb-page/credentials.json
```
Confidence
89% confidence
Finding
This line references the credentials file in the context of permission hardening. Although the surrounding intent is protective, it still confirms the design relies on a local plaintext secret file, which remains a real risk if permissions are not actually enforced, if backups/cloud sync expose the file, or if other local processes can read it.

Credential Access

High
Category
Privilege Escalation
Content
# Windows
icacls "$HOME/.config/fb-page/credentials.json" /inheritance:r /grant:r "$($env:USERNAME):(R,W)"
# macOS / Linux
# chmod 600 ~/.config/fb-page/credentials.json
```

> ⚠️ Never commit this file to version control. It contains long-lived secrets.
Confidence
89% confidence
Finding
Like the prior finding, this is tied to the same local secret file and indicates reliance on filesystem protection alone for safeguarding long-lived credentials. The context lowers suspicion because it recommends restrictive permissions, but the underlying pattern is still risky because bearer tokens in plaintext remain highly valuable if the host is compromised.

Credential Access

High
Category
Privilege Escalation
Content
- **Always load credentials first.** If missing or incomplete, guide setup.
- **Only use `FB_PAGE_TOKEN` and `FB_PAGE_ID`** for API calls. `FB_APP_ID` and `FB_APP_SECRET` are for token exchange only.
- **Never write extra fields** to the credentials file (no owner IDs, conv IDs, or third-party keys).
- **Remove FB_APP_SECRET** from credentials.json after token exchange — it is not needed for API calls.
- **Least-privilege:** only request the permissions your use case needs. Do not request `pages_manage_ads` or `pages_manage_instant_articles` unless explicitly needed.
- **Rotate FB_PAGE_TOKEN** periodically via Graph API Explorer, and immediately if the host is ever compromised.
- **All API calls go to `graph.facebook.com` only.** No external forwarding, no third-party services.
Confidence
96% confidence
Finding
The agent rules require always loading credentials first from the local credentials file and acknowledge that `FB_APP_SECRET` may exist there. This codifies a workflow centered on local secret retrieval, making credential exposure a built-in operational risk rather than an incidental implementation detail.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The README advertises that users can ask for 'anything the Meta Graph API supports,' which creates an extremely broad action surface for an agentic skill. In practice, this can cause unintended activation or unsafe execution of destructive or privacy-impacting Facebook Page operations because the allowed command scope is not narrowly constrained.

Session Persistence

Medium
Category
Rogue Agent
Content
- **Posts** — text, image, link, video, scheduled
- **Comments** — get, reply, hide, delete
- **Insights** — page stats, post performance
- **Events** — list, create
- **Page info** — name, followers, about
- **Token management** — refresh expired tokens
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.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Windows
icacls "$HOME/.config/fb-page/credentials.json" /inheritance:r /grant:r "$($env:USERNAME):(R,W)"
# macOS / Linux
# chmod 600 ~/.config/fb-page/credentials.json
```

> ⚠️ Never commit this file to version control. It contains long-lived secrets.
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
"credentialSetup":  {
                            "type":  "manual",
                            "docsUrl":  "https://developers.facebook.com/tools/explorer/",
                            "description":  "One-time OAuth2 token exchange via Meta Graph API Explorer. After exchange, FB_APP_SECRET may be removed from credentials.json. Restrict file permissions with icacls (Windows) or chmod 600 (macOS/Linux) immediately after saving."
                        },
    "requires":  {
                     "binaries":  [
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Static analysis

No suspicious patterns detected.