AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Pwnote Engagement File

skill-pwnote-skills-pwnote-engagement-file · by Pwnote

Create or validate a pwnote engagement import/export JSON file. Use when the user wants to generate, edit, or verify a pwnote engagement file for data transfer between pwnote instances. The file bundles an entire pentest engagement — metadata, notebook documents, code/host/credential blocks, findings with CVSS/cwe/cve, attack-path boards, and activity history. Also use when the user asks how to s…

No reviews yet
0 installs
25 views
0.0% view→install

Install

$ agentstack add skill-pwnote-skills-pwnote-engagement-file

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-pwnote-skills-pwnote-engagement-file)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
21d ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Pwnote Engagement File? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Security

This skill describes the engagement file schema for data transfer between pwnote instances. Follow these rules:

  • Never output real credential secret values anywhere — use `` as placeholder
  • Never log, echo, or print plaintext secrets
  • Treat requestBody, requestHeaders, responseBody fields as potentially sensitive — redact before sharing externally
  • The secret field in credential blocks is populated from user-provided data, never generated by the agent

Installation

npx skills add Pwnote/skills

Pwnote Engagement File Format

Reference for creating or editing pwnote engagement import/export JSON files. A valid file contains all data for one pentest engagement and can be imported via Settings → Import or the workspace Import button.

File Structure

{
  "engagement": { ... },
  "docs": [ ... ],
  "blocks": [ ... ],
  "findings": [ ... ],
  "boards": [ ... ],
  "boardNodes": [ ... ],
  "boardEdges": [ ... ],
  "activity": [ ... ]
}

All top-level keys are required but may be empty arrays.

Field Reference

engagement (object)

| Field | Type | Required | Description | |-------|------|----------|-------------| | name | string | yes | Engagement name, e.g. "Q4External2026" | | client | string | yes | Client name, e.g. "Acme Corp" | | testType | string | yes | One of: "black-box", "grey-box", "white-box" | | scope | string[] | yes | IPs, domains, CIDRs, app URLs | | roe | string | no | Rules of engagement as free text | | startDate | string | yes | ISO date "YYYY-MM-DD" | | endDate | string | yes | ISO date "YYYY-MM-DD" | | testers | string[] | yes | Operator names/handles | | archived | boolean | yes | false for new engagements |

Generated fields (omit — set on import): id, createdAt, updatedAt.

docs (array of objects)

| Field | Type | Required | Description | |-------|------|----------|-------------| | title | string | yes | Doc name, e.g. "01_Recon" | | order | number | yes | Sort order within engagement | | parentId | string | no | Parent doc ID for folder nesting | | folder | boolean | no | true if this doc is a folder |

Generated fields: id, engagementId, createdAt, updatedAt.

blocks (array of objects)

Each block has these base fields plus type-specific fields:

Base fields (all block types): | Field | Type | Required | Description | |-------|------|----------|-------------| | type | string | yes | Block type discriminator (see below) | | docId | string | yes | Must match a doc id in the file | | order | number | yes | Sort order within doc | | tags | string[] | no | Tag labels, e.g. ["nmap", "discovery"] |

Generated fields: id.

Type-specific fields:

"heading" — Section header | Field | Type | Required | Description | |-------|------|----------|-------------| | level | number | yes | 1, 2, or 3 | | text | string | yes | Heading text |

Use level: 1 for document titles, level: 2 for major sections, level: 3 for sub-sections. Always use a mix of levels for structure — never use only level 1.

"paragraph" — Plain text | Field | Type | Required | Description | |-------|------|----------|-------------| | text | string | yes | Paragraph content |

"markdown" — Rich text block | Field | Type | Required | Description | |-------|------|----------|-------------| | markdown | string | yes | Markdown content |

"code" — Code snippet | Field | Type | Required | Description | |-------|------|----------|-------------| | language | string | yes | e.g. "bash", "python3", "rust", "go", "javascript", "typescript", "sql", "yaml" | | code | string | yes | Code content |

"command-output" — Shell command and its output | Field | Type | Required | Description | |-------|------|----------|-------------| | command | string | yes | The command run | | output | string | yes | Command output text | | timestamp | string | no | ISO timestamp |

"host" — Host/asset entry | Field | Type | Required | Description | |-------|------|----------|-------------| | ip | string | yes | IP address | | hostname | string | no | DNS name | | os | string | no | Operating system | | ports | string[] | yes | Port list, e.g. ["22/tcp", "80/tcp", "443/tcp"] | | notes | string | no | Free-text notes |

"credential" — Credential (sensitive). The secret field must use ` when demonstrating — never output real values. | Field | Type | Required | Description | |-------|------|----------|-------------| | username | string | yes | Username | | secret | string | yes | in examples; real values come from user-provided data only | | secretType | string | yes | One of: "password", "hash", "token", "key" | | source | string | no | Where credential was found | | sensitive | boolean | yes | Always true` |

"screenshot" — Image evidence | Field | Type | Required | Description | |-------|------|----------|-------------| | dataUrl | string | no | Base64 data URL of image | | caption | string | no | Image caption |

