Back to skill

Security audit

Influencer Report

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated influencer-vetting purpose, but it needs Review because it can process unrelated videos from the user's Memories.ai library and retrieves results through an under-disclosed endpoint.

Before installing, use only isolated Memories.ai API keys or libraries for the specific creator/job being reviewed. Assume creator URLs, video URLs, transcripts, visual descriptions, and metadata may be sent to Memories.ai services and demo.memories-ai.org. Avoid confidential campaign research until the skill scopes library reads to the current scrape task and documents or secures result retrieval.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/influencer_report.py:200
Finding
Analysis Results Retrieved Through an Undocumented Unauthenticated Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/influencer_report.py`, lines 200-208 **Vulnerability Type**: Unauthenticated access to potentially sensitive analysis results **Risk Level**: Medium ### Vulnerable Code ```python def poll_result(task_id: str) -> Optional[dict]: """Poll webhook results endpoint for task completion.""" webhook_url = f"https://demo.memories-ai.org/webhooks/memories/result/{task_id}" print(f"[Poll] Waiting for task {task_id}...") for attempt in range(int(POLL_TIMEOUT / POLL_INTERVAL)): time.sleep(POLL_INTERVAL) try: resp = requests.get(webhook_url, timeout=15) ``` ### Technical Analysis The Skill submits videos to authenticated Memories.ai API endpoints but retrieves the resulting transcript and visual analysis from a separate `demo.memories-ai.org` endpoint. The polling request does not include an authorization credential or other proof that the requesting user owns the task. Consequently, access control appears to depend on possession and confidentiality of `task_id`. Task identifiers are embedded in URL paths and printed to standard output elsewhere in the workflow. URL paths and console output may be captured by browser history, reverse proxies, observability systems, terminal logs, CI logs, or support diagnostics. The separate result-service domain is also not disclosed in `SKILL.md`, which only documents the Memories.ai V1 and V2 API endpoints. This creates an unexpected trust boundary for transcript and visual-analysis data. ### Attack Path 1. A user submits a video for MAI transcript analysis. 2. The API returns a task identifier, which the script prints to its output. 3. The script constructs the result URL as: `https://demo.memories-ai.org/webhooks/memories/result/{task_id}`. 4. The task identifier is exposed through shared console output, application logs, proxy logs, monitoring data, or another disclosure channel. 5. A party possessing the identifier se ...[truncated 892 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Retrieve results through an authenticated, officially documented Memories.ai API endpoint. 2. Include authorization in a request header rather than relying on task-identifier secrecy. 3. Require the result service to verify that the authenticated account owns the requested task. 4. Avoid placing sensitive or reusable identifiers in URL paths where they may be logged. 5. Stop printing complete task identifiers, or redact them in application output. 6. Document every external domain that receives or returns user-related data. 7. Validate TLS certificates normally and restrict outbound requests to an explicit allowlist of approved production domains. 8. If an unauthenticated webhook-result endpoint is unavoidable, use short-lived, cryptographically random, single-use tokens and expire result records promptly. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/influencer_report.py:101
Finding
Account-Wide Video Library Access Exceeds the Scope of the Requested Profile<![CDATA[ ## Vulnerability Details **File Location**: `scripts/influencer_report.py`, lines 101-115 and 348-357 **Vulnerability Type**: Excessive data access and cross-profile data selection **Risk Level**: Medium ### Vulnerable Code The library function requests all videos using an empty request body: ```python def v1_list_videos(v1_key: str) -> list[dict]: """List all videos in the V1 library.""" url = f"{V1_BASE}/list_videos" headers = {"Authorization": v1_key, "Content-Type": "application/json"} print("[V1] Listing videos in library...") try: resp = requests.post(url, headers=headers, json={}, timeout=30) resp.raise_for_status() data = resp.json() videos = data.get("data", []) if isinstance(videos, dict): videos = videos.get("videos", []) print(f"[V1] Found {len(videos)} videos in library") return videos ``` The calling workflow then selects the first entries without verifying that they belong to the requested profile or scraper task: ```python # Step 2: List videos all_videos = v1_list_videos(v1_key) # Step 3: Search for relevant content search_results = v1_search("creator talking to camera", v1_key, top_k=args.scrape_count) # Extract video URLs from library for v in all_videos[:args.scrape_count]: url = v.get("video_url") or v.get("url") or v.get("videoUrl", "") if url: video_urls.append(url) ``` ### Technical Analysis The declared operation is to vet a specific creator. After initiating a profile scrape, however, the implementation invokes the account-level `/list_videos` endpoint with no profile, task, creator, or ingestion filter. It therefore requests all video records available to the supplied V1 API key. The script then takes the first `scrape_count` records from that shared library. It does not verify that those records: - Were produced by the scraper task started ...[truncated 2000 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Retrieve videos using the scraper task identifier returned by `v1_scrape`. 2. Prefer an API endpoint that returns only records created by the current scraper task. 3. If the API supports filters, require an exact profile URL, creator identifier, platform, and ingestion-time filter. 4. Verify every returned video against the requested profile before submitting it to V2 analysis. 5. Do not fall back to the first records in an account-wide library. 6. Scope search requests to the current creator or task instead of using only a generic semantic query. 7. Reject ambiguous results rather than silently incorporating potentially unrelated content. 8. Use a dedicated, minimally privileged API key or isolated library for each tenant or workflow where server-side scoping is unavailable. 9. Add tests covering libraries containing multiple creators and ensure that only records associated with the requested profile enter the report. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (12)

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill advertises capabilities that imply environment-variable access, file writing, and network use, but it does not declare any explicit tool scope or permissions boundaries. That makes the execution surface ambiguous and can allow an agent to invoke the skill more broadly than intended, increasing the risk of unauthorized external requests, secret exposure, or local file modification.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The activation language is broad enough to match generic requests like 'analyze' or 'review' an influencer, without clearly defining when the skill should or should not run. Over-broad triggering can cause unintended invocation of a networked skill that scrapes and sends third-party content to external APIs, creating privacy, consent, and data-handling risks.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The skill description and workflow omit a clear disclosure that creator profile URLs, video URLs, and associated content are transmitted to external Memories.ai APIs for scraping, transcript generation, and metadata analysis. Users may unknowingly cause third-party data to be sent off-platform, which is especially sensitive in a vetting context involving reputational analysis and potentially large batches of creator content.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The report directly embeds AI-produced audio transcript and visual-analysis text into markdown output without any sanitization, warning, or sensitivity gating. In an influencer-vetting context, these fields can contain personal, defamatory, explicit, or otherwise sensitive generated content, which may be surfaced to end users as if it were safe to share, increasing privacy, reputational, and compliance risk.

External Transmission

Medium
Category
Data Exfiltration
Content
# Config
# ---------------------------------------------------------------------------

V1_BASE = "https://api.memories.ai/serve/api/v1"
V2_BASE = "https://mavi-backend.memories.ai/serve/api/v2"

PLATFORM_MAI_ENDPOINTS = {
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script sends user-supplied creator profile URLs to a third-party scraping API, and later transmits discovered video URLs to additional third-party analysis endpoints. In the context of a vetting/report skill this data flow is expected, but the lack of explicit consent, privacy notice, or destination disclosure means users may unintentionally expose sensitive targets, private campaign research, or non-public creator lists to an external service.

External Transmission

Medium
Category
Data Exfiltration
Content
print(f"[V1] Scraping profile: {profile_url} (count={count})...")
    try:
        resp = requests.post(url, headers=headers, json=payload, timeout=30)
        resp.raise_for_status()
        data = resp.json()
        if data.get("code") == "0000":
Confidence
93% confidence
Finding
This request transmits the supplied profile URL to an external scraping service, which is a real data exfiltration boundary. Given the skill's purpose, this is intended behavior, but it still creates privacy and data-governance risk because user input is sent off-platform without strong notice or scoping controls.

External Transmission

Medium
Category
Data Exfiltration
Content
print("[V1] Listing videos in library...")
    try:
        resp = requests.post(url, headers=headers, json={}, timeout=30)
        resp.raise_for_status()
        data = resp.json()
        videos = data.get("data", [])
Confidence
88% confidence
Finding
Listing videos from the external Memories.ai library causes the skill to retrieve potentially sensitive previously ingested content from a third-party service. In a multi-user or shared-key environment, this can expose unrelated library contents and broaden data access beyond the specific influencer being vetted.

External Transmission

Medium
Category
Data Exfiltration
Content
print(f"[V1] Searching: '{query}'...")
    try:
        resp = requests.post(url, headers=headers, json=payload, timeout=30)
        resp.raise_for_status()
        data = resp.json()
        results = data.get("data", [])
Confidence
85% confidence
Finding
The script performs a remote search over the external video library using a generic query, which may pull in unrelated content and expand disclosure beyond the requested creator. In context this is not malicious, but it is a real confidentiality and over-collection risk because the search is not tightly bound to the user-provided target.

External Transmission

Medium
Category
Data Exfiltration
Content
print(f"[V2] Submitting MAI transcript: {video_url[:80]}...")
    try:
        resp = requests.post(url, headers=headers, json={"video_url": video_url}, timeout=30)
        resp.raise_for_status()
        data = resp.json()
        if data.get("code") == "0000":
Confidence
95% confidence
Finding
This request sends full video URLs to a third-party MAI transcript endpoint for deep visual/audio analysis. Because videos may reveal unpublished content, campaign plans, or sensitive moderation targets, transmitting them externally without explicit notice and controls presents a meaningful privacy and data-sharing risk.

External Transmission

Medium
Category
Data Exfiltration
Content
print(f"[V2] Fetching metadata: {video_url[:80]}...")
    try:
        resp = requests.post(url, headers=headers,
                             json={"video_url": video_url, "channel": "rapid"}, timeout=30)
        resp.raise_for_status()
        data = resp.json()
Confidence
93% confidence
Finding
The metadata call also transmits video URLs to a third-party backend and may enrich them with engagement or channel information, increasing the amount of externalized data. Within this skill that is functional, but it still represents a true external data transfer risk that users may not expect from a simple vetting command.

Missing User Warnings

Low
Confidence
86% confidence
Finding
The code requires MEMORIES_V1_API_KEY and MEMORIES_API_KEY from the environment and uses them for authenticated API calls. Although the docstring lists the variables, it does not warn users that the skill reads credentials from the environment, which is a safety-relevant behavior under the missing-warning criteria for sensitive environment variable access.

Static analysis

No suspicious patterns detected.