Back to skill

Security audit

Instagram Analyzer

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly an Instagram analytics scraper, but it leaves user-controlled URLs and usernames too broad, creating review-worthy network and file-writing risks.

Review this skill before installing. Use it only with trusted Instagram usernames and Instagram post/Reel URLs, avoid supplying arbitrary URLs, keep outputs in a controlled directory, and do not store real Instagram credentials in shared folders or source control. A safer version should validate Instagram hosts and username syntax, constrain output paths, document privacy/retention expectations, and pin dependencies.

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

Error
Location
scripts/instagram_analyzer.py:128
Finding
Unrestricted Browser Navigation Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/instagram_analyzer.py`, lines 128-144 **Vulnerability Type**: Server-Side Request Forgery through unrestricted URL navigation **Risk Level**: High ### Vulnerable Code ```python def analyze_post(self, post_url: str, output_format: str = "json") -> dict: """Analyze a single Instagram post/Reel""" result = { "url": post_url, "post_type": "reel" if "/reel/" in post_url else "post", "username": "", "metrics": {}, "ratios": {}, "timing": {}, "error": None, "timestamp": datetime.utcnow().isoformat() } print(f"📊 Analyzing: {post_url}") with sync_playwright() as p: browser = p.chromium.launch(headless=self.config["scraper"]["headless"]) context = browser.new_context( user_agent=self.config["browser"]["user_agent"], viewport={"width": 390, "height": 844} ) page = context.new_page() try: page.goto(post_url, timeout=self.config["scraper"]["timeout"]) ``` ### Technical Analysis The `post_url` argument is controlled by the caller and is passed directly to Playwright's `page.goto()` method. The implementation does not validate the URL scheme, hostname, port, resolved IP address, or redirect destination. Although the command is documented as accepting Instagram post URLs, no code enforces that restriction. A caller can therefore direct Chromium to HTTP services available from the Skill's execution environment, including localhost, private network addresses, link-local services, or arbitrary external websites. Using a browser rather than a basic HTTP client does not prevent SSRF. Chromium still issues requests with the network access available to the host process and may follow redirects to otherwise prohibited destinations. ### Attack Path 1. An attacker invokes `analyze-post` with a URL that targets an internal service rather than Instagram. 2. ` ...[truncated 878 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse the supplied URL with a standards-compliant URL parser. 2. Require the `https` scheme. 3. Allow only explicitly approved Instagram hosts, such as `www.instagram.com` and `instagram.com`. 4. Reject embedded credentials, unexpected ports, malformed hostnames, and non-HTTP schemes. 5. Resolve the hostname and reject loopback, private, link-local, multicast, reserved, and unspecified IP ranges for both IPv4 and IPv6. 6. Disable automatic redirects or validate the scheme, hostname, and resolved address after every redirect. 7. Normalize hostnames before comparison to prevent case, trailing-dot, and internationalized-domain bypasses. 8. Apply outbound network restrictions at the container or firewall layer so the process cannot reach internal infrastructure unnecessarily. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/instagram_analyzer.py:352
Finding
Profile Username Allows Output Path Traversal and Unauthorized File Creation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/instagram_analyzer.py`, lines 352-354 **Vulnerability Type**: Path traversal in an output filename **Risk Level**: High ### Vulnerable Code ```python # Save results output_file = self.data_dir / "profiles" / f"{username}_{int(time.time())}.json" output_file.parent.mkdir(exist_ok=True) with open(output_file, 'w') as f: json.dump(result, f, indent=2) ``` The same unvalidated value is received through the CLI: ```python profile_parser.add_argument("username", help="Instagram username") ``` ### Technical Analysis The caller-controlled `username` is directly embedded in a filesystem path. No validation restricts the value to the character set and length permitted for Instagram usernames. A username containing `../` path components can cause the resulting path to escape the intended `data/profiles` directory. If the formatted filename begins with an absolute path, `pathlib` can also discard the preceding base path components. The timestamp and `.json` suffix make exact overwrite targeting more difficult, but they do not prevent unauthorized file creation outside the configured output directory. The code does not resolve the completed path and verify that it remains beneath the intended output root before opening the file. ### Attack Path 1. An attacker supplies a profile username containing traversal components or an absolute path. 2. The value is retained unchanged by the argument parser. 3. Profile processing uses the same value and eventually reaches the result-saving operation. 4. `pathlib` constructs a path that may resolve outside `data/profiles`. 5. The process creates and writes a timestamped JSON file using its filesystem privileges. ### Impact Assessment An attacker can create JSON files outside the intended profile-output directory wherever the Skill process has write permission. This can pollute application directories, temporary locations, shared writable directories, or other ...[truncated 376 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Validate usernames against Instagram's permitted username syntax and maximum length before using them in URLs or filenames. 2. Reject path separators, traversal components, control characters, absolute paths, and platform-specific reserved names. 3. Generate output filenames from a sanitized identifier or a cryptographic hash rather than raw caller input. 4. Resolve both the output root and candidate destination with `Path.resolve()`. 5. Verify with `Path.relative_to()` or an equivalent containment check that the destination remains beneath the resolved profile-output directory. 6. Create files with restrictive permissions and fail if the containment check does not pass. 7. Apply the same validation to the Reels filename at `scripts/instagram_analyzer.py:361-364`, which also incorporates the username into an output path. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:18
Finding
Mutable and Unverified Dependency Resolution Creates Supply-Chain Risk<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 18-21; `requirements.txt`, lines 2-6 **Vulnerability Type**: Unpinned dependencies without integrity verification **Risk Level**: Medium ### Vulnerable Code `SKILL.md` declares automatically installed packages without versions: ```yaml pip: - playwright - beautifulsoup4 - lxml ``` `requirements.txt` uses open-ended lower bounds and does not provide package hashes: ```text playwright>=1.40.0 beautifulsoup4>=4.12.0 lxml>=4.9.0 requests>=2.31.0 python-dateutil>=2.8.0 ``` ### Technical Analysis The Skill's dependency metadata requests installation of mutable package names without exact versions. The requirements file also allows any future release above the specified minimum versions. Neither source provides cryptographic hashes for integrity verification. Consequently, the code installed in a future deployment can differ from the dependency versions reviewed during this audit. Package installation and import may execute third-party build or initialization code with the privileges of the Skill environment. The dependency declarations are also inconsistent: `requests` and `python-dateutil` are present in `requirements.txt` but are not used by the reviewed implementation, unnecessarily expanding the supply-chain attack surface. This finding does not establish that the named packages are currently malicious. It identifies non-reproducible and unverified dependency resolution that could expose deployments to a compromised, malicious, or incompatible future release. ### Attack Path 1. The Skill is installed or rebuilt after dependency versions have changed. 2. The package resolver selects the latest versions satisfying the unbounded declarations. 3. Package installation processes or imports execute code that was not part of the originally reviewed dependency set. 4. If an upstream release or distribution channel is compromised, attacker-controlled package code executes with the inst ...[truncated 508 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin every direct and transitive dependency to an exact reviewed version. 2. Generate a lock file containing cryptographic hashes and require hash verification during installation. 3. Ensure `SKILL.md` and the installation mechanism use the same locked dependency set. 4. Remove unused dependencies such as `requests` and `python-dateutil` unless they become necessary. 5. Install only from an approved package index over authenticated TLS. 6. Run dependency installation and the Skill itself in an isolated, least-privileged environment. 7. Use automated vulnerability and provenance scanning when updating the lock file. 8. Review dependency changes before permitting automatic upgrades. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (10)

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill explicitly stores scraped profile data, post analytics, and reels links to local files, but provides no guidance on privacy, retention, access control, or lawful handling of potentially personal data. This creates a real security and privacy risk because users may collect and persist identifiable third-party data without understanding storage exposure or compliance obligations.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill instructs users to configure Instagram credentials in a .env file but does not include any warning about secret management, accidental disclosure, or safe storage practices. This is dangerous because users may place live account credentials in insecure locations, commit them to source control, or expose them through logs and shared environments.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This code navigates to user-supplied Instagram URLs using Playwright, which causes network requests to an external service and transmits request metadata such as IP address, headers, and the requested target. Although there is a progress print for the URL being analyzed, there is no user-facing warning or disclosure that the tool performs live external scraping/network access.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# Instagram Analyzer Dependencies
playwright>=1.40.0
beautifulsoup4>=4.12.0
lxml>=4.9.0
requests>=2.31.0
Confidence
97% confidence
Finding
The dependency is specified with a lower bound only, which permits installation of any newer version, making builds non-reproducible and increasing supply-chain risk if a later release introduces a vulnerability or breaking change. In a security-sensitive automation skill, this weakens assurance that the tested dependency set is the one actually deployed.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# Instagram Analyzer Dependencies
playwright>=1.40.0
beautifulsoup4>=4.12.0
lxml>=4.9.0
requests>=2.31.0
python-dateutil>=2.8.0
Confidence
97% confidence
Finding
The dependency is specified with a lower bound only, which permits installation of any newer version, making builds non-reproducible and increasing supply-chain risk if a later release introduces a vulnerability or breaking change. In a security-sensitive automation skill, this weakens assurance that the tested dependency set is the one actually deployed.

Unpinned Dependencies

Low
Category
Supply Chain
Content
# Instagram Analyzer Dependencies
playwright>=1.40.0
beautifulsoup4>=4.12.0
lxml>=4.9.0
requests>=2.31.0
python-dateutil>=2.8.0
Confidence
98% confidence
Finding
The dependency is specified with a lower bound only, which permits installation of any newer version, making builds non-reproducible and increasing supply-chain risk if a later release introduces a vulnerability or breaking change. This is more concerning for lxml because it has a history of security advisories, so an unpinned install makes it unclear whether a safe version is consistently used.

Unverifiable Dependency: lxml has 14 known advisory(ies) (CVE-2021-43818 (lxml's HTML Cleaner allows crafted and SVG embedded scripts to pass through); CVE-2014-3146 (lxml Cross-site Scripting Via Control Characters); CVE-2021-28957 (lxml vulnerable to Cross-Site Scripting ) +11 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
94% confidence
Finding
The manifest does not pin lxml, and lxml has multiple historical advisories, so it is impossible to verify from this file whether deployments will use an affected or remediated version. In a parser/library used to process external content, version uncertainty increases the chance that a vulnerable release could be installed unnoticed.

Unpinned Dependencies

Low
Category
Supply Chain
Content
playwright>=1.40.0
beautifulsoup4>=4.12.0
lxml>=4.9.0
requests>=2.31.0
python-dateutil>=2.8.0
Confidence
98% confidence
Finding
The dependency is specified with a lower bound only, which permits installation of any newer version, making builds non-reproducible and increasing supply-chain risk if a later release introduces a vulnerability or breaking change. This is somewhat more significant for requests because it is commonly used for network communication and has had multiple advisories, so version ambiguity reduces confidence in transport-layer safety.

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
95% confidence
Finding
The manifest does not pin requests, and requests has several known advisories, so the actual installed version cannot be assessed for exposure from this file alone. Because requests handles outbound HTTP and may process redirects, auth, and URL parsing, unresolved version selection can leave the skill exposed to known client-side issues.

Unpinned Dependencies

Low
Category
Supply Chain
Content
beautifulsoup4>=4.12.0
lxml>=4.9.0
requests>=2.31.0
python-dateutil>=2.8.0
Confidence
96% confidence
Finding
The dependency is specified with a lower bound only, which permits installation of any newer version, making builds non-reproducible and increasing supply-chain risk if a later release introduces a vulnerability or breaking change. Even without known context-specific abuse here, exact version control is a standard hardening measure for reliable and secure builds.

Static analysis

No suspicious patterns detected.