Back to skill

Security audit

canonry

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent Canonry operations guide with broad, sensitive integrations, but the risky actions are disclosed and generally bounded by approval and server-side permission checks.

Install this only if you intend to operate Canonry. Use read-only or stored-only modes where possible, keep ~/.canonry/config.yaml and token/key files private, do not paste secrets into chat, and require explicit approval before writes, ad-spend actions, schedules, public webhooks, Cloudflare route changes, or WordPress content changes.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (19)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
intent routes, the optional resource, and generated Canonry `SKILL.md` files.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/canonry-cli.md (reported line 517)May include surrounding context.

md
uses `GET /projects/:name/content/dismissals`; dismiss uses `POST` with
`targetRef` and optional `addressedUrl` and `note`. Re-dismissing updates those
optional values and the dismissal time. Restore uses
`DELETE /projects/:name/content/dismissals/:targetRef` and returns HTTP 204; CLI and
MCP acknowledge it as `{ targetRef, restored: true }`. A missing record returns
the API's not-found error.

External Model or Provider Selection

High
Category
Excessive Agency
Confidence
90% confidence
Finding

Skill selects an external model or provider that may use a different account or billing plan than the operator expects. Undisclosed model switches can cause unexpected cost or quota consumption.

Content

Scanner excerpt · references/canonry-cli.md (reported line 701)May include surrounding context.

md
cnry settings                                  # show config: providers, apiUrl, db path
cnry settings --format json
cnry settings reload-providers --format json   # apply the server's saved provider config
cnry settings provider gemini --api-key <KEY> --model gemini-flash-latest
cnry settings provider openai --max-per-day 1000 --max-per-minute 20
cnry settings provider perplexity --api-key <KEY> --model fast
cnry settings provider muse --api-key <KEY> --model muse-spark-1.3

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/indexing.md (reported line 94)May include surrounding context.

cnry bing set-site https://example.com/

text

Get API key from: https://www.bing.com/webmasters/ → Settings → API Access

