Back to skill

Security audit

Content360

Security checks for vulnerabilities and agentic risk

Overview

This skill appears purpose-built for Content360 and Notion syncing, but it handles high-impact publishing workflows and account credentials with weak scoping and safeguards.

Review this before installing if it will touch production accounts. Use least-privilege Content360 and Notion credentials, avoid storing a primary account password if possible, run --dry-run first, verify the target workspace/database IDs, and do not allow live scheduling/deletion/approval actions without human review.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/content360_sync.py:188
Finding

Untrusted Notion Content Embedded into HTML Without Escaping

Content
View full analysis
{content_text}", "media": [], "url": "", "opened": True }] }) ``` The value passed as `content_text` is assembled directly from Notion-controlled properties: ```python caption = extract_text(props.get("Caption", "")) hook = extract_text(props.get("Hook", "")) cta = extract_text(props.get("CTA", "")) if hook: full_text = f"{hook}\n\n{caption}" else: full_text = caption if cta: full_text += f"\n\n{cta}" ``` ### Technical Analysis The `Caption`, `Hook`, and `CTA` fields are read from an external Notion database and treated as plain text. The resulting value is interpolated directly into an HTML fragment without HTML escaping or sanitization. An attacker who can modify records in the source Notion database can supply markup such as links, images, malformed HTML, or active elements. The script then submits that markup to Content360 as the `body` of a post. Whether JavaScript or other active content can execute depends on Content360's server-side sanitization and the rendering behavior of downstream social-media integrations. The client-side script nevertheless fails to enforce the documented plain-text trust boundary. ### Attack Path 1. An attacker obtains permission to create or edit a page in the configured Notion content calendar. 2. The attacker places crafted HTML in the page's `Caption`, `Hook`, or `CTA` property. 3. An operator runs the synchronization script without `--dry-run`. 4. The script reads the crafted value and inserts it directly into `
{content_text}
`. 5. The resulting HTML is submitted to Content360 and may be stored, previewed, or ...[truncated 853 chars]
Remediation
View remediation
{safe_content}" ``` 2. If limited formatting must be supported, use a maintained allowlist-based sanitizer and permit only explicitly required elements and attributes. 3. Reject active elements, event-handler attributes, dangerous URL schemes, embedded frames, and remote resource tags. 4. Validate content both when reading it from Notion and immediately before sending it to Content360. 5. Add tests covering tags, entities, malformed markup, event handlers, and `javascript:` URLs. 6. Retain or verify server-side sanitization in Content360 as defense in depth rather than relying on it as the sole protection. ]]>

T08 · Insecure Dependencies

Note
Location
README.md:28
Finding

Unpinned Third-Party Dependency Installation

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
README.md:20
Finding

Personal and Tenant-Specific Identifiers Committed to Project Files