"checklist" — Task checklist | Field | Type | Required | Description | |-------|------|----------|-------------| | title | string | yes | Checklist title | | items | array | yes | Array of { id: string, text: string, done: boolean } |

"timeline" — Timeline event | Field | Type | Required | Description | |-------|------|----------|-------------| | timestamp | string | yes | ISO datetime | | event | string | yes | Event description | | actor | string | no | Who performed the action |

"table" — Data table | Field | Type | Required | Description | |-------|------|----------|-------------| | headers | string[] | yes | Column headers | | rows | array | yes | Array of string arrays (cells) |

"separator" — Visual divider No extra fields beyond base.

"http-request" — HTTP request/response pair | Field | Type | Required | Description | |-------|------|----------|-------------| | method | string | yes | HTTP method: "GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS" | | url | string | yes | Request URL | | requestHeaders | string | yes | Raw request headers (one per line) | | requestBody | string | yes | Request body | | responseStatus | number | yes | HTTP status code (0 if no response) | | responseHeaders | string | yes | Raw response headers (one per line) | | responseBody | string | yes | Response body |

"finding" — Linked finding (references a finding by ID) | Field | Type | Required | Description | |-------|------|----------|-------------| | findingId | string | yes | Must match a finding id in the file |

findings (array of objects)

| Field | Type | Required | Description | |-------|------|----------|-------------| | title | string | yes | Finding title | | severity | string | yes | One of: "critical", "high", "medium", "low", "info" | | cvssScore | number | no | 0.0–10.0 | | cvssVector | string | no | CVSS vector string | | cwe | string | no | CWE identifier, e.g. "CWE-79" | | cve | string | no | CVE identifier, e.g. "CVE-2024-12345" | | affectedAssets | string[] | yes | Affected hosts/URLs | | description | string | yes | Vulnerability description | | poc | string | yes | Proof of concept | | remediation | string | yes | Fix guidance | | references | string[] | yes | URLs to references | | status | string | yes | One of: "draft", "confirmed", "fixed", "accepted-risk", "needs-retest" | | retestResult | string | no | Outcome of retest | | tags | string[] | yes | Tag labels |

Generated fields: id, engagementId, createdAt, updatedAt.

boards (array of objects)

| Field | Type | Required | Description | |-------|------|----------|-------------| | name | string | yes | Board name, e.g. "Topology" | | kind | string | yes | One of: "topology", "killchain", "planning", "forensics", "retest", "post-exploitation", "custom" | | locked | boolean | no | true to lock board from edits |

Generated fields: id, engagementId, createdAt, updatedAt.

boardNodes (array of objects)

| Field | Type | Required | Description | |-------|------|----------|-------------| | refType | string | yes | One of: "host", "finding", "credential", "freeform" | | refId | string | no | Links to block/finding ID (null for freeform) | | x | number | yes | Flow canvas X position | | y | number | yes | Flow canvas Y position | | data | object | no | Extra node data (label for freeform, ip/ports for host, etc.) | | boardId | string | yes | Must match a board id in the file |

Generated fields: id.

boardEdges (array of objects)

| Field | Type | Required | Description | |-------|------|----------|-------------| | source | string | yes | Source boardNode id | | target | string | yes | Target boardNode id | | label | string | no | Edge label (e.g. "credential" for cred edges) | | boardId | string | yes | Must match a board id in the file |

Generated fields: id.

activity (array of objects)

| Field | Type | Required | Description | |-------|------|----------|-------------| | actor | string | yes | Who performed the action | | kind | string | yes | Activity kind, e.g. "engagement.create", "block.create", "finding.status" | | message | string | yes | Human-readable description | | meta | object | no | Extra metadata |

Generated fields: id, engagementId, timestamp.

ID Linking Rules

IDs in export files are local references. The import process regenerates all IDs but preserves the relationship graph by remapping foreign keys automatically. Use any ID pattern you like (e.g. tmp_doc_recon, tmp_f_xss, tmp_bn_host1).

All cross-references MUST point to IDs defined within the same JSON file. The import remaps them to the newly generated IDs so links survive the import intact.

| Foreign Key | Points To | Field Location | |-------------|-----------|----------------| | block.docId | doc id | every block | | block.findingId | finding id | finding-type blocks only | | boardNode.boardId | board id | every boardNode | | boardNode.refId | block id or finding id | host/finding/credential nodes | | boardEdge.source | boardNode id | every boardEdge | | boardEdge.target | boardNode id | every boardEdge | | boardEdge.boardId | board id | every boardEdge |

Freeform nodes have refId: null (no link to any block/finding).

Node Linking Example

To display a host and linked finding on a topology board:

{
  "docs": [{ "id": "tmp_doc_recon", "title": "01_Recon", "order": 0 }],
  "blocks": [
    {
      "id": "tmp_b_host1", "docId": "tmp_doc_recon", "order": 0, "tags": [],
      "type": "host", "ip": "10.0.0.1", "hostname": "web.example.com",
      "os": "Ubuntu 22.04", "ports": ["22/tcp", "80/tcp", "443/tcp"]
    },
    {
      "id": "tmp_b_finding1", "docId": "tmp_doc_recon", "order": 1, "tags": ["web"],
      "type": "finding", "findingId": "tmp_f_xss"
    }
  ],
  "findings": [
    {
      "id": "tmp_f_xss", "title": "Reflected XSS",
      "severity": "high", "cvssScore": 6.1, "...": "..."
    }
  ],
  "boards": [
    { "id": "tmp_brd_topology", "name": "Topology", "kind": "topology" }
  ],
  "boardNodes": [
    {
      "id": "tmp_bn_host1", "boardId": "tmp_brd_topology",
      "refType": "host", "refId": "tmp_b_host1",
      "x": 100, "y": 100,
      "data": { "ip": "10.0.0.1", "hostname": "web.example.com", "ports": ["22/tcp", "80/tcp", "443/tcp"] }
    },
    {
      "id": "tmp_bn_finding1", "boardId": "tmp_brd_topology",
      "refType": "finding", "refId": "tmp_f_xss",
      "x": 350, "y": 100,
      "data": { "title": "Reflected XSS", "severity": "high", "cvssScore": 6.1 }
    }
  ],
  "boardEdges": [
    {
      "id": "tmp_be_1", "boardId": "tmp_brd_topology",
      "source": "tmp_bn_host1", "target": "tmp_bn_finding1",
      "label": "exploits"
    }
  ]
}

Key rules for node data:

  • host nodes: data must include ip, hostname, ports
  • finding nodes: data must include title, severity, cvssScore
  • credential nodes: data must include username, secretType
  • freeform nodes: data must include label (display text)
  • Edges between credential and host nodes should use label: "credential" for visual styling

Example: Minimal Engagement

{
  "engagement": {
    "name": "External Pentest Q4",
    "client": "Example Corp",
    "testType": "grey-box",
    "scope": ["10.0.0.0/24", "app.example.com"],
    "roe": "Testing window: 09-18 local.\nExclusions: production DB.",
    "startDate": "2026-07-21",
    "endDate": "2026-08-04",
    "testers": ["operator"],
    "archived": false
  },
  "docs": [
    { "id": "tmp_doc_recon", "title": "01_Recon", "order": 0, "engagementId": "tmp_eng" },
    { "id": "tmp_doc_exploit", "title": "02_Exploitation", "order": 1, "engagementId": "tmp_eng" }
  ],
  "blocks": [
    {
      "id": "tmp_b_host1", "docId": "tmp_doc_recon", "order": 0, "tags": [],
      "type": "host", "ip": "10.0.0.1", "hostname": "web.example.com", "os": "Ubuntu 22.04",
      "ports": ["22/tcp", "80/tcp", "443/tcp"]
    },
    {
      "id": "tmp_b_finding1", "docId": "tmp_doc_exploit", "order": 0, "tags": ["web"],
      "type": "finding", "findingId": "tmp_f_xss"
    },
    {
      "id": "tmp_b_sep1", "docId": "tmp_doc_recon", "order": 1, "tags": [],
      "type": "separator"
    },
    {
      "id": "tmp_b_code1", "docId": "tmp_doc_exploit", "order": 1, "tags": [],
      "type": "code", "language": "python3", "code": "print('hello')"
    }
  ],
  "findings": [
    {
      "id": "tmp_f_xss",
      "title": "Reflected XSS in search endpoint",
      "severity": "high",
      "cvssScore": 6.1,
      "affectedAssets": ["app.example.com/search"],
      "description": "The search parameter is reflected without sanitization.",
      "poc": "alert(1)",
      "remediation": "Encode HTML entities in the response.",
      "references": ["https://owasp.org/www-community/attacks/xss/"],
      "status": "confirmed",
      "tags": ["xss", "web"]
    }
  ],
  "boards": [
    {
      "id": "tmp_brd_topology",
      "name": "Topology", "kind": "topology", "locked": false,
      "engagementId": "tmp_eng", "createdAt": 0, "updatedAt": 0
    }
  ],
  "boardNodes": [
    {
      "id": "tmp_bn_host1", "boardId": "tmp_brd_topology",
      "refType": "host", "refId": "tmp_b_host1",
      "x": 100, "y": 100,
      "data": { "ip": "10.0.0.1", "hostname": "web.example.com", "ports": ["22/tcp", "80/tcp", "443/tcp"] }
    },
    {
      "id": "tmp_bn_finding1", "boardId": "tmp_brd_topology",
      "refType": "finding", "refId": "tmp_f_xss",
      "x": 300, "y": 100,
      "data": { "title": "Reflected XSS in search endpoint", "severity": "high", "cvssScore": 6.1 }
    }
  ],
  "boardEdges": [
    {
      "id": "tmp_be_1", "boardId": "tmp_brd_topology",
      "source": "tmp_bn_host1", "target": "tmp_bn_finding1",
      "label": "exploits"
    }
  ],
  "activity": [
    {
      "id": "tmp_act_1", "engagementId": "tmp_eng",
      "timestamp": 0, "actor": "operator",
      "kind": "engagement.create", "message": "Engagement created"
    }
  ]
}

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.