### Check connection and coverage
```bash

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · references/canonry-cli.md (reported line 12)May include surrounding context.

md
in a group. `cnry --help --format json` and `cnry ga --help --format json` provide
the same discovery output. The catalog includes access, flags, dry-run support and
supported rolling windows. Contextual help prints `Access: stored`, `Access: live`
or `Access: write`; live means the command calls a provider now, while write means
it changes server or local state. `--trace` reports the response access header for
API calls. Help is local and does not contact the server.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · references/canonry-cli.md (reported line 1196)May include surrounding context.

md
# One contract joins business meaning to the selected Google Ads action and GTM graph.
cnry conversion-tracking contracts <project> --format jsonl
cnry conversion-tracking contracts get <project> <contract-id>
cnry conversion-tracking contracts create <project> --input contract.json
cnry conversion-tracking contracts update <project> <contract-id> --input contract.json
cnry conversion-tracking contracts delete <project> <contract-id>
cnry conversion-tracking contracts integrity <project> <contract-id> --format jsonl

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · references/canonry-cli.md (reported line 1585)May include surrounding context.

md
return a validation error. Inspect retention/loss counters before assuming
coverage. Use `history` for durable audit
events, with `--limit 1..500 --offset <n>` for traversal. Offset pages are not a
concurrent-write snapshot.

Google setup and telemetry default to local configuration. Pass `--target server`
to use the connected server; settings reads always describe the server.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · references/google-business-profile.md (reported line 111)May include surrounding context.

md
**Account-credential gotcha:** API calls use your **Application Default Credentials** (`gcloud auth application-default login` → `print-access-token`), while `gcloud services enable` uses the separate **gcloud CLI account** (`gcloud config get-value account`). These can be different identities. Verify the token's real account with `curl "https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=$TOKEN"` before concluding anything about access — a "wrong account" symptom is often just the two credential stores disagreeing.

### Create OAuth client credentials

1. Cloud Console → APIs & Services → **OAuth consent screen** → set up consent (External works). Add your own email under "Test users" while the app is in test mode.
2. Cloud Console → APIs & Services → **Credentials** → **+ Create Credentials** → **OAuth client ID**.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The document explicitly tells users to persist a Google OAuth client secret and per-user OAuth tokens in ~/.canonry/config.yaml, and even notes that tokens are stored there, without any warning about file permissions, encryption, OS keychain use, or secret-handling hygiene. If that file is readable by other local users, captured in backups, checked into dotfile sync, or exposed through logs/support bundles, an attacker could reuse refresh tokens or client credentials to access managed Google Business Profile data.

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 · references/indexing.md (reported line 137)May include surrounding context.

Submit URLs:

bash
curl -X POST "https://www.bing.com/indexnow" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{
    "host": "example.com",

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · references/server-side-traffic.md (reported line 82)May include surrounding context.

Connecting a Cloud Run source

bash
# 1. Create a service account in the Cloud project that hosts the Cloud Run
#    service. Grant it `roles/logging.viewer`. Download the JSON key.

# 2. Connect from cnry CLI:

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · references/server-side-traffic.md (reported line 258)May include surrounding context.

hits for the tracked site.

bash
# 1. In the Vercel dashboard, create a token with read access to the
#    target team (Settings → Tokens → Create). Note the team ID
#    (Settings → General → Team ID) and the Vercel project ID
#    (Project → Settings → General → Project ID).

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 · references/server-side-traffic.md (reported line 390)May include surrounding context.

bash
CANONRY_PUBLIC_URL=https://canonry-ops.example.net

curl -sS -o /dev/null -w '%{http_code}\n' \
  -X POST -H 'content-type: application/json' --data '{}' \
  "${CANONRY_PUBLIC_URL%/}/api/v1/projects/<project>/traffic/cloudflare/ingest"

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 · references/server-side-traffic.md (reported line 460)May include surrounding context.

bash
# assets -> no worker. Omitting "script" is what disables it.
curl -s -X POST -H "Authorization: Bearer $CF_TOKEN" -H "Content-Type: application/json" \
  --data '{"pattern":"<host>/_nuxt/*"}' \
  "https://api.cloudflare.com/client/v4/zones/$ZONE/workers/routes"

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · references/server-side-traffic.md (reported line 462)May include surrounding context.

assets -> no worker. Omitting "script" is what disables it.

curl -s -X POST -H "Authorization: Bearer $CF_TOKEN" -H "Content-Type: application/json"
--data '{"pattern":"/_nuxt/*"}'
"https://api.cloudflare.com/client/v4/zones/$ZONE/workers/routes"

text

Prefixes by framework: `/_nuxt/*` Nuxt, `/_next/*` Next.js, plus `/assets/*`,

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · references/server-side-traffic.md (reported line 482)May include surrounding context.

assets -> no worker. Omitting "script" is what disables it.

curl -s -X POST -H "Authorization: Bearer $CF_TOKEN" -H "Content-Type: application/json"
--data '{"pattern":"/_nuxt/*"}'
"https://api.cloudflare.com/client/v4/zones/$ZONE/workers/routes"

text

Prefixes by framework: `/_nuxt/*` Nuxt, `/_next/*` Next.js, plus `/assets/*`,

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 · references/server-side-traffic.md (reported line 687)May include surrounding context.

bash
CANONRY_QUEUE_SMOKE_PATH="/canonry-cloudflare-queue-smoke/$(date -u +%Y%m%dT%H%M%SZ)"

curl -sS -o /dev/null -w '%{http_code}\n' \
  "https://www.example.com${CANONRY_QUEUE_SMOKE_PATH}?utm_source=chatgpt"

sleep 2

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · references/wordpress-integration.md (reported line 7)May include surrounding context.

md
## What Canonry Automates

- Read and write page content, titles, slugs, and status
- Audit pages for `noindex`, missing SEO title, missing meta description, missing schema, and thin content
- Compare live vs staging for a page with `cnry wordpress diff`
- Update SEO meta when the site exposes writable REST meta fields

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

Scanner excerpt · references/canonry-cli.md (reported line 1100)May include surrounding context.

md
Every read command queries persisted DB rows, so a stale `lastSyncedAt` means the response is stale — always check `ga status` before drawing conclusions, and re-`ga sync` if the data is older than the analysis window. Use `--only ai`, `--only social` or `--only search-landing` to refresh just one slice when iterating.

`ga search-landing-pages` reads GA4's Search Console collection, not Canonry's own GSC sync: its clicks come through the GA4 property's Search Console link and can differ from `google performance` for the same days. Active users is GA4's plain `activeUsers` from the same request, which is what GA4's report shows (not limited to Google organic sessions). Search Console data reaches GA4 about two days late, so the last days of each window are thin, exactly as in GA4. A property without a Search Console link is expected to read `unavailable` with Google's message in `error` (inferred, not yet observed from a live unlinked property); the previous snapshot stays readable beside that status.

## Google Business Profile (Local AEO)

Static analysis

No suspicious patterns detected.