Content
View full analysis
Remediation
View remediation
NOTION_DATABASE_ID= ``` 2. Remove the hardcoded database default and require explicit configuration: ```python NOTION_DATABASE_ID = os.environ.get("NOTION_DATABASE_ID", "") ``` 3. Terminate before any network request if `NOTION_API_KEY` or `NOTION_DATABASE_ID` is missing. 4. Display the selected workspace and database identifiers before a real synchronization and require explicit confirmation for interactive use. 5. Keep `--dry-run` as the documented first-run procedure. 6. Review repository history and remove personal or tenant metadata where practical. 7. Apply least-privilege permissions to the Notion integration so it can access only the intended database. ]]>
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
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (22)

Tainted flow: 'url' from os.environ.get (line 144, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/content360_sync.py (reported line 260)May include surrounding context.

python
payload = {"page_size": 100}
    if filter_props:
        payload["filter"] = filter_props
    resp = requests.post(
        url,
        headers={
            "Authorization": f"Bearer {NOTION_API_KEY}",

Tainted flow: 'url' from os.environ.get (line 144, credential/environment) → requests.patch (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/content360_sync.py (reported line 296)May include surrounding context.

python
def notion_update_page(page_id, properties):
    url = f"https://api.notion.com/v1/pages/{page_id}"
    resp = requests.patch(
        url,
        headers={
            "Authorization": f"Bearer {NOTION_API_KEY}",

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The README documents a credentialed authentication flow requiring email/password, session cookies, and bearer tokens, and it includes a real email address plus precise instructions for obtaining and using access tokens. In adversarial or loosely governed agent environments, this materially lowers the barrier to credential misuse, token theft, and unauthorized access to Content360 and connected publishing accounts.

Content

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

md
Content360 uses **Laravel Sanctum + Inertia.js**. The auth requires:

1. **Session cookie** from logging in via email/password
2. **Bearer token** (access token) in the `Authorization` header
3. **`X-Inertia-Version`** hash header (extracted from any authenticated response)
4. **`X-Requested-With: XMLHttpRequest`** on every request

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description focuses on Content360 management, but the file also describes reading and modifying a Notion content calendar and running a sync workflow that can create and schedule posts. This mismatch can mislead users about what data sources are touched and what external side effects occur, undermining informed consent and safe review.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
87% confidence
Finding

The skill instructs users to store both a bearer token and primary account credentials, and references an automated session login flow. Handling reusable login credentials alongside API tokens materially increases credential exposure risk if the skill, logs, or runtime are compromised, and can enable full account takeover rather than limited API misuse.

Content

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

md
- `CONTENT360_EMAIL` = your login email
   - `CONTENT360_PASSWORD` = your login password

**Note**: Access tokens require an active web session to work. If the token returns 401, re-authenticate by logging in via the web interface or using the session login flow in `content360_sync.py`.

### Auth Flow

Credential Access

High
Category
Privilege Escalation
Confidence
88% confidence
Finding

The skill explicitly requires the user's Content360 email and password for automatic session authentication and references a session login flow. In an agent skill, requesting reusable account credentials is high risk because compromise of the skill, logs, or execution environment could expose full account access well beyond a scoped API token.

Content

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

md
- `CONTENT360_EMAIL` = your login email
   - `CONTENT360_PASSWORD` = your login password

**Note**: Access tokens require an active web session to work. If the token returns 401, re-authenticate by logging in via the web interface or using the session login flow in `content360_sync.py`.

### Auth Flow

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The README advertises deletion support and delete endpoints without a strong destructive-operation warning. In a skill that automates social-media management, undocumented or under-emphasized deletion functionality increases the chance of accidental post removal or misuse by an agent or operator.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest describes a skill for creating, scheduling, publishing, analytics, media upload, and inbox management within Content360. This README says the built sync script reads from a Notion content calendar and writes back to Notion by marking posts as posted, which is a separate cross-system synchronization capability not reflected in the manifest description.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The README states that the sync process marks Notion records as "Posted" after syncing, but it does not prominently warn that running the skill will modify external data. In an agent setting, undocumented writeback behavior can cause unintended state changes, data integrity issues, and operational confusion across connected systems.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill declares no explicit tool scope even though the documentation clearly indicates access to environment secrets and networked APIs. In an agent setting, missing permission boundaries can let the skill operate with broader capabilities than users expect, increasing the chance of unintended secret access or outbound actions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The documentation lists destructive and externally visible operations such as delete, approve, add-to-queue, and schedule without warning that they can remove content or publish business-facing material. In an agent-driven environment, lack of safety prompts increases the risk of accidental destructive actions or unauthorized posting to public accounts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The run instructions present the real sync command without a prominent warning that it may create drafts and schedule posts based on Notion content. Users may assume it is a harmless synchronization step and unintentionally trigger visible actions across connected social media workflows.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The surrounding documentation and the skill manifest describe a Content360 integration for creating, scheduling, publishing, analytics, media upload, and inbox management within Content360. This script also queries a Notion content calendar and writes back to Notion pages to mark posts as posted, which is a separate cross-system synchronization behavior not reflected in the manifest description.

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

python
# ── Notion helpers ──────────────────────────────────────────────────────────
def notion_query_database(db_id, filter_props=None):
    url = f"https://api.notion.com/v1/databases/{db_id}/query"
    payload = {"page_size": 100}
    if filter_props:
        payload["filter"] = filter_props

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

python
# ── Notion helpers ──────────────────────────────────────────────────────────
def notion_query_database(db_id, filter_props=None):
    url = f"https://api.notion.com/v1/databases/{db_id}/query"
    payload = {"page_size": 100}
    if filter_props:
        payload["filter"] = filter_props

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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/content360_sync.py (reported line 260)May include surrounding context.

python
payload = {"page_size": 100}
    if filter_props:
        payload["filter"] = filter_props
    resp = requests.post(
        url,
        headers={
            "Authorization": f"Bearer {NOTION_API_KEY}",

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script can create posts in Content360 and mark records as posted in Notion immediately when run without --dry-run, with no interactive confirmation, approval gate, or environment safeguard. In an automation context, a mistaken invocation, bad data in Notion, or compromised execution environment could trigger unintended publishing workflow changes at scale.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill description and endpoint list include live-content actions such as publish, schedule, approve, delete, and webhook management, but the documentation does not prominently warn that these operations can affect production social accounts and delete data. In an agent context, insufficient guardrails around high-impact actions increase the chance of accidental destructive changes or unintended publication.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
75% confidence
Finding

The manifest focuses on creating, scheduling, publishing, analytics, media upload, and inbox management. The README explicitly states that post deletion is built and verified, which is a destructive content-management capability not clearly covered by the manifest’s stated scope.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The documentation instructs users to store bearer tokens, email, and password as secrets but omits operational warnings about sensitivity, least privilege, rotation, and avoiding plaintext exposure. While this is not credential theft by itself, poor secret-handling guidance in agent-integrated tooling raises the likelihood of accidental leakage or misuse.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest describes a skill for interacting with Content360 itself: creating, scheduling, publishing, analytics, media upload, and inbox management. However, the file also states that the sync script reads from a Notion content calendar and uses that external system as an input source, which is a meaningful behavioral extension beyond the declared Content360-only scope.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

A skill whose stated purpose is integrating with Content360 would obviously need Content360 authentication and API operations. Requiring a Notion content calendar schema and reading external planning data introduces an additional cross-service capability that is not declared in the manifest description.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.