← Fastly Agent ToolkitCONTENT HISTORY

Update to Fastly Agent Toolkit

Snapshot Oct 9, 2026 · 18:03 UTC · version 0.1.0

Collection source: downloaded plugin package.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "description": "Performs an internal audit of Fastly Next-Gen WAF (NGWAF) workspaces to audit that critical templated protection rules are configured and enabled. Use when auditing NGWAF workspace security posture, checking for missing or disabled login protection rules (LOGINDISCOVERY, LOGINATTEMPT, LOGINSUCCESS, LOGINFAILURE), auditing credit card validation rules (CC-VAL-ATTEMPT, CC-VAL-FAILURE, CC-VAL-SUCCESS), auditing gift card protection rules (GC-VAL-ATTEMPT, GC-VAL-FAILURE, GC-VAL-SUCCESS), identifying potential login endpoints not covered by NGWAF rules, or comparing attack traffic against blocked traffic to confirm enabled rules are actually blocking.",
  "included_files": [
    {
      "relative_path": "scripts/assess_ngwaf_rules.sh",
      "size_in_bytes": 4038
    }
  ],
  "name": "fastly-ngwaf",
  "skill_md_contents": "---\nname: fastly-ngwaf\ndescription: \"Performs an internal audit of Fastly Next-Gen WAF (NGWAF) workspaces to audit that critical templated protection rules are configured and enabled. Use when auditing NGWAF workspace security posture, checking for missing or disabled login protection rules (LOGINDISCOVERY, LOGINATTEMPT, LOGINSUCCESS, LOGINFAILURE), auditing credit card validation rules (CC-VAL-ATTEMPT, CC-VAL-FAILURE, CC-VAL-SUCCESS), auditing gift card protection rules (GC-VAL-ATTEMPT, GC-VAL-FAILURE, GC-VAL-SUCCESS), identifying potential login endpoints not covered by NGWAF rules, or comparing attack traffic against blocked traffic to confirm enabled rules are actually blocking.\"\n---\n\n# Fastly NGWAF Workspace Audit\n\nAudits NGWAF workspaces to verify critical templated rules are configured and enabled. Use the **fastly-cli** skill to configure rules; this skill identifies gaps.\n\n## Quick Start\n\nThe bundled assessment requires Bash, `curl`, `jq`, network access to `api.fastly.com`, and a locally configured `FASTLY_API_KEY` with NGWAF read access.\nThe manual workflow also requires the `fastly` CLI.\nConfigure credentials in the user's local environment or CLI configuration.\nNever ask the user to paste an API key into chat or print it in command output.\n\nSet `NGWAF_SKILL_DIR` to the absolute directory containing this `SKILL.md`, using the installed skill location supplied by the client.\nThis is a variable you assign, not a client-provided environment variable.\nRun the helper from the user's working directory:\n\n```bash\nNGWAF_SKILL_DIR=/absolute/path/to/fastly-ngwaf\nbash \"$NGWAF_SKILL_DIR/scripts/assess_ngwaf_rules.sh\"\n```\n\nFor manual inspection or partial audits, work through the steps below with the `fastly` CLI.\n\nThe CLI ignores `FASTLY_API_KEY`. Its precedence is `--token` > `FASTLY_API_TOKEN` > `fastly.toml` profile > default\nstored token. To reuse the script's credential:\n\n```bash\nexport FASTLY_API_TOKEN=\"$FASTLY_API_KEY\"\n```\n\n## Audit Workflow\n\n1. **List workspaces** — verify the account has NGWAF workspaces\n2. **Fetch rules per workspace** — retrieve each workspace's rule set\n3. **Validate critical signals** — confirm required rules exist and are enabled\n4. **Flag gaps and search for uncovered endpoints** — report missing/disabled rules\n5. **Check attack traffic against blocked traffic** — confirm enabled rules are actually blocking\n\n### Step 1: List Workspaces\n\n```bash\nfastly ngwaf workspace list --json | jq -r '.data[].id'\n```\n\nIf empty, NGWAF is not configured for this account.\n\n### Step 2: Fetch Rules for a Workspace\n\n```bash\nfastly ngwaf workspace rule list --workspace-id \"$WORKSPACE_ID\" --json\n```\n\nBoth list commands return `{\"data\": [...], \"meta\": {...}}` and cap at 100 items with no flag to raise it. Check\n`.meta.total`; above 100, fall back to `GET /ngwaf/v1/workspaces?limit=200` or `.../rules?limit=200`.\n\n`rule list` also takes `--enabled` and `--action` to filter server-side.\n\n### Step 3: Validate Critical Signals\n\nFor each workspace, verify these templated rules exist and `enabled` is `true`:\n\n| Category               | Required Signals                                                 |\n| ---------------------- | ---------------------------------------------------------------- |\n| Login Protection       | `LOGINDISCOVERY`, `LOGINATTEMPT`, `LOGINSUCCESS`, `LOGINFAILURE` |\n| Credit Card Validation | `CC-VAL-ATTEMPT`, `CC-VAL-FAILURE`, `CC-VAL-SUCCESS`             |\n| Gift Card Validation   | `GC-VAL-ATTEMPT`, `GC-VAL-FAILURE`, `GC-VAL-SUCCESS`             |\n\nCheck a specific signal:\n\n```bash\nfastly ngwaf workspace rule list --workspace-id \"$WORKSPACE_ID\" --json \\\n  | jq '[.data[] | select(.actions[].signal == \"LOGINDISCOVERY\") | {enabled, id}]'\n```\n\n### Step 4: Search for Uncovered Login Endpoints\n\nWhen `LOGINATTEMPT` is missing or disabled, search recent request logs for login-like traffic the WAF isn't protecting.\nNo CLI equivalent exists (there is no `fastly ngwaf workspace requests`), so use the API:\n\n```bash\ncurl -s -H \"Fastly-Key: $FASTLY_API_KEY\" \\\n  \"https://api.fastly.com/ngwaf/v1/workspaces/$WORKSPACE_ID/requests?limit=100&page=1&q=from%3A-30min%20method%3APOST%20path%3A~%22%2Alogin%2A%22\" \\\n  | jq -r '.data[].path' | sort | uniq -c\n```\n\n### Step 5: Check Attack Traffic Against Blocked Traffic\n\nA rule can be present and enabled and still block nothing when the workspace mode overrides it. `requests_attack` is\nwhat NGWAF flagged; `requests_total_blocked` is what it stopped. Attacks above zero with nothing blocked means the\nworkspace is in `log` or `off` mode. Report it even when every rule checks out.\n\n```bash\nfastly ngwaf workspace time-series get --workspace-id \"$WORKSPACE_ID\" \\\n  --from=2026-08-01T00:00:00Z --to=2026-08-08T00:00:00Z \\\n  --metrics=requests_total,requests_attack,requests_total_blocked \\\n  --granularity=86400 --json \\\n  | jq -r '.data[] | \"\\(.timestamp)  total=\\(.requests_total)  attack=\\(.requests_attack)  blocked=\\(.requests_total_blocked)\"'\n```\n\nAcross every workspace at once, grouped by workspace:\n\n```bash\nfastly ngwaf time-series list \\\n  --from=2026-08-01T00:00:00Z --to=2026-08-08T00:00:00Z \\\n  --metrics=requests_total,requests_attack \\\n  --granularity=86400 --dimensions=workspaces --json \\\n  | jq -r '.data[] | \"\\(.dimensions.workspace)  \\(.dimensions.time)  \\(.values | add)\"'\n```\n\nThe workspace-level subcommand is `get`, the account-level one is `list`. They differ in three ways that break audit\nscripts:\n\n- Output shape. `get` returns flat objects keyed by metric with a `timestamp`. `list` nests them under `dimensions`\n  and a `values` array, hence `.values | add`.\n- Bucket size. The CLI only sends `--granularity` when passed; `get` then buckets hourly and `list` daily. Always\n  pass it.\n- Zeroes. `get` reports a quiet metric as `0`. `list` drops it from `values`, and returns\n  `{\"data\":[],\"meta\":{\"total\":0}}` when nothing recorded. A missing key means zero, not an error.\n\nRead `requests_total_blocked` through `get`. A workspace that blocked nothing is the case this audit is looking for,\nand `list` reports it as an absence.\n\n`--from` and `--metrics` are required on both. Timestamps are RFC 3339, not the `YYYY-MM-DD` that `fastly stats` takes.\n\n`--metrics` also accepts `XSS`, `SQLI`, `HTTP404` and any custom signal name on the workspace, so a rule verified in\nstep 3 can be checked for real traffic by signal name. Query those through `get`.\n\n## Expected Output\n\n**Healthy workspace** — all signals present and enabled:\n\n```text\n### Workspace: abc123\n  [LOGIN Rules]\n  - LOGINDISCOVERY: ENABLED\n  - LOGINATTEMPT: ENABLED\n  - LOGINSUCCESS: ENABLED\n  - LOGINFAILURE: ENABLED\n  [CC Rules]\n  - CC-VAL-ATTEMPT: ENABLED\n  - CC-VAL-FAILURE: ENABLED\n  - CC-VAL-SUCCESS: ENABLED\n  [GC Rules]\n  - GC-VAL-ATTEMPT: ENABLED\n  - GC-VAL-FAILURE: ENABLED\n  - GC-VAL-SUCCESS: ENABLED\n```\n\n**Unhealthy workspace** — missing or disabled rules require remediation:\n\n```text\n### Workspace: def456\n  [LOGIN Rules]\n  - LOGINDISCOVERY: NOT CONFIGURED (Recommended: CRITICAL: Configure and enable this rule to discover unknown login endpoints)\n  - LOGINATTEMPT: IS DISABLED (Recommended: Enable this rule)\n  - LOGINSUCCESS: ENABLED\n  - LOGINFAILURE: ENABLED\n  -> LOGINATTEMPT is not enabled. Searching recent request logs for potential login paths...\n  -> Found potential login paths in last 30 minutes:\n       3 /api/v1/login\n       1 /auth/signin\n```\n\n## Error Handling\n\n| Error                             | Cause                        | Fix                                            |\n| --------------------------------- | ---------------------------- | ---------------------------------------------- |\n| `FASTLY_API_KEY not set`          | Environment variable missing | Configure the key locally, outside chat       |\n| `API call failed with status 403` | Token lacks NGWAF scope      | Verify token has `global:read` permission      |\n| `No workspaces found`             | NGWAF not provisioned        | Enable NGWAF on the account first              |\n| `jq is not installed`             | Missing dependency           | `brew install jq` or `apt-get install -y jq`   |\n| `curl is not installed`           | Missing dependency           | Install `curl` with the system package manager |\n\n## API References\n\n- [List Workspaces](https://www.fastly.com/documentation/reference/api/ngwaf/workspaces/#ngwafListWorkspaces)\n- [List Workspace Rules](https://www.fastly.com/documentation/reference/api/ngwaf/rules/#ngwafListWorkspaceRules)\n- [Time Series Metrics](https://www.fastly.com/documentation/reference/api/ngwaf/timeseries/)\n"
}

SHA-256 of public snapshot: 55b4eb94f9041896adedfe591061f944cc6dd28b20e0a1464f4850a70f41093e