seo-ahrefs
An Ahrefs API analyst skill. It reads referring domains, backlinks, organic keywords and Content Explorer data through the pinned @ahrefs/[email protected] MCP server, and pairs with seo-backlinks for multi-source confidence weighting.
Why it's held
Changes the agent's instructions or settings. Touches cloud credentials. Contains characters that reorder text.
What it can touch
| files | write, including SSH keys (~/.ssh), cloud credentials (~/.aws, gcloud, kube), every environment variable, MATOMO_URL / MATOMO_API_TOKEN / MATOMO_SITE_ID, Google API key, OAuth token and service account JSON referenced from ~/.config/codex-seo/google-api.json, ~/.codex/config.toml, ~/.codex/settings.json, ~/.agents/skills/, ~/.config/codex-seo/google-api.json, ~/.config/codex-seo/matomo.json, ~/.cache/codex-seo/drift/baselines.db, ~/.banana/pricing.json |
|---|---|
| network | 1.1.1.1, 10.0.0.1, 10.0.0.5, 10.0.0.6, 10.0.0.7, 100.100.100.200, 100.101.102.103, 169.254.169.254, 192.168.1.1, 192.168.1.10, 93.184.216.34, a.test, accounts.google.com, acme.example, acme.test, ads.google.com, agricidaniel.com, ahrefs.com, ai.google.dev, aistudio.google.com, amzn.to, api.dataforseo.com, api.geoapify.com, api.github.com, api.indexnow.org and 96 more |
| shell | runs commands |
| secrets | AHREFS_API_TOKEN, AHREFS_TOKEN, BING_KEY, BING_WEBMASTER_API_KEY, CODEX_SEO_SECRET, DATAFORSEO_PASSWORD, DFSE_PASSWORD, FIRECRAWL_API_KEY, GOOGLE_AI_API_KEY, GOOGLE_API_KEY, GOOGLE_APPLICATION_CREDENTIALS, INDEXNOW_KEY, INDEXNOW_KEY_LOCATION, KEYWORDSEVERYWHERE_API_KEY, MATOMO_API_TOKEN, MATOMO_TOKEN, MOZ_API_KEY, PROFOUND_API_KEY, PROFOUND_KEY, SERANKING_API_KEY, SR_KEY |
What it actually does
The bundle is the whole codex-seo suite (v2.5.0), not just the Ahrefs skill. It ships about 30 SEO skills plus optional extensions for Ahrefs, DataForSEO, Firecrawl, Banana/Gemini image generation, Bing Webmaster/IndexNow, Matomo, Profound, SE Ranking and Unlighthouse. The skills tell the agent to run bundled Python scripts through "${CODEX_SEO_ROOT}/scripts/codex-seo" run <script>.py. Those scripts fetch pages (behind a url_safety SSRF guard), call vendor and Google APIs, write audit artifacts into the working directory and store drift baselines in a local SQLite file. The extension installers prompt for vendor API tokens, pre-warm npm MCP packages with npx --yes, copy SKILL.md files into ~/.agents/skills/, and merge MCP server entries holding those tokens into ~/.codex/config.toml, which they then chmod 0600. Every shown SKILL.md ends with a Security section telling the agent to treat fetched content as untrusted data. The visible files contain no hidden instructions, no exfiltration and no persistence beyond normal skill and MCP registration.
What the check found
highTouches SSH keys
Reads private SSH key files or points the agent at them. Very few agent tools have a reason to.
.gitignore:188 id_rsa
.gitignore:189 id_rsa.*
.gitignore:190 id_ed25519
highChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
extensions/ahrefs/docs/AHREFS-SETUP.md:23 5. Atomically writes `mcpServers.ahrefs` into `~/.codex/config.toml`
highChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
extensions/banana/docs/BANANA-SETUP.md:16 add to `~/.codex/config.toml`:
highChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
extensions/banana/scripts/setup_mcp.py:47 """Write ~/.codex/config.toml atomically.
highChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
extensions/dataforseo/docs/DATAFORSEO-SETUP.md:45 If the installer's auto-configuration fails, add this to `~/.codex/config.toml`:
highChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
extensions/dataforseo/install.ps1:78 # MCP servers live in ~/.codex/config.toml (the file `codex mcp add` writes).
extensions/dataforseo/install.ps1:111 Write-Host " [OK] MCP server configured in ~/.codex/config.toml" -ForegroundColor Green
extensions/dataforseo/install.ps1:112 Write-Host " [OK] MCP server configured in ~/.codex/config.toml" -ForegroundColor Green
highChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
extensions/dataforseo/uninstall.ps1:31 Write-Host " [OK] Removed dataforseo from ~/.codex/config.toml" -ForegroundColor Green
extensions/dataforseo/uninstall.ps1:33 Write-Host " [!] Could not auto-remove MCP config. Remove 'dataforseo' from ~/.codex/config.toml manually." -ForegroundColor Yellow
extensions/dataforseo/uninstall.ps1:36 Write-Host " [!] codex_config.py not found. Remove 'dataforseo' from ~/.codex/config.toml manually." -ForegroundColor Yellow
highChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
extensions/firecrawl/docs/FIRECRAWL-SETUP.md:22 If the installer fails, add this to `~/.codex/config.toml` manually:
highChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
extensions/firecrawl/uninstall.ps1:19 Write-Host "v Removed MCP server from ~/.codex/config.toml" -ForegroundColor Green
highTouches cloud credentials
Reads cloud login files such as ~/.aws/credentials, gcloud or kube config, or points the agent at them.
scripts/google_auth.py:197 config_dir = os.path.expanduser("~/.config/gcloud")
scripts/google_auth.py:198 return os.path.join(config_dir, "application_default_credentials.json")
highContains characters that reorder text
Bidirectional control characters can make text or code read differently from how it runs.
tests/test_content_humanize.py:54 cleaned, removed = strip_invisible("safe⟦U+202E⟧vil")
highTouches cloud credentials
Reads cloud login files such as ~/.aws/credentials, gcloud or kube config, or points the agent at them.
tests/test_google_gcloud_adc.py:22 (tmp_path / "application_default_credentials.json").write_text(json.dumps(data))
mediumDownloads a script and runs it straight away
Piping a download into a shell runs code nobody reviewed, and the download can change after this check.
CHANGELOG.md:1084 `curl -fsSL .../install.sh | bash` got the April 14 release, missing FLOW
CHANGELOG.md:1342 - **Supply chain risk in docs**: removed deprecated `irm | iex` pattern from docs/INSTALLATION.md, replaced with safe `git clone` + `powershell -File` method
CHANGELOG.md:1505 - **Install script supply chain fix**: Replaced `irm | iex` Windows PowerShell one-liner with `git clone + powershell -File` as primary install method. Codex CL
mediumChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
CHANGELOG.md:630 not fix it. They now write `~/.codex/config.toml` (the file `codex mcp add`
CHANGELOG.md:635 setup_mcp.py` now write `~/.codex/config.toml` atomically (temp file in the same
mediumDownloads a script and runs it straight away
Piping a download into a shell runs code nobody reviewed, and the download can change after this check.
SECURITY.md:48 2. **Tampered install.** A modified plugin install, GitHub release, or manual install script could deliver altered files. Plugin install is the default path; `c
mediumChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
SECURITY.md:93 - Install scripts write only to user-level directories under `~/.codex/` and `~/.config/codex-seo/`.
mediumDownloads a script and runs it straight away
Piping a download into a shell runs code nobody reviewed, and the download can change after this check.
docs/INSTALLATION.md:52 The Windows path uses `git clone` rather than `irm | iex` because piped remote-script execution is a supply chain risk. Inspect `install.ps1` before running.
docs/INSTALLATION.md:128 curl -fsSL https://raw.githubusercontent.com/zhtyyx/codex-seo/main/uninstall.sh | bash
docs/INSTALLATION.md:131 curl -fsSL https://raw.githubusercontent.com/zhtyyx/codex-seo/main/install.sh | bash
mediumDownloads a script and runs it straight away
Piping a download into a shell runs code nobody reviewed, and the download can change after this check.
docs/MIGRATION-v1-to-v2.md:168 curl -fsSL https://raw.githubusercontent.com/zhtyyx/codex-seo/main/install.sh | bash
mediumDownloads a script and runs it straight away
Piping a download into a shell runs code nobody reviewed, and the download can change after this check.
docs/TROUBLESHOOTING.md:39 curl -fsSL https://raw.githubusercontent.com/zhtyyx/codex-seo/main/install.sh | bash
mediumChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
extensions/ahrefs/install.ps1:16 # MCP servers live in ~/.codex/config.toml (the file `codex mcp add` writes).
mediumDownloads a script and runs it straight away
Piping a download into a shell runs code nobody reviewed, and the download can change after this check.
extensions/ahrefs/install.sh:30 echo " Install it first: curl -fsSL https://raw.githubusercontent.com/zhtyyx/codex-seo/main/install.sh | bash"
extensions/ahrefs/install.sh:35 # `./install.sh` and `curl | bash` invocations.
mediumChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
extensions/ahrefs/install.sh:12 # MCP servers live in ~/.codex/config.toml (the file `codex mcp add` writes).
mediumDownloads a script and runs it straight away
Piping a download into a shell runs code nobody reviewed, and the download can change after this check.
extensions/banana/install.sh:25 echo " Install it first: curl -fsSL https://raw.githubusercontent.com/zhtyyx/codex-seo/main/install.sh | bash"
mediumChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
extensions/banana/install.sh:11 # MCP servers live in ~/.codex/config.toml (the file `codex mcp add` writes).
mediumDownloads a script and runs it straight away
Piping a download into a shell runs code nobody reviewed, and the download can change after this check.
extensions/dataforseo/install.ps1:16 Write-Host " Install it first: irm https://raw.githubusercontent.com/zhtyyx/codex-seo/main/install.ps1 | iex"
mediumDownloads a script and runs it straight away
Piping a download into a shell runs code nobody reviewed, and the download can change after this check.
extensions/dataforseo/install.sh:33 echo " Install it first: curl -fsSL https://raw.githubusercontent.com/zhtyyx/codex-seo/main/install.sh | bash"
extensions/dataforseo/install.sh:77 # Determine script directory (works for both ./install.sh and curl|bash)
mediumChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
extensions/dataforseo/install.sh:11 # MCP servers live in ~/.codex/config.toml (the file `codex mcp add` writes).
extensions/dataforseo/install.sh:127 echo " Add the dataforseo server manually to ~/.codex/config.toml"
mediumDownloads a script and runs it straight away
Piping a download into a shell runs code nobody reviewed, and the download can change after this check.
extensions/firecrawl/install.ps1:20 Write-Host " Install it first: irm https://raw.githubusercontent.com/zhtyyx/codex-seo/main/install.ps1 | iex"
mediumChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
extensions/firecrawl/install.ps1:12 # MCP servers live in ~/.codex/config.toml (the file `codex mcp add` writes).
mediumDownloads a script and runs it straight away
Piping a download into a shell runs code nobody reviewed, and the download can change after this check.
extensions/firecrawl/install.sh:25 echo " Install it first: curl -fsSL https://raw.githubusercontent.com/zhtyyx/codex-seo/main/install.sh | bash"
extensions/firecrawl/install.sh:64 # Determine script directory (works for both ./install.sh and curl|bash)
mediumChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
extensions/firecrawl/install.sh:11 # MCP servers live in ~/.codex/config.toml (the file `codex mcp add` writes).
extensions/firecrawl/install.sh:101 echo " Add the firecrawl-mcp server manually to ~/.codex/config.toml"
mediumDownloads a script and runs it straight away
Piping a download into a shell runs code nobody reviewed, and the download can change after this check.
extensions/unlighthouse/install.sh:20 # Support both traditional (curl|bash → ~/.agents/skills/seo) and marketplace
mediumContains invisible characters
Zero-width and other invisible characters can hide words or split them so filters and reviewers miss them.
tests/test_agentic.py:501 "⟦U+FEFF⟧User-agent: GPTBot\r\nUser-agent: CCBot\r\nDisallow: /\r\n",
mediumChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
tests/test_banana_setup_mcp_atomic_write.py:1 """Regression tests for setup_mcp.py's atomic ~/.codex/config.toml write.
mediumContains invisible characters
Zero-width and other invisible characters can hide words or split them so filters and reviewers miss them.
tests/test_content_humanize.py:12 cleaned, removed = strip_invisible("wat⟦U+200B⟧er⟦U+200B⟧mark")
tests/test_content_humanize.py:61 result = humanize("Let's del⟦U+200B⟧ve into roofing.")
mediumGoes through every environment variable
Reads the whole environment, usually to pass it on to another program. Together with a webhook or paste-site address it is how credential stealers work.
tests/test_dataforseo_costs.py:176 env = {k: v for k, v in os.environ.items() if not k.startswith("DATAFORSEO_")}
mediumChanges the agent's instructions or settings
Editing CLAUDE.md, AGENTS.md, memory files, hooks or MCP settings lets a tool keep steering the agent even after it's removed.
tests/test_firecrawl_install_atomic_write.py:1 """Static contract for the PowerShell installers' ~/.codex/config.toml writes.
tests/test_firecrawl_install_atomic_write.py:6 that touches ~/.codex/config.toml routes the write through
mediumContains invisible characters
Zero-width and other invisible characters can hide words or split them so filters and reviewers miss them.
tests/test_hostile_inputs.py:128 path.write_text("⟦U+FEFF⟧" + fixture, encoding="utf-8")
tests/test_hostile_inputs.py:137 body = "⟦U+FEFF⟧Café".encode("utf-16-le")
mediumTalks to a bare IP address
Contacts a server by its IP address instead of a name, which hides who runs it.
tests/test_matomo_report.py:691 assert not matomo_auth.resolves_to_private_address("https://93.184.216.34")
mediumTalks to a bare IP address
Contacts a server by its IP address instead of a name, which hides who runs it.
tests/test_url_safety.py:168 "http://1.1.1.1",
tests/test_url_safety.py:203 url, ip = url_safety.validate_url_strict("https://1.1.1.1/")
tests/test_url_safety.py:205 assert url == "https://1.1.1.1/"
mediumInstallers write MCP server entries with plaintext API tokens into the agent config
The extension installers merge MCP server definitions into ~/.codex/config.toml and put the user's vendor tokens in the env block. That is how these tools register and it is expected for their purpose. Still, it changes the agent's configuration and stores credentials on disk. The docs say the file is chmod 0600 afterwards. The installer scripts themselves were omitted, so this behaviour could not be verified line by line.
extensions/ahrefs/docs/AHREFS-SETUP.md:23 5. Atomically writes `mcpServers.ahrefs` into `~/.codex/config.toml`
extensions/ahrefs/docs/AHREFS-SETUP.md:24 with your token in the `env` block. The settings file is `chmod 0o600`
mediumInstallers download and run third-party npm MCP packages with npx --yes
The extensions run third-party npm packages, pinned to versions such as @ahrefs/[email protected] and [email protected], and npx --yes runs them without a prompt. Pinning reduces the risk but does not remove it. Several installers and docs also trigger pipe-to-shell rule hits, and those files were not provided for inspection.
extensions/ahrefs/docs/AHREFS-SETUP.md:20 3. Pre-warms the `@ahrefs/[email protected]` npm package via `npx --yes` so the first
extensions/ahrefs/skills/seo-ahrefs/SKILL.md:6 compatibility: "Tested with @ahrefs/[email protected] (installed by extensions/ahrefs/install.sh)."
mediumRuntime sync of prompt files from GitHub that the agent then applies
`$seo flow sync` downloads the latest prompt files from a third-party GitHub repo, and the flow commands tell the agent to read those files and apply each prompt. If that repo changed, it could alter agent behaviour after this review. A lock file exists but was omitted, so its enforcement could not be checked. This is consistent with the stated purpose, but it is unreviewed remote instruction content.
skills/seo-flow/SKILL.md:40 | `$seo flow sync` | Pull latest prompt files from github.com/AgriciDaniel/flow |
skills/seo-flow/SKILL.md:52 1. Read all files in `references/prompts/find/`
skills/seo-flow/SKILL.md:53 2. Apply each prompt to the URL or topic
mediumInstallers download and run npm packages via npx; installer scripts not visible
The Ahrefs installer, and by the rule hits the Firecrawl, DataForSEO, Banana and Unlighthouse installers, fetch and run npm packages with `npx --yes`. The version is pinned (@ahrefs/[email protected]), which reduces risk. The install.sh and install.ps1 files themselves were omitted from the bundle, so the pipe-to-shell rule hits could not be verified line by line. A human should read them before listing.
extensions/ahrefs/docs/AHREFS-SETUP.md:20 3. Pre-warms the `@ahrefs/[email protected]` npm package via `npx --yes` so the first
extensions/ahrefs/docs/AHREFS-SETUP.md:36 Re-run the installer to pre-warm or run `npx --yes --package=@ahrefs/[email protected] mcp --help` manually.
mediumInstallers register MCP servers and store tokens in the agent's config
The installer copies skill files into the agent's skills directory and writes an MCP server entry, with the API token in its env block, into ~/.codex/config.toml. This is expected for an MCP-backed extension, and the docs say the file is chmod 0600 and that an uninstaller clears the entry. It is still a change to the agent's configuration that the user should know about.
extensions/ahrefs/docs/AHREFS-SETUP.md:22 4. Copies `skills/seo-ahrefs/SKILL.md` into `~/.agents/skills/seo-ahrefs/`.
extensions/ahrefs/docs/AHREFS-SETUP.md:23 5. Atomically writes `mcpServers.ahrefs` into `~/.codex/config.toml`
extensions/ahrefs/docs/AHREFS-SETUP.md:24 with your token in the `env` block. The settings file is `chmod 0o600`
Keep an eye on it
This check is of one commit. Watch seo-ahrefs and we'll email you if a later commit changes what it can touch.
About this check
Checked November 2, 2026 at commit f8fcfad14c89, 440 files. Rules for known red flags, then two Claude reviews, one of them told to assume the author is malicious. A later commit hasn't been checked. How checks work.