mirror of
https://github.com/usestrix/strix.git
synced 2026-08-19 18:13:34 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7cb8da7e5a | ||
|
|
aa5867f5df |
@@ -42,7 +42,10 @@ Notable source-aware skills:
|
||||
- `source_aware_whitebox` (coordination): white-box orchestration playbook
|
||||
- `source_aware_sast` (custom): semgrep/AST/secrets/supply-chain static triage workflow
|
||||
- `dependency_cve_scanning` (custom): trivy-based SCA workflow for reporting known dependency CVEs via `create_dependency_report`
|
||||
- `npx_confusion` (custom): npx/npm exec/bunx fallback and adjacent package-runner identity confusion, with runner-specific registry and reporting gates
|
||||
- `agentic_system_security` (vulnerabilities): effective-authority and MCP/tool ecosystem security testing
|
||||
- `azure` (cloud): Azure and Microsoft Entra privilege, PIM, workload identity, and cross-plane escalation analysis
|
||||
- `infrastructure_lifecycle` (reconnaissance): abandoned or mutable external dependencies such as update endpoints, MX, storage, and control domains
|
||||
- `argument_injection` (vulnerabilities): shell-free CLI option smuggling, secondary argument-file parsing, and platform-specific argv transformation boundaries
|
||||
|
||||
Notable LLM security skills:
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
---
|
||||
name: npx-confusion
|
||||
description: Test package and executable identity confusion in npx, npm exec, and bunx fallback, plus explicit auto-fetch runners such as pnpm/yarn dlx and deno run npm:, with runner-specific resolution analysis, registry-state controls, reporting gates, and false-positive elimination
|
||||
---
|
||||
|
||||
# npx Confusion
|
||||
|
||||
Use this skill when a package runner may execute code from a package other than the publisher or package the workflow intended. For `npx`, `npm exec`, and `bunx`, the recurring case is a missing local executable being reinterpreted as a remotely fetched package spec. Explicit auto-fetch runners such as `pnpm dlx`, `yarn dlx`, and `deno run npm:` have different semantics; analyze them as an adjacent package-identity problem rather than pretending they share npm's fallback order.
|
||||
|
||||
Load `dependency_cve_scanning` for known vulnerable versions, `infrastructure_lifecycle` for abandoned domains or registry resources, `agentic_system_security` for the authority of an MCP/agent process, and `semantic_confusion` for the general lookup-order model.
|
||||
|
||||
## Core Condition
|
||||
|
||||
Choose the branch that matches the runner.
|
||||
|
||||
For local-first fallback (`npx`, `npm exec`, or `bunx`), require all of the following:
|
||||
|
||||
1. A target-controlled workflow invokes a bare executable or ambiguous package token.
|
||||
2. The intended package and its executable name differ, or other evidence establishes the expected publisher/package.
|
||||
3. The executable is not resolved in the workflow's real local, workspace, global, or cache context as applicable to that runner.
|
||||
4. The runner consequently selects an unintended remote package spec from its configured registry.
|
||||
5. The affected workflow reaches that package's executable with security-relevant authority.
|
||||
|
||||
For explicit auto-fetch runners (`pnpm dlx`/`pnx`/`pnpx`, `yarn dlx`, or `deno run npm:`), do not require or claim a missing-local-binary fallback. Require evidence that the command names or infers a package different from the one the workflow intended, such as a scoped-package/bin mismatch, typo, generated configuration error, or wrong publisher. Then prove the exact fetched package, chosen binary/module, execution path, and inherited authority.
|
||||
|
||||
A public package merely being outside the target's ownership is not a vulnerability. Third-party packages are normal; the mismatch between intended executable provenance and actual registry resolution is the finding.
|
||||
|
||||
## Resolution Model
|
||||
|
||||
Record the npm version because `npx` has used `npm exec` since npm 7 and resolver behavior changes between releases. For npm, model these decisions:
|
||||
|
||||
```text
|
||||
bare command
|
||||
-> executable in ancestor node_modules/.bin?
|
||||
-> executable in global bin?
|
||||
-> matching local/global package and usable bin?
|
||||
-> matching environment in the npx cache?
|
||||
-> treat the command token as a package spec
|
||||
-> fetch its manifest from the configured registry
|
||||
-> infer one executable from package.json#bin
|
||||
-> install into the npx cache and execute
|
||||
```
|
||||
|
||||
Also record:
|
||||
|
||||
- working directory and workspace root
|
||||
- local dependency tree and generated `node_modules/.bin` links
|
||||
- global prefix/bin directory and npx cache
|
||||
- `registry`, scope-specific registry rules, proxy and authentication configuration
|
||||
- command form, flags, package spec/version, TTY/CI state, and `yes` policy
|
||||
- npm's executable-inference result when the package exposes zero, one, or several `bin` entries
|
||||
|
||||
Do not collapse package-name lookup and bin selection into one step. npm can fetch a manifest yet fail because it cannot infer exactly one executable.
|
||||
|
||||
### Runner distinctions
|
||||
|
||||
Record the exact runner and version. Do not reuse npm's local/global/cache ordering for another implementation.
|
||||
|
||||
| Runner | Resolution behavior to model | Package binding / fetch control |
|
||||
|---|---|---|
|
||||
| `npx` / `npm exec` | Local/workspace/global/cache resolution followed by package-spec fallback; executable inference depends on `package.json#bin` | `--package <pkg>` binds the provider; `--no` rejects an install prompt |
|
||||
| `bunx` | Checks a locally installed package, then can install from npm into Bun's cache | `--package <pkg>` binds the provider; `--no-install` forbids installation |
|
||||
| `yarn dlx` | Downloads the command-named package into a temporary environment by default; this is not a local-bin fallback | `--package <pkg>` selects a different provider package |
|
||||
| `pnpm dlx` / `pnx` / `pnpx` | Fetches and hotloads a registry package, then runs its default binary; project trust policies are version-dependent | `--package=<pkg>` selects the provider; prefer declared dependencies plus `pnpm exec` when remote fetch is unintended |
|
||||
| `deno run npm:<pkg>` | Uses an explicit npm package spec and cache; a subpath can select a binary | Pin the package/subpath and model lock, cache, lifecycle-script, and Deno permission settings |
|
||||
|
||||
Treat mutable tags and ranges such as `latest`, `next`, `@2`, caret, and tilde ranges as selectors, not pins. A privileged repeatable workflow needs an exact reviewed version plus lockfile/integrity enforcement where the runner supports it.
|
||||
|
||||
## High-Signal Patterns
|
||||
|
||||
### Bare executable fallback
|
||||
|
||||
```text
|
||||
npx internal-tool
|
||||
npx -y internal-tool
|
||||
npm exec -- internal-tool
|
||||
```
|
||||
|
||||
The signal is strongest in CI, release scripts, bootstrap commands, developer setup, and tool/agent configuration where the same command is run repeatedly.
|
||||
|
||||
### Scoped package versus unscoped bin
|
||||
|
||||
A scoped package can expose an unscoped executable:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "@org/tooling",
|
||||
"bin": { "org-tool": "./bin/run.js" }
|
||||
}
|
||||
```
|
||||
|
||||
Inside a correctly installed workspace, `npx org-tool` may resolve `node_modules/.bin/org-tool`. Outside that tree, the same command can fall back to the public package named `org-tool`. Treat documentation, MCP configuration, and bootstrap scripts as separate execution contexts rather than assuming the repository-local result applies everywhere.
|
||||
|
||||
### Agent and MCP launchers
|
||||
|
||||
Inspect `.mcp.json`, editor/desktop agent configuration, devcontainers, and generated tool launchers for `command: npx` plus `-y` and a bare package or binary name. Combine this resolver analysis with `agentic_system_security` to determine the credentials, tools, files, and network access inherited by that process.
|
||||
|
||||
## Candidate Collection
|
||||
|
||||
Search executable surfaces and retain file, line, command, and execution context:
|
||||
|
||||
```bash
|
||||
rg -n --no-heading -g '!node_modules' -g '!**/dist/**' \
|
||||
-e '\b(npx|npm\s+exec|bunx|pnx|pnpx|pnpm\s+dlx|yarn\s+dlx)\s+[^[:space:]]+' \
|
||||
-e '\bdeno\s+run\b[^\n]*\bnpm:' \
|
||||
-e '"command"\s*:\s*"(npx|bunx|pnx|pnpx|pnpm|yarn|deno)"' \
|
||||
-e '"args"\s*:\s*\[[^]]*"(dlx|npm:[^"]+|-y)"' \
|
||||
.
|
||||
```
|
||||
|
||||
Search the source/configuration tree rather than a fixed file list: these commands also live in
|
||||
`scripts/`, husky/lint-staged hooks, `turbo.json`/`nx.json` task definitions,
|
||||
`.circleci/`, composite-action `action.yml`, devcontainer `postCreateCommand`,
|
||||
nested workspace `package.json` files, and editor/agent config under
|
||||
`.cursor/`, `.vscode/`, and `.mcp.json`. If generated output is itself shipped or executed, search its specific directory separately instead of globally including every `dist/` artifact.
|
||||
|
||||
Also inspect:
|
||||
|
||||
- package scripts and lifecycle hooks
|
||||
- workspace package `name` and `bin` maps
|
||||
- READMEs and generated setup instructions
|
||||
- CI composite actions and reusable workflows
|
||||
- source maps or bundled package metadata that reveal internal commands
|
||||
|
||||
Discard paths, shell variables, flags, Node built-ins, and text that is not executed or presented as an executable command.
|
||||
|
||||
## Establish the Actual Resolution
|
||||
|
||||
Prefer inspecting the existing dependency tree, lockfile, workspace packages, and `.bin` links. Do not run `npm ci` merely to decide whether a command is local: it changes the tree and can execute lifecycle scripts.
|
||||
|
||||
For a version-controlled reproduction environment, record npm's registry lookup without allowing a missing package to be installed:
|
||||
|
||||
```bash
|
||||
npx --no --loglevel=http <candidate>
|
||||
```
|
||||
|
||||
Interpret this carefully:
|
||||
|
||||
- a local executable may run immediately; `--no` only refuses missing-package installation
|
||||
- an HTTP registry request shows fallback, not ownership or successful execution
|
||||
- a cancellation naming the missing package shows npm's chosen package spec
|
||||
- cache, global installs, parent directories, workspaces, and registry configuration can change the result
|
||||
|
||||
Repeat the resolution analysis in every context that matters: repository root, documented launch directory, CI checkout, generated agent configuration, and bootstrap-before-install flow. Do not substitute a clean empty directory for the target context except to understand npm's generic name mapping.
|
||||
|
||||
Do not apply `npx --no` as a generic dry-run flag. Use `bunx --no-install` only for Bun's local-resolution question. `dlx` and `deno run npm:` already name a remotely resolvable package, so validate their package spec, registry, cache/lock, selected binary or subpath, and permissions using that runner's own behavior.
|
||||
|
||||
## Ownership and Registry State
|
||||
|
||||
Query the exact registry selected by the target configuration, then distinguish:
|
||||
|
||||
- intended package owned by the expected publisher
|
||||
- unrelated public package with the same name
|
||||
- unregistered name (`404` from a functioning registry)
|
||||
- private or access-controlled name (`401`/`403`)
|
||||
- transient/rate-limited/blocked lookup (`429`, `5xx`, timeout)
|
||||
- placeholder, reserved, disputed, or previously unpublished name
|
||||
|
||||
Before trusting any of those states, check whether the target's lookup path can distinguish a known existing package from a newly generated negative control. Resolve the registry from the same working directory and configuration used by the target:
|
||||
|
||||
```bash
|
||||
# Public npm example; use a known package from the actual registry when different.
|
||||
task_registry="$(npm config get registry)"
|
||||
npm view --registry="$task_registry" lodash name --json
|
||||
npm view --registry="$task_registry" "$(openssl rand -hex 12)" name --json
|
||||
```
|
||||
|
||||
Run the pair through the same `.npmrc`, scope routing, authentication, proxy, and egress path as the candidate. Direct `curl` requests to the public registry are a separate observation unless the target runner uses that exact route. A successful pair establishes coarse positive/negative discrimination, not authenticity of every candidate response; verify that returned documents name the requested package and contain plausible registry metadata.
|
||||
|
||||
If the pair fails or returns indistinguishable responses, mark the target-path registry state `UNKNOWN`. An independently verified public-registry response may characterize public state, but it does not prove what the target runner resolves. Re-confirm candidate absence before relying on it.
|
||||
|
||||
A `404` proves absence from that registry at that time; it does not by itself prove that registration would be accepted. Registry similarity, trademark, reservation, security-hold, and unpublish rules remain separate facts. Two concrete cases to check rather than infer:
|
||||
|
||||
- A registry-owned security placeholder occupies the name even when its only version is `0.0.1-security`. Do not identify one from the version alone: inspect the packument, description, dist-tags, top-level and version-level maintainers, and version publisher such as `_npmUser`.
|
||||
- npm rejects new unscoped names that collide with an existing package after `.`, `-`, and `_` are removed. Normalize both the candidate and existing names: looking up only the candidate's stripped form catches `some-tool` versus `sometool`, but misses the reverse direction when the existing package contains punctuation. Treat this as registry-policy eligibility evidence, not a guarantee that registration would otherwise succeed.
|
||||
|
||||
When a candidate name is already registered, distinguish the target's own
|
||||
organization from an unrelated party before calling it a clash. Correlate `npm owner ls <name>`, version-level publisher metadata, known target-controlled npm organizations, and independently verified repository provenance. Repository/homepage fields are self-asserted supporting evidence and do not settle ownership alone. If publisher identity remains ambiguous, mark it `UNKNOWN`.
|
||||
|
||||
## Validation and Impact
|
||||
|
||||
Demonstrate the complete resolver statement:
|
||||
|
||||
```text
|
||||
target-controlled invocation and context
|
||||
-> intended executable absent
|
||||
-> exact public package spec selected
|
||||
-> package ownership/availability state
|
||||
-> execution trigger and inherited authority
|
||||
```
|
||||
|
||||
Do not report an unregistered name without an execution path, or an execution path whose command is satisfied locally in every relevant context. Derive impact from the environment that executes the package: developer workstation, CI job, release pipeline, agent runtime, container build, or documentation-only workflow.
|
||||
|
||||
## Reporting
|
||||
|
||||
There is no CVE and no vulnerable installed version here, so this does not go through `create_dependency_report`; that tool requires an advisory-matched CVE. Use `create_vulnerability_report` only after the applicable core condition is fully verified.
|
||||
|
||||
A registry lookup or `404` alone is candidate evidence, not a working PoC. The report must preserve the target invocation and execution context, show the exact selected package and binary/module, demonstrate the runner's execution transition in a representative controlled setup without publishing the contested name, and establish the authority inherited by that process. When source is available, include the responsible invocation/configuration and concrete fix in `code_locations`.
|
||||
|
||||
Do not file documentation/comment-only references, locally satisfied commands, unregisterable names, ambiguous ownership, or chains that stop before package execution. Retain them as investigation notes only when useful.
|
||||
|
||||
Derive CVSS from the demonstrated path rather than a fixed severity label. Account for required developer/user action, registry and configuration prerequisites, runner permissions, credential availability, and the confidentiality, integrity, and availability actually exposed. A CI, release, container-build, or agent context can be severe, but the context name alone does not establish High or Critical impact.
|
||||
|
||||
Deduplicate by root cause, affected asset/workflow, and remediation. Combine call sites when the same configuration mistake and fix apply; keep separate findings when the same candidate name affects different products, tenants, runner semantics, authority, or fixes.
|
||||
|
||||
## False Positives
|
||||
|
||||
- The executable is provided by a declared dependency in every real execution context.
|
||||
- `npx --package @scope/pkg <bin>` explicitly binds the executable to the intended package.
|
||||
- A versioned package spec or scope-specific registry points to the intended publisher.
|
||||
- The public package is the deliberately selected third-party tool.
|
||||
- npm fetches the manifest but cannot infer or execute a bin.
|
||||
- The reference appears only in generated/minified text with no executable call site.
|
||||
- A registry/proxy error is misread as an unregistered name, or the target-path control pair is inconclusive.
|
||||
- A package is absent but registry policy prevents the contested registration.
|
||||
- The command resolves to the deliberately selected ecosystem tool and expected publisher.
|
||||
- The already-registered name belongs to the target's own organization.
|
||||
- An explicit `dlx` or `npm:` package spec is treated as missing-local fallback without evidence of a package/publisher mismatch.
|
||||
|
||||
## Remediation
|
||||
|
||||
- Install the intended package and invoke its local executable through an npm script.
|
||||
- For npm, bind and pin the provider: `npx --package @org/tool@<version> org-tool`; use `--no` when a missing dependency must fail.
|
||||
- For Bun, use `bunx --package @org/tool@<version> org-tool` and `--no-install` when remote installation is not intended.
|
||||
- Replace `yarn dlx`/`pnpm dlx` in repeatable or privileged workflows with a declared, locked dependency plus the runner's local `exec` command. When ephemeral execution is required, bind and pin the provider package explicitly.
|
||||
- For Deno, pin the `npm:` package and binary subpath, retain a reviewed lockfile, use cache-only operation where appropriate, and grant only the permissions the command requires.
|
||||
- Route private scopes to the intended registry and prevent public fallback.
|
||||
- Pin package versions and lockfiles in privileged workflows.
|
||||
- Replace bare `npx -y <name>` agent launchers with reviewed, publisher-qualified, version-pinned package specs.
|
||||
|
||||
## Summary
|
||||
|
||||
Treat package-runner confusion as an identity and execution-context bug. Prove the runner-specific transition, distinguish binary names from package names, verify registry and publisher state without equating absence with eligibility, and report only a complete execution path under the affected workflow's actual authority.
|
||||
@@ -105,6 +105,27 @@ tree-sitter parse -q <file>
|
||||
|
||||
Use outputs to improve route/symbol/sink maps for subsequent targeted scans.
|
||||
|
||||
## Resolution and Namespace Risks
|
||||
|
||||
In repositories with developer tooling, plugins, templates, or package runners, inspect lookup order rather than only dependency versions:
|
||||
|
||||
- command runners that fall back from local binaries or `PATH` to a public registry
|
||||
- scoped/private package names exposing unscoped binary or alias names
|
||||
- plugin, template, module, and autoload search paths writable by a lower-privileged actor
|
||||
- CI/composite actions and devcontainer/bootstrap scripts that transitively execute package commands
|
||||
- missing local artifacts that silently activate a remote or broader fallback
|
||||
|
||||
Record candidate names and verify ownership/existence without claiming or publishing them. A namespace gap is reportable only when the target actually resolves or executes the attacker-contestable name under realistic conditions.
|
||||
|
||||
For npm/JavaScript, distinguish the package name from the executable name and
|
||||
model the actual working directory, dependency tree, global bin directory,
|
||||
cache, and registry configuration. `load_skill(["npx_confusion"])` when a bare
|
||||
`npx`/`npm exec` command may fall back from a missing executable to a public
|
||||
package. Trivy cannot detect this class because no installed package version
|
||||
needs to be vulnerable.
|
||||
|
||||
Load `infrastructure_lifecycle` when source, images, firmware, or history contain abandoned domains, provider resources, package namespaces, update URLs, mail identities, telemetry, or control endpoints. Use targeted string/dataflow analysis when this is the research question; the full baseline scanner bundle is not required merely to trace one endpoint consumer.
|
||||
|
||||
## Secret and Supply Chain Coverage
|
||||
|
||||
Detect hardcoded credentials:
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
---
|
||||
name: infrastructure-lifecycle
|
||||
description: Discovery and security analysis of abandoned or ownership-drifted infrastructure trusted by software, firmware, DNS, mail, update systems, packages, scripts, telemetry, and deployed agents
|
||||
---
|
||||
|
||||
# Infrastructure Lifecycle Trust
|
||||
|
||||
Use this skill when a product, application, device, image, or organization continues to trust an external name or provider resource whose ownership can expire, be deleted, be reassigned, or move outside the intended organization.
|
||||
|
||||
This is broader than subdomain takeover. The vulnerable asset may make outbound requests to a retired update bucket, load JavaScript from an abandoned domain, send mail to an expired MX domain, query a reassigned WHOIS/RDAP server, install from a missing package namespace, or beacon to an embedded telemetry/control endpoint. The security property is continuity of ownership across the full lifetime of every trust consumer.
|
||||
|
||||
## Trust-Consumer Graph
|
||||
|
||||
Model each dependency:
|
||||
|
||||
```text
|
||||
consumer/version/deployment
|
||||
-> embedded logical name or URL
|
||||
-> DNS/provider/package resolution chain
|
||||
-> current owner/controller
|
||||
-> content/protocol accepted
|
||||
-> privilege and trigger in the consumer
|
||||
```
|
||||
|
||||
Record separately:
|
||||
|
||||
- where the reference is stored: source, binary, firmware, image layer, config, database, IaC, documentation, update metadata
|
||||
- deployed versions and whether the consumer still runs
|
||||
- endpoint type, resolution chain, TLS/signature/authentication requirements, and fallback order
|
||||
- current registration/provider ownership and historical ownership
|
||||
- request trigger, frequency, payload/data sent, and response/content interpretation
|
||||
- consumer privilege: browser origin, installer/root, CI runner, mail receiver, parser, agent, or telemetry process
|
||||
- decommission owner, renewal/update process, and monitoring coverage
|
||||
|
||||
A domain or bucket being available is only half the finding. Show that a live in-scope consumer still trusts it and what that consumer would accept.
|
||||
|
||||
## Control and Claimability Levels
|
||||
|
||||
Do not collapse these into one claim:
|
||||
|
||||
| Level | Evidence |
|
||||
|---|---|
|
||||
| Indicator | NXDOMAIN, expired registration, provider tombstone, missing package/resource |
|
||||
| Authoritative availability | Registrar/provider/package authority confirms the exact name/resource can be acquired or bound |
|
||||
| Acquisition/control | Authorized tester controls the registrable domain, resource, namespace, or provider binding |
|
||||
| Protocol identity | Required DNS, custom-host binding, TLS certificate, authentication, or protocol handshake succeeds |
|
||||
| Consumer acceptance | A live in-scope consumer contacts the controlled endpoint and accepts the relevant response semantics |
|
||||
|
||||
Record the highest proven level for every consumer. Before acquisition or provider binding, determine whether control can immediately receive existing third-party traffic and apply the Passive Sensor and Sinkhole plan below.
|
||||
|
||||
## High-Value Dependency Classes
|
||||
|
||||
### Update and Code Distribution
|
||||
|
||||
- firmware/software update URLs, manifests, package indexes, installers, drivers, VM/container images
|
||||
- CDN/object-storage buckets serving binaries, scripts, templates, rules, signatures, or configuration
|
||||
- browser JavaScript/CSS imports and desktop/mobile auto-update channels
|
||||
- bootstrap, CI, devcontainer, build, and installation scripts
|
||||
- model/agent skill, plugin, prompt, MCP server, and tool-definition update channels
|
||||
|
||||
Record signature, hash, certificate, pinning, version/rollback, and content-type enforcement. TLS alone authenticates the current domain controller, not continuity with the original publisher.
|
||||
|
||||
### Naming and Package Resolution
|
||||
|
||||
- missing public/private package names, scoped package versus executable alias, plugin/module/template namespaces
|
||||
- `PATH`, autoload, search path, registry, cache, mirror, and remote fallback order
|
||||
- provider-generated hostnames or globally unique resource names released on deletion
|
||||
- legacy aliases retained in manifests, lockfiles, scripts, or installed products
|
||||
|
||||
Do not register or publish candidate names merely to test them without explicit authorization and a containment plan. Prove the consumer's resolution behavior first.
|
||||
|
||||
Registry "missing" responses are not interchangeable with "claimable".
|
||||
Similarity, reservation, security-hold, dispute, and unpublish rules can block
|
||||
a name that returns `404`; verify ownership and registry policy separately.
|
||||
Load `npx_confusion` when the consumer first treats a missing executable as an
|
||||
npm package spec. Model other ecosystems independently rather than assuming
|
||||
npm's resolution order applies to them.
|
||||
|
||||
### Mail and Identity
|
||||
|
||||
- expired organizational, supplier, recovery, notification, or former employee domains
|
||||
- MX targets and catch-all aliases that remain in applications, address books, SSO, password recovery, certificates, or vendor accounts
|
||||
- OAuth redirect/logout URIs, SAML endpoints, webhook callbacks, CORS/CSP allowlists, and trusted-origin lists tied to retired hosts
|
||||
- domain-based tenant verification and support/administrative identity flows
|
||||
|
||||
Differentiate ability to receive a tester-created message from interception of real correspondence. Do not access unrelated mail or use received secrets/credentials.
|
||||
|
||||
### Telemetry, Control, and Protocol Infrastructure
|
||||
|
||||
- crash reporting, analytics, licensing, activation, NTP/DNS, support, and health-check endpoints
|
||||
- hardcoded agent/controller, webshell/C2, webhook, exfiltration, or callback domains embedded in deployed systems
|
||||
- hardcoded retired WHOIS/RDAP endpoints, certificate validation services, keyservers, mirrors, proxies, and service-discovery dependencies
|
||||
- local/remote management domains in appliances, mobile apps, extensions, and container images
|
||||
|
||||
Treat unexpected inbound traffic as potentially sensitive. Passive receipt does not authorize interaction, command issuance, credential use, or expansion beyond the approved sensor purpose.
|
||||
|
||||
## Discovery
|
||||
|
||||
### Source, Image, and Firmware Corpus
|
||||
|
||||
Extract hostnames, URLs, email domains, bucket names, package names, registry endpoints, and certificate subjects from:
|
||||
|
||||
- source and history, lockfiles, CI/IaC, release assets, SBOMs
|
||||
- container/VM layers including deleted-file history
|
||||
- firmware rootfs, strings/resources, scripts, configs, examples, and updater logic
|
||||
- JavaScript/mobile/desktop bundles, extensions, templates, and documentation
|
||||
- logs and network captures from controlled normal operation
|
||||
|
||||
Use staged extraction rather than relying on one broad regex:
|
||||
|
||||
```bash
|
||||
# URLs and email addresses
|
||||
rg -n -i 'https?://|wss?://|s3[.-]|blob\.core\.|[A-Z0-9._%+-]+@[A-Z0-9.-]+' extracted/
|
||||
|
||||
# Then query format-aware config keys, DNS/MX data, certificate metadata,
|
||||
# package manifests, and binary strings for bare hostnames/namespaces.
|
||||
```
|
||||
|
||||
Review bare-hostname candidates for prose, source-map, test, and generated-data false positives. Deduplicate content-addressed layers and repeated vendor boilerplate so prevalence is not inflated. Preserve the source file, artifact hash, version, and surrounding semantic context for every candidate.
|
||||
|
||||
### Ownership and Resolution History
|
||||
|
||||
- Resolve A/AAAA/CNAME/NS/MX/TXT/CAA and retain complete chains.
|
||||
- Check current registrar/provider resource state through authoritative sources, including custom-domain binding and reservation rules.
|
||||
- Use historical DNS, CT, WHOIS/RDAP, package metadata, source history, and release timelines to establish ownership drift.
|
||||
- Identify wildcard/catch-all responses, parked domains, provider tombstones, and reused cloud IPs that mimic availability.
|
||||
- Compare vulnerable/current builds to learn whether the reference was removed, replaced, or cryptographically hardened. Record CAA, DNSSEC/DANE where relevant, certificate issuance/custom-host requirements, pinning, embedded trust stores, and independent content signatures.
|
||||
|
||||
Do not rely on an HTTP `404`, NXDOMAIN, or “NoSuchBucket” alone. Providers reserve names, enforce ownership verification, or return identical errors for owned/private resources.
|
||||
|
||||
### Live Consumer Confirmation
|
||||
|
||||
Within scope, observe a controlled consumer through:
|
||||
|
||||
- offline code/dataflow from trigger to request and response consumer
|
||||
- DNS/HTTP proxy logs in a lab
|
||||
- packet capture or process/network tracing during a normal test operation
|
||||
- a tester-owned canary endpoint configured through a supported setting
|
||||
- already-authorized sensor/sinkhole telemetry
|
||||
|
||||
Record request method/protocol, SNI/Host, headers, authentication, body data classification, retry cadence, TLS verification, and how the response is parsed or executed.
|
||||
|
||||
## Security Analysis
|
||||
|
||||
Ask in order:
|
||||
|
||||
1. Can ownership/control actually transfer to an unrelated party?
|
||||
2. Does an in-scope deployed consumer still resolve or contact it?
|
||||
3. What authenticity/integrity checks survive endpoint takeover?
|
||||
4. What response fields/content/protocol messages can the controller influence?
|
||||
5. Under what identity and privilege does the consumer process them?
|
||||
6. Is the trigger automatic, scheduled, administrative, user-driven, or update-only?
|
||||
7. What population and versions remain affected?
|
||||
8. What claimability level is proven, and is acquisition necessary for the remaining questions?
|
||||
9. Could acquisition receive out-of-scope traffic or data?
|
||||
10. Does this name serve several distinct consumers that require separate semantics and impact analysis?
|
||||
|
||||
High-impact patterns include:
|
||||
|
||||
- unsigned or weakly verified update/package content processed with system/administrator privilege
|
||||
- JavaScript loaded under a trusted web origin or CSP allowlist
|
||||
- mail/recovery/identity messages delivered to a re-registered domain
|
||||
- secrets or device metadata automatically sent to a reassigned endpoint
|
||||
- trusted control/telemetry responses parsed as commands, config, templates, or executable content
|
||||
- CA/domain verification, service discovery, or protocol logic depending on mutable external ownership
|
||||
|
||||
## Passive Sensor and Sinkhole Handling
|
||||
|
||||
Operating a domain or provider resource that receives real third-party traffic is a separate data-handling activity, not ordinary proof-of-concept hosting. Before enabling it, define:
|
||||
|
||||
- written authorization and legal/privacy owner
|
||||
- accepted protocols and non-interaction policy
|
||||
- collection minimization, encryption, access control, retention, deletion, and redaction
|
||||
- handling for credentials, personal data, malware, or out-of-scope victims
|
||||
- notification/escalation and provider/registrar coordination
|
||||
- prohibition on commands, authentication attempts, payload delivery, or use of received secrets
|
||||
|
||||
Prefer aggregate metadata or a unique tester-controlled canary. Do not deliberately expose a genuinely vulnerable product to collect wild exploitation without separate deployment authorization and containment review.
|
||||
|
||||
## Relationship to Other Skills
|
||||
|
||||
- Load `subdomain_takeover` for dangling DNS records or custom-domain provider bindings. Ordinary expiration/re-registration of a registrable domain, MX identity, or embedded software endpoint remains in this skill.
|
||||
- Load `source_aware_sast` for targeted source/dataflow confirmation; string presence does not prove current ownership or live consumption.
|
||||
- Load `agentic_system_security` only when the endpoint supplies or controls AI skills, plugins, MCP/model adapters, tool definitions, or effective agent authority.
|
||||
- Load `semantic_confusion` only when a security decision and privileged consumer use different endpoint/package/alias representations or resolution results. Pure temporal ownership drift does not require it.
|
||||
|
||||
## Validation Deliverable
|
||||
|
||||
Include:
|
||||
|
||||
1. exact consumer artifact/version/deployment and reference location
|
||||
2. full DNS/provider/package resolution and current ownership evidence
|
||||
3. historical ownership/decommission timeline
|
||||
4. live or source-confirmed request trigger and accepted response semantics
|
||||
5. TLS/signature/hash/authentication behavior
|
||||
6. consumer privilege, affected population, and configuration prerequisites
|
||||
7. controlled ownership/canary evidence where authorized
|
||||
8. highest claimability level and confidence in live-consumer/prevalence evidence
|
||||
9. sensor/data-handling authorization when acquisition could receive existing traffic
|
||||
10. separate impact analysis for each mail, identity, update, telemetry, code, or control consumer
|
||||
11. remediation across both the endpoint and every retained consumer
|
||||
|
||||
## Common False Positives
|
||||
|
||||
- NXDOMAIN/provider tombstone with a name that cannot be registered or bound.
|
||||
- A hardcoded URL present only in dead code, examples, tests, or an undeployed version.
|
||||
- Live requests go to a vendor-controlled wildcard/catch-all despite an apparently missing specific resource.
|
||||
- Update content is independently signed and the reassigned endpoint cannot produce an accepted artifact; this usually blocks forged-code impact, but metadata exposure, update suppression, unsigned manifest fields, and rollback/version behavior still require analysis.
|
||||
- Expired domain appears in documentation but is absent from authentication, mail, software, and deployed configuration.
|
||||
- A package name is unregistered but the consumer is pinned to a private registry with no public fallback, the scope is routed by `.npmrc`, or the command is already satisfied by a locally installed binary.
|
||||
- The name is unregistered but registry policy, reservation, dispute, or unpublish state prevents the contested registration.
|
||||
- Inbound sensor traffic cannot be attributed to an in-scope consumer/version.
|
||||
|
||||
## Remediation
|
||||
|
||||
- Remove or replace references in every supported and still-deployed version.
|
||||
- Retain defensive ownership of externally embedded domains/resource names for the consumer's realistic lifetime.
|
||||
- Sign update/config/package content with independently managed, rotatable keys and enforce rollback/version policy.
|
||||
- Eliminate implicit public fallback; pin registries, publishers, hashes, and plugin identities.
|
||||
- Inventory domain/MX/provider/package dependencies in decommission workflows and continuous monitoring.
|
||||
- Revoke old credentials/tokens, rotate trust, and provide a migration/kill-switch path for stranded clients.
|
||||
- Monitor DNS, CT, registrar, provider binding, package namespace, and live outbound traffic for ownership drift.
|
||||
|
||||
## Summary
|
||||
|
||||
External names are long-lived security dependencies. Track every consumer to its current controller, prove that deployed software still trusts the endpoint, analyze the authenticity checks and processing privilege, and manage ownership for as long as any supported or abandoned client can call home.
|
||||
@@ -0,0 +1,99 @@
|
||||
---
|
||||
name: hurl
|
||||
description: Reproducible, reviewable HTTP request chains and response assertions with Hurl for authorized multi-step security validation, vulnerable-versus-fixed regression cases, captured values, and low-rate semantic oracles
|
||||
---
|
||||
|
||||
# Hurl Security Regression Playbook
|
||||
|
||||
Use [Hurl](https://hurl.dev/) when a security proof requires an ordered HTTP session whose requests, captured values, and assertions should be code-reviewed and replayed. It is well suited to authentication flows, redirects, cookies, CSRF tokens, upload lifecycles, patch regression, and paired semantic-differential cases.
|
||||
|
||||
Hurl sends exactly what the file describes. It does not make state-changing requests safe. Review scope, methods, targets, and captured secrets before every run.
|
||||
|
||||
## Install
|
||||
|
||||
Prefer an official release binary or package. On macOS:
|
||||
|
||||
```bash
|
||||
brew install hurl
|
||||
hurl --version
|
||||
```
|
||||
|
||||
Official alternatives include release packages and `cargo install --locked hurl`; see [installation](https://hurl.dev/docs/installation.html). Record the tool version with results.
|
||||
|
||||
## Minimal Chain
|
||||
|
||||
```hurl
|
||||
# lab-regression.hurl
|
||||
GET {{base_url}}/session
|
||||
HTTP 200
|
||||
[Captures]
|
||||
csrf: xpath "string(//input[@name='csrf']/@value)"
|
||||
[Asserts]
|
||||
header "Content-Type" startsWith "text/html"
|
||||
|
||||
POST {{base_url}}/action
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
[FormParams]
|
||||
csrf: {{csrf}}
|
||||
operation: noop
|
||||
HTTP 204
|
||||
```
|
||||
|
||||
Hurl keeps cookies across requests in the same file, so an explicit `Cookie` header is unnecessary here.
|
||||
|
||||
Run one reviewed case against one authorized target first:
|
||||
|
||||
```bash
|
||||
hurl --test --jobs 1 --connect-timeout 5s --max-time 15s \
|
||||
--variable base_url=https://lab.example lab-regression.hurl
|
||||
```
|
||||
|
||||
When credentials are required, pass them with `--secrets-file local-secrets.env`, keep that file outside version control, and avoid verbose/debug output that could expose headers or bodies. Use `--variables-file` only for non-secret environment values.
|
||||
|
||||
## Designing a Security Regression
|
||||
|
||||
- Assert the security invariant, not only a status code: denied identity, final normalized location, absence/presence of a structural field, unchanged object state, or exact benign result.
|
||||
- Capture only values needed by later requests. Do not write tokens, personal data, or response bodies into committed reports.
|
||||
- Encode a malformed but non-triggering control alongside the suspected case.
|
||||
- Run the same file against vulnerable and fixed builds through `base_url` or other explicit variables.
|
||||
- Keep state-changing methods in a clearly labeled lab/staging file; prefer no-op actions, inert markers, and cleanup requests.
|
||||
- Check every redirect step when the vulnerability crosses routing, origin, or authentication boundaries. Blindly following redirects can hide the relevant transition.
|
||||
- Use unique canaries so cached or pre-existing state cannot create a false positive.
|
||||
|
||||
## Chain Structure
|
||||
|
||||
Organize longer files around capability transitions:
|
||||
|
||||
```text
|
||||
fingerprint -> establish session -> reach boundary -> prove primitive -> verify state -> cleanup
|
||||
```
|
||||
|
||||
At each response, assert the condition required by the next request. A final success assertion cannot explain which earlier assumption failed.
|
||||
|
||||
Useful Hurl features include:
|
||||
|
||||
- captures from headers, cookies, JSONPath, XPath, and regex queries
|
||||
- assertions over status, headers, body, JSON/XML, redirects, and timing
|
||||
- request-local options and variables
|
||||
- `--test` plus JSON, JUnit, TAP, or HTML reports
|
||||
|
||||
Consult the [Hurl manual](https://hurl.dev/docs/manual.html) for version-specific syntax instead of guessing an option.
|
||||
|
||||
## Safety Rules
|
||||
|
||||
- Use an explicit `base_url`; never derive the destination from untrusted response data without validating scheme, host, and port.
|
||||
- Review POST/PUT/PATCH/DELETE requests and server-side side effects before replay.
|
||||
- Set bounded timeouts and retries for the target; do not use polling as an unbounded brute-force loop.
|
||||
- Do not use Hurl for raw HTTP parser/smuggling cases when its HTTP stack normalizes the bytes being tested; use an appropriate raw harness in an isolated lab.
|
||||
- Use `--path-as-is` when literal `/../` or `/./` path segments are the behavior under test; otherwise Hurl's underlying URL handling can normalize them.
|
||||
- Redact reports. HTML/JSON/JUnit artifacts may contain request URLs, headers, captured variables, and response snippets.
|
||||
- Keep authentication material in local secret storage and use dedicated test accounts with minimum privilege.
|
||||
|
||||
## Validation Deliverable
|
||||
|
||||
1. reviewed `.hurl` file with variableized target and no embedded secrets
|
||||
2. vulnerable, fixed, and negative-control environment descriptions
|
||||
3. assertion at every capability transition
|
||||
4. deterministic results with tool version and timestamps
|
||||
5. side effects, cleanup, and residual-state check
|
||||
6. redacted report appropriate for sharing
|
||||
@@ -0,0 +1,100 @@
|
||||
---
|
||||
name: hypothesis
|
||||
description: Property-based local differential testing with Hypothesis for parsers, canonicalizers, serializers, validators, routers, and other pure functions, emphasizing explicit invariants, shrinking, reproducibility, and bounded resource use
|
||||
---
|
||||
|
||||
# Hypothesis Differential Testing
|
||||
|
||||
Use [Hypothesis](https://hypothesis.readthedocs.io/) when a security property can be expressed over local code and failures are likely to hide in combinations of encoding, normalization, structure, or parser recovery. It is especially useful for comparing two implementations or checking that validation and consumption preserve the same meaning.
|
||||
|
||||
Do not point unrestricted generators at a live service. Hypothesis is safest and most useful against pure local adapters with no network, subprocess, filesystem, or persistent-state side effects.
|
||||
|
||||
## Install
|
||||
|
||||
Use an isolated virtual environment and install a reviewed pinned version:
|
||||
|
||||
```bash
|
||||
python -m pip install 'hypothesis==<reviewed-version>'
|
||||
```
|
||||
|
||||
Official project: [Hypothesis](https://github.com/HypothesisWorks/hypothesis)
|
||||
|
||||
## Start From an Invariant
|
||||
|
||||
Write the security relationship before writing strategies. Examples:
|
||||
|
||||
```text
|
||||
allowlist(raw) implies sink(canonicalize(raw)) remains inside the allowed origin/path
|
||||
validator(raw) accepts implies consumer(raw) assigns the same media type/structure
|
||||
parse_A(raw) and parse_B(raw) agree on message boundaries and authoritative fields
|
||||
serialize(parse(raw)) cannot introduce a delimiter, wildcard, traversal, or new field
|
||||
```
|
||||
|
||||
A test that only checks “does not crash” can find robustness bugs but does not establish a security differential.
|
||||
|
||||
## Minimal Differential Harness
|
||||
|
||||
```python
|
||||
from hypothesis import given, settings, strategies as st
|
||||
|
||||
|
||||
def outcome(parser, raw):
|
||||
try:
|
||||
return ("accept", parser(raw))
|
||||
except ExpectedParseError as exc:
|
||||
return ("reject", type(exc).__name__)
|
||||
|
||||
|
||||
@settings(max_examples=250, deadline=500)
|
||||
@given(st.text(max_size=128))
|
||||
def test_security_boundary(raw: str) -> None:
|
||||
checked = outcome(security_parser, raw)
|
||||
consumed = outcome(sink_parser, raw)
|
||||
assert equivalent_security_meaning(checked, consumed)
|
||||
```
|
||||
|
||||
- Bound string/list/binary sizes, recursion, examples, and deadline.
|
||||
- Build structured inputs from relevant tokens rather than generating unrestricted noise.
|
||||
- Normalize expected accept/reject/error outcomes explicitly so ordinary parser rejection is not mistaken for a property-test failure.
|
||||
- Use `st.one_of`, `st.sampled_from`, `st.lists`, `st.binary`, `st.text`, and composite strategies to represent the actual grammar.
|
||||
- Add explicit edge seeds with `@example` for known delimiters and regressions.
|
||||
- Let Hypothesis shrink failures; the minimal counterexample is often the clearest explanation of the parser disagreement.
|
||||
|
||||
## High-Value Strategy Axes
|
||||
|
||||
- percent and double encoding, malformed escapes, mixed separators
|
||||
- Unicode normalization, replacement characters, surrogates, case folding, IDNA
|
||||
- dot segments, slash/backslash, absolute/relative paths, sibling-prefix collisions
|
||||
- duplicate, empty, first/last, comma-joined, or differently cased fields
|
||||
- declared length versus actual bytes, truncation, padding, and terminators
|
||||
- nested objects, parser depth, ordering, unknown keys, and error recovery
|
||||
- serialize/deserialize round trips and version-to-version behavior
|
||||
|
||||
Generate only axes supported by the target's transformation graph. Cartesian payload spraying obscures causality.
|
||||
|
||||
## Reproducibility
|
||||
|
||||
- Keep the minimized failing example as a normal regression test.
|
||||
- Preserve code revision, dependency lock, locale, platform, and parser/library versions.
|
||||
- Keep Hypothesis's example database in a task-specific artifact directory when replay across runs matters.
|
||||
- For CI, rely on stored explicit regressions for critical cases; randomized discovery supplements them.
|
||||
- Classify nondeterminism before suppressing health checks. Timing, global state, environment, and shared caches can create flaky false differentials.
|
||||
|
||||
## Safety and Resource Controls
|
||||
|
||||
- Adapt target functions so tests cannot reach the network or execute commands.
|
||||
- Use temporary directories and non-secret corpora for parsers that require files.
|
||||
- Put native parsers in a disposable, networkless process/container with CPU, memory, file-size, and process ceilings.
|
||||
- Do not disable deadlines globally to hide hangs; isolate and bound intentionally slow examples.
|
||||
- A crash, timeout, or excessive allocation is a robustness result. Prove a security boundary or exploitability separately.
|
||||
- Never reuse captured credentials, customer content, or production requests as generative corpora without sanitization.
|
||||
|
||||
## Validation Deliverable
|
||||
|
||||
1. stated invariant and why it protects a security boundary
|
||||
2. adapters and exact component/version pair compared
|
||||
3. bounded strategies and resource settings
|
||||
4. minimized counterexample and both interpretations
|
||||
5. stable explicit regression test
|
||||
6. impact trace from disagreement to privileged consumer
|
||||
7. fixed-version or corrected-invariant result
|
||||
@@ -0,0 +1,207 @@
|
||||
---
|
||||
name: agentic-system-security
|
||||
description: Security testing for authorized AI agents and MCP-style tool ecosystems, covering effective authority, tool/resource/prompt inventory, confused-deputy behavior, side-effect authorization, cross-tenant isolation, executable component supply chain, shadow integrations, and repeatable safety regression
|
||||
---
|
||||
|
||||
# Agentic System Security
|
||||
|
||||
Use this skill when an AI system can select tools, retrieve resources, invoke remote/local services, maintain memory, delegate to other agents, or install skills/plugins. Pair it with `llm_prompt_injection` for instruction attacks and classic vulnerability skills for the downstream HTTP, cloud, filesystem, identity, or code-execution sink.
|
||||
|
||||
Prompt text is not an authorization boundary. Treat the agent runtime as a confused deputy whose effective authority is bounded by the union of its credentials, tools, resources, network reach, filesystem access, delegated agents, and approval policy, then reduce that upper bound to the actually reachable subset by tracing token audience, scopes, routing, target authorization, environment, and approval flow.
|
||||
|
||||
## Effective-Authority Map
|
||||
|
||||
Draw the complete path:
|
||||
|
||||
```text
|
||||
user / external content
|
||||
-> model context and memory
|
||||
-> planner / router / policy
|
||||
-> tool or delegated agent
|
||||
-> credential and target system
|
||||
-> side effect / returned data
|
||||
```
|
||||
|
||||
Inventory, for each node:
|
||||
|
||||
- trust source and tenant/user ownership
|
||||
- immutable component identity, package/server name, version, and transport
|
||||
- tools, resources, prompts, model endpoints, plugins, skills, and MCP servers
|
||||
- credential identity, issuer, audience/resource, subject, tenant, scopes/roles, expiry, downstream token exchange, environment, and where it is injected
|
||||
- readable data and write/execute capabilities
|
||||
- network/listener exposure and test-versus-production target
|
||||
- argument validation, authorization point, approval point, schema/argument digest, delegated principal propagation, and audit log
|
||||
- data returned to the model and whether it can contain new instructions
|
||||
|
||||
Test from the lowest-privileged realistic user and device. The key comparison is the user's authority versus the agent/tool credential's authority.
|
||||
|
||||
## Core Test Areas
|
||||
|
||||
### Shadow Agent and AI Discovery
|
||||
|
||||
Do not assume the approved application inventory contains every agent, model endpoint, browser extension, local MCP server, or AI API integration. Correlate multiple independent signals:
|
||||
|
||||
- DNS/proxy/egress logs for first-seen model, agent, vector database, plugin, and AI SaaS domains
|
||||
- OAuth/SSO grants, enterprise-app consent, service principals, API tokens, and unusual delegated scopes
|
||||
- endpoint processes, browser extensions/native messaging, listening loopback ports, and MCP client/server configuration
|
||||
- repository, CI/CD, secrets-manager, and container/image references to model providers, tool servers, and AI credentials
|
||||
- cloud-hosted model endpoints, notebooks, functions, gateways, and procurement/expense/SaaS inventory
|
||||
|
||||
Baseline local discovery from the host before interpreting network or SSO signals:
|
||||
|
||||
```bash
|
||||
# macOS
|
||||
lsof -nP -iTCP -sTCP:LISTEN
|
||||
ps -axo pid,ppid,user,command
|
||||
|
||||
# Linux
|
||||
ss -lntp
|
||||
ps -eo pid,ppid,user,args
|
||||
|
||||
# Windows PowerShell
|
||||
Get-NetTCPConnection -State Listen | Select-Object LocalAddress,LocalPort,OwningProcess
|
||||
Get-Process | Select-Object Id,ProcessName,Path
|
||||
|
||||
# Cross-platform config and credential leads
|
||||
rg -l 'mcpServers|modelContextProtocol|OPENAI_API_KEY|ANTHROPIC_API_KEY|AZURE_OPENAI_ENDPOINT' <reviewed-roots>
|
||||
```
|
||||
|
||||
Correlate each listener or config hit to PID/container, parent process, binary hash/version, launch command, config file, destination, and credential reference before calling it an active agent component. A loopback listener is a lead, not proof of reachable authority.
|
||||
|
||||
Classify each discovered integration by data read, data write, external communication, execution, identity/admin, and production reach. Human-validate attribution before treating a domain or key name as active AI use. Inspect unauthenticated local MCP/agent listeners separately; network inventory tools often miss loopback-only services.
|
||||
|
||||
### Tool Discovery and Argument Boundaries
|
||||
|
||||
- Enumerate advertised and conditionally available tools, resources, prompts, schemas, annotations, and delegated agents.
|
||||
- Compare what the UI exposes with what the protocol/runtime accepts directly.
|
||||
- Test missing, extra, duplicate, nested, oversized, alternate-type, and cross-tenant identifiers in tool arguments.
|
||||
- Validate scheme/host/path, filesystem paths, cloud resource IDs, recipient identities, SQL/query fields, and command arguments at the tool boundary.
|
||||
- Treat tool descriptions, names, examples, resource metadata, and returned content as attacker-influenceable unless provenance is enforced.
|
||||
- Canonicalize tool identity as `server identity/version + endpoint/transport + tool name + schema digest`; do not collapse two identically named tools from different servers into one trust decision.
|
||||
- Treat protocol hints such as `readOnlyHint`, `destructiveHint`, `idempotentHint`, and `openWorldHint` as untrusted metadata, not authorization.
|
||||
- Verify that unknown tools or schema-invalid calls fail closed without falling back to a broader handler.
|
||||
|
||||
### Confused Deputy and Consequential Actions
|
||||
|
||||
- Ask whether untrusted user/document/tool text can choose the tool, target, identity, or action.
|
||||
- Test read-to-write escalation: a summarizer should not send, publish, delete, purchase, deploy, or modify because retrieved text requests it.
|
||||
- Test whether approval binds the exact server identity/version, tool name, schema digest, normalized arguments, credential, target, side effect, and expiry. Revalidate those fields immediately before execution; a generic “continue?” is weak if arguments can change after approval.
|
||||
- Exercise replay, retry, parallel calls, partial failure, cancellation, and delegated execution for duplicate or bypassed actions.
|
||||
- Prove impact at the actual target and audit log. Model narration or a fabricated tool result is not evidence.
|
||||
- Use dry-run/no-op/read-only operations first; require explicit human approval for consequential operations.
|
||||
|
||||
### Identity, Tenant, and Environment Isolation
|
||||
|
||||
- Vary user, workspace, tenant, session, conversation, and delegated-agent identity independently.
|
||||
- Test whether one tenant can reference another tenant's resources, tool sessions, caches, vector entries, files, or credentials.
|
||||
- Check whether development/test tools or credentials can reach production, and whether local tools inherit broad workstation authority.
|
||||
- Verify credential scoping at the target service, not only in the agent's application logic.
|
||||
- Confirm memory and cached tool results are partitioned and revoked when identity or role changes.
|
||||
|
||||
### MCP and Local Tool Servers
|
||||
|
||||
- Inventory stdio, streamable HTTP, SSE/legacy, and custom transports; record bind address, origin/auth controls, process command, environment, and lifecycle.
|
||||
- Look for unauthenticated loopback services reachable from browsers, containers, local users, SSRF, port forwarding, or shared hosts.
|
||||
- Compare `tools/list`, `resources/list`, and `prompts/list` results across identities, but do not assume listing means calling is authorized.
|
||||
- For each tool, validate the same authorization and argument checks through every supported transport.
|
||||
- Treat server-launched subprocess configuration, environment variables, and working directories as sensitive executable configuration.
|
||||
- For HTTP/SSE transports, validate OAuth issuer, signature, expiry, audience/resource, tenant, and scope claims at the server boundary. Reject tokens minted for the wrong audience, and do not treat a session ID as identity.
|
||||
- For downstream APIs, do not pass through the same bearer token unless the target explicitly authorizes that audience and principal. Separate upstream MCP authentication from downstream target authorization.
|
||||
- For browser or loopback OAuth, review redirect URI, state/PKCE handling, localhost binding, and consent proxying. Treat metadata fetches and tool discovery on remote servers as SSRF-relevant surfaces.
|
||||
- For stdio servers, the launch command and environment are already code execution. Discovery must not execute an unreviewed server binary or mutable package tag.
|
||||
|
||||
### Executable Component Supply Chain
|
||||
|
||||
Every skill, plugin, MCP server, model adapter, package, and update channel is an executable or behavior-shaping dependency. Record:
|
||||
|
||||
- canonical source, publisher, package namespace, pinned version and integrity/provenance
|
||||
- install/update mechanism, manifest/lockfile/config source, mutable tags, automatic updates, and rollback path
|
||||
- declared and effective permissions, credentials, filesystem/network access
|
||||
- transitive dependencies and lifecycle scripts
|
||||
- review/approval ownership and last verification date
|
||||
|
||||
In agent and MCP configs, inspect `command: npx` with `-y` and a bare package or
|
||||
binary name. The process can fetch code without an interactive prompt and then
|
||||
run it with the agent's authority. Load `npx_confusion` to determine whether the
|
||||
name resolves locally, becomes a public package spec, and belongs to the
|
||||
intended publisher.
|
||||
|
||||
Test missing/private-name fallback, typosquatting exposure, mutable remote instructions, compromised-update blast radius, and whether an “instruction-only” component can invoke tools or modify executable files. Resolve `latest`, floating git refs, and mutable image tags to immutable versions or digests before launch. Do not claim or publish contestable package names as proof, and do not execute unknown packages just to discover what they are.
|
||||
|
||||
Load `infrastructure_lifecycle` when a skill, plugin, MCP server, model adapter, tool-schema origin, package namespace, or update endpoint is retired, mutable, or externally reassignable. Passive receipt of an agent heartbeat or catalog request does not authorize returning tool definitions, prompts, commands, or executable content.
|
||||
|
||||
### Output, Telemetry, and Failure Modes
|
||||
|
||||
- Validate model/tool output before it reaches HTML, shell, SQL, URLs, file paths, templates, or a second agent.
|
||||
- Ensure logs record initiating user, tool/server identity, sanitized arguments, approval, target, result, and correlation ID without storing secrets.
|
||||
- Test timeout, tool error, truncated output, malformed result, model retry, and policy-service failure. Failures should not silently switch to a more privileged tool or credential.
|
||||
- Verify kill switches, credential revocation, and disabling a component actually terminate active sessions and queued work.
|
||||
|
||||
## Safe Testing Workflow
|
||||
|
||||
1. **Map** every capability and trust boundary before injecting prompts.
|
||||
2. **Classify** tools as read, write, execute, communicate, identity/admin, or external-cost.
|
||||
3. **Establish controls** with dedicated test tenants, synthetic data, read-only credentials, budgets, and target allowlists.
|
||||
4. **Probe one boundary** at a time: selection, arguments, authorization, approval, execution, result handling.
|
||||
5. **Validate the side effect** in the target system and audit trail; compare denied and allowed identities.
|
||||
6. **Chain confirmed primitives** using the effective-authority and capability map from this skill.
|
||||
7. **Clean up and revoke** created data, sessions, tokens, and local servers.
|
||||
8. **Turn each confirmed case into a regression** across relevant models, prompts, tools, roles, and environments.
|
||||
|
||||
## MCP Inspector (Conditional)
|
||||
|
||||
Use the official [MCP Inspector](https://github.com/modelcontextprotocol/inspector) only against a reviewed local/test server:
|
||||
|
||||
```bash
|
||||
npx @modelcontextprotocol/inspector@<reviewed-version> --cli \
|
||||
--config reviewed-mcp.json --server test-server \
|
||||
--method tools/list --format json
|
||||
```
|
||||
|
||||
- Current upstream requirements should be checked before pinning; as of August 12, 2026, MCP Inspector 2.1.0 requires Node.js `>=22.19.0`.
|
||||
- Prefer CLI/TUI and loopback binding over exposing the web UI.
|
||||
- Preserve the generated API token; never disable authentication or bind the process-spawning backend to an external interface.
|
||||
- Do not publish ports 6274/6277 or pass through the Docker socket/host devices.
|
||||
- `tools/list` is protocol-read-only, but launching/initializing an arbitrary stdio server executes it and list handlers can still have process-side effects. Review the server command/config first. Calling a tool can perform real external actions.
|
||||
- Treat the inspected server command/config as executable; `npx` also downloads code, so pin a reviewed package version for repeatable or sensitive work.
|
||||
|
||||
## Regression With Promptfoo (Conditional)
|
||||
|
||||
[Promptfoo](https://github.com/promptfoo/promptfoo) can encode a bounded model/tool safety matrix after manual validation:
|
||||
|
||||
```bash
|
||||
npx promptfoo@<reviewed-version> eval
|
||||
```
|
||||
|
||||
- Current upstream engine constraints should be checked before pinning; as of August 12, 2026, Promptfoo documents Node.js `^20.20.0` or `>=22.22.0`.
|
||||
- Use synthetic prompts/data and a dedicated test provider/project.
|
||||
- Provider calls transmit data externally and can incur cost even when evaluation orchestration is local. Set request/concurrency and spending ceilings.
|
||||
- Pin model, provider, prompt, tool schema, retrieval corpus revision, and evaluator versions.
|
||||
- Include allowed and denied controls across roles/tenants; use multiple runs for nondeterministic outcomes.
|
||||
- Automated red-team labels are leads, not findings. Confirm the real tool call, data access, or side effect manually.
|
||||
- Store redacted results; evaluation logs can contain system prompts, secrets, retrieved data, and tool arguments.
|
||||
|
||||
## Validation
|
||||
|
||||
A report must include:
|
||||
|
||||
1. initiating identity, tenant, model/runtime, and exact component versions
|
||||
2. effective-authority map and relevant tool/resource schema
|
||||
3. untrusted input source and decision boundary crossed
|
||||
4. exact target-side operation or data access, with redacted audit evidence
|
||||
5. denied identity/input and allowed control results across repeat runs
|
||||
6. credential, feature, approval, environment, and user-interaction prerequisites
|
||||
7. cleanup/revocation and a bounded regression case
|
||||
|
||||
## False Positives
|
||||
|
||||
- The model claims a tool ran but the target and audit log show no action.
|
||||
- A listed tool cannot be invoked by the tested identity or validates arguments safely.
|
||||
- A safety refusal changes wording but effective capability remains denied.
|
||||
- Cross-session output is synthetic, cached public data, or hallucinated rather than another user's data.
|
||||
- A scanner flags an instruction string without showing that it reaches a privileged decision or sink.
|
||||
- A component has broad declared permissions but the runtime credential/network policy prevents the claimed access.
|
||||
|
||||
## Summary
|
||||
|
||||
Agent security is capability security. Map the real authority carried through models, tools, credentials, plugins, and delegated agents; validate authorization and approval at the target-side effect; treat every installed component as executable supply chain; and preserve each confirmed boundary failure as a bounded regression.
|
||||
@@ -9,6 +9,8 @@ Prompt injection occurs when attacker-influenced content changes model behavior
|
||||
|
||||
Load `llm_applications` for the full OWASP 2026 LLM01-LLM10 architecture and coverage workflow. Treat every LLM feature as a potential confused deputy: models cannot reliably distinguish instructions from data, but impact depends on the application's data, tools, decisions, and output sinks.
|
||||
|
||||
When the system can invoke MCP servers, plugins, skills, delegated agents, or consequential tools, also load `agentic_system_security` to model effective authority, target-side authorization, executable component supply chain, and repeatable safety regression. This skill remains focused on instruction/data confusion and unsafe model output.
|
||||
|
||||
## Attack Surface
|
||||
|
||||
**Direct Injection**
|
||||
|
||||
@@ -7,6 +7,8 @@ description: Subdomain takeover testing for dangling DNS records and unclaimed c
|
||||
|
||||
Subdomain takeover lets an attacker serve content from a trusted subdomain by claiming resources referenced by dangling DNS (CNAME/A/ALIAS/NS) or mis-bound provider configurations. Consequences include phishing on a trusted origin, cookie and CORS pivot, OAuth redirect abuse, and CDN cache poisoning.
|
||||
|
||||
Use `infrastructure_lifecycle` instead for expired registrable domains, MX/recovery identity, update/control endpoints, or long-lived software consumers. Provider error fingerprints are leads; confirm current claimability and custom-domain ownership requirements from authoritative provider behavior/documentation.
|
||||
|
||||
## Attack Surface
|
||||
|
||||
- Dangling CNAME/A/ALIAS to third-party services (hosting, storage, serverless, CDN)
|
||||
|
||||
Reference in New Issue
Block a user