Skip to content
Back to skills

Kiro Capture

ASecurity

Capture and analyze kiro-cli HTTPS traffic using mitmdump. Sets up mitmdump proxy, provides the kiro-cli launch command, then parses the capture log to generate individual API call files and a detailed analysis report. Use via /kiro-capture.

  • 61 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 2, 2026
ai-agentsrustgobashawsapisecurity

Works with

  • terminal
  • cli
  • api

Security analysis

A100/100

Scanned October 2, 2026

npx -y skills add d-kuro/kirocc --skill kiro-capture --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Kiro Capture?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Kiro Capture
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/d-kuro-kiro-capture/badge)](https://www.skillsdirectory.com/skills/d-kuro-kiro-capture)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: kiro-capture
description: "Capture and analyze kiro-cli HTTPS traffic using mitmdump. Sets up mitmdump proxy, provides the kiro-cli launch command, then parses the capture log to generate individual API call files and a detailed analysis report. Use via /kiro-capture."
disable-model-invocation: true
---

# kiro-capture

Capture kiro-cli HTTPS traffic with mitmdump and generate analysis reports.

## Phase Detection

On invocation, find the latest session under `/tmp/kiro-capture/`:

```bash
LATEST=$(ls -dt /tmp/kiro-capture/*/ 2>/dev/null | head -1)
if [ -n "$LATEST" ] && [ -f "${LATEST}state.json" ]; then
  cat "${LATEST}state.json"
fi
```

Decision logic:

- `state.json` exists with `"status": "capturing"`:
  - Check PID with `kill -0 <pid>`
  - PID alive → ask user: "Capture in progress. Stop and analyze?" If yes → Phase 2
  - PID dead → tell user "mitmdump already stopped. Analyzing log." → Phase 2
- `state.json` exists with `"status": "completed"` or `"status": "analyzing"` → ask user: "Previous capture is done. Start a new capture?"
- No `state.json` or empty directory → Phase 1

## Phase 1: Setup

### Step 1 — Check prerequisites

```bash
which mitmdump
```

If not found:

```bash
brew install mitmproxy
```

Check CA certificate:

```bash
ls ~/.mitmproxy/mitmproxy-ca-cert.pem
```

If missing, run mitmdump once to generate it:

```bash
mitmdump --set flow_detail=0 &
MITM_PID=$!
sleep 2
kill $MITM_PID 2>/dev/null
wait $MITM_PID 2>/dev/null
```

### Step 2 — Check port availability

```bash
lsof -i :8080 -t 2>/dev/null
```

If port 8080 is in use, try 8081, 8082, ... until a free port is found.

### Step 3 — Create session directory

```bash
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
SESSION_DIR="/tmp/kiro-capture/${TIMESTAMP}"
mkdir -p "$SESSION_DIR"
```

### Step 4 — Start mitmdump

```bash
mitmdump -p $PORT --set flow_detail=3 >"${SESSION_DIR}/raw.log" 2>&1 &
MITM_PID=$!
sleep 1
kill -0 $MITM_PID 2>/dev/null && echo "OK" || echo "FAILED"
```

### Step 5 — Save state.json

Write to `${SESSION_DIR}/state.json`:

```json
{
  "status": "capturing",
  "pid": <MITM_PID>,
  "port": <PORT>,
  "session_dir": "<SESSION_DIR>",
  "started_at": "<ISO8601>"
}
```

### Step 6 — Output kiro-cli launch command

Tell the user:

"mitmdump is running on port {PORT}. Run the following command in a **separate terminal** to start kiro-cli through the proxy:

```bash
HTTPS_PROXY=http://127.0.0.1:{PORT} \
HTTP_PROXY=http://127.0.0.1:{PORT} \
SSL_CERT_FILE=~/.mitmproxy/mitmproxy-ca-cert.pem \
kiro-cli chat
```

When you're done using kiro-cli, come back here and run `/kiro-capture` again to stop the capture and generate the analysis report.

Session directory: `{SESSION_DIR}`"

Phase 1 ends here. Wait for the user to re-invoke.

## Phase 2: Analysis

### Step 7 — Stop mitmdump

Read PID from `state.json` and stop that specific process:

```bash
kill <PID_FROM_STATE_JSON>
while kill -0 <PID_FROM_STATE_JSON> 2>/dev/null; do sleep 0.2; done
```

Skip if PID is already dead.

### Step 8 — Update state.json

Set `status` to `"analyzing"`.

### Step 9 — Parse capture log

Read `${SESSION_DIR}/raw.log` and extract request/response pairs.

mitmdump `flow_detail=3` output format:

```
<IP>: <METHOD> <URL>
    <header>: <value>
    ...

<request body>

<< <STATUS> <SIZE>
    <header>: <value>
    ...

<response body>
```

For each request/response pair, extract:

1. **Sequence number** — assign 01, 02, ... in order of appearance
2. **API name** — from `x-amz-target` header. Known APIs:
   - `AmazonCodeWhispererStreamingService.GenerateAssistantResponse` (EventStream response)
   - `AmazonCodeWhispererService.ListAvailableModels` (JSON)
   - `ToolkitTelemetry.ClientTelemetryMetrics` (JSON)
   - `AmazonCodeWhispererService.GetProfile` (JSON)
   - `AmazonCodeWhispererService.GetUsageLimits` (JSON, **403 is expected/normal**; may be absent in a session)
   - `AmazonCodeWhispererService.SendTelemetryEvent` (JSON)
   - `AWSCognitoIdentityService.GetCredentialsForIdentity` (JSON; cognito-identity host — returns temporary AWS creds used to SigV4-sign the telemetry calls)
   - If no `x-amz-target`, infer from URL path/host:
     - `oidc.*.amazonaws.com/token` → `SSOOIDC.CreateToken` (JSON; `grantType: refresh_token` rotates the Bearer token mid-session)
     - `client-telemetry.*.amazonaws.com/metrics` → `ToolkitTelemetry.ClientTelemetryMetrics`
3. **Request URL**
4. **Request headers** — all headers, but redact:
   - `authorization` header value → `[REDACTED]` (covers both `Bearer <token>` and `AWS4-HMAC-SHA256 ... Signature=...`)
   - `x-amz-security-token` header value → `[REDACTED]`
5. **Request body** — extract JSON as-is, but redact secret **values** in these bodies:
   - `CreateToken` request: `refreshToken`, `clientSecret` → `[REDACTED]`
6. **Response status** — from `<< STATUS SIZE` line
7. **Response headers**
8. **Response body**:
   - JSON → extract as-is, but redact secret **values**:
     - `GetCredentialsForIdentity` response: `AccessKeyId`, `SecretKey`, `SessionToken` → `[REDACTED]`
     - `CreateToken` response: `accessToken`, `refreshToken` → `[REDACTED]`
   - EventStream (`application/vnd.amazon.eventstream`) → apply EventStream parsing below

**Redaction rule:** secret values may only ever appear in `raw.log` (the mitmdump input). Every generated `.md` must contain `[REDACTED]` in their place. After generating files, verify no secret fragment (AWS `ASIA...` access key IDs, `Bearer aoa...`/`aor...` tokens, `AWS4-HMAC ... Signature=<hex>`, Cognito `IQoJ...` session tokens) leaks into any `.md` — including `report.md` prose.

### EventStream response parsing

`GenerateAssistantResponse` responses use EventStream binary format. In mitmdump logs, binary and text are interleaved.

Parsing steps:

1. Identify event boundaries by `:event-type` markers
2. Extract JSON objects (`{...}`) from each event segment
3. Classify events:
   - `initial-response` — stream preamble (`{"conversationId":""}`)
   - `reasoningContentEvent` — native reasoning/thinking stream: `text` deltas followed by a final `signature` field. Concatenate the `text` deltas; note the `signature` exists but show it as `[present]` (do not dump the full value)
   - `assistantResponseEvent` — assistant response text (delta `content` field)
   - `toolUseEvent` — tool call (`name`, `toolUseId`, `input` fields)
   - `metadataEvent` — turn end (`stopReason`, e.g. `END_TURN`)
   - `contextUsageEvent` — context usage (`contextUsagePercentage` field)
   - `meteringEvent` — credit consumption (`{"unit":"credit","usage":...}`)
4. Merge events sharing the same `toolUseId` to reconstruct complete tool calls
5. Concatenate `assistantResponseEvent` `content` fields to reconstruct full response text; concatenate `reasoningContentEvent` `text` fields to reconstruct the reasoning trace

> Note: `reasoningContentEvent` and `meteringEvent` are emitted by kiro-cli 2.10.0. Reasoning is now **native** (a `reasoningContentEvent` stream), not a `thinking` tool in the tools array.

### Step 10 — Generate individual API call files

For each request/response pair, create `${SESSION_DIR}/NN_APIName.md`.

Format (follows existing `_docs/capture/01_ClientTelemetryMetrics.md`):

```markdown
# NN. ServiceName.APIName

## Request

\`\`\`
METHOD URL
\`\`\`

### Request Headers

\`\`\`
header: value
authorization: [REDACTED]
x-amz-security-token: [REDACTED]
...
\`\`\`

### Request Body

\`\`\`json
{JSON body}
\`\`\`

## Response

\`\`\`
STATUS SIZE
\`\`\`

### Response Headers

\`\`\`
header: value
...
\`\`\`

### Response Body

\`\`\`json
{JSON body}
\`\`\`
```

For EventStream responses, use this Response Body format instead:

```markdown
### Response Body

Content-Type: `application/vnd.amazon.eventstream`

**Events:**

| #   | Event Type             | Summary                          |
| --- | ---------------------- | -------------------------------- |
| 1   | initial-response       | conversationId ""                |
| 2   | reasoningContentEvent  | {text delta / signature present} |
| 3   | assistantResponseEvent | {first 80 chars}                 |
| 4   | toolUseEvent           | {tool name}: {first 80 chars}    |
| 5   | metadataEvent          | stopReason {value}               |
| 6   | contextUsageEvent      | {percentage}%                    |
| 7   | meteringEvent          | {usage} credits                  |

**Full reasoning text:** (if any reasoningContentEvent)

\`\`\`
{concatenated reasoning text}
\`\`\`

**Full assistant response:**

\`\`\`
{concatenated full text}
\`\`\`

**Tool calls:** (if any toolUseEvent)

\`\`\`json
[{reconstructed tool call objects}]
\`\`\`

**Metering:** {unit}, usage {value}
```

### Step 11 — Generate analysis report

Create `${SESSION_DIR}/report.md`.

Template:

```markdown
# Capture Analysis Report — {TIMESTAMP}

## Capture Environment

| Item             | Value                                                 |
| ---------------- | ----------------------------------------------------- |
| Date             | {started_at from state.json}                          |
| kiro-cli version | {from user-agent: md/appVersion-X.Y.Z}                |
| AWS SDK          | {from user-agent: aws-sdk-rust/X.Y.Z}                 |
| OS               | {from user-agent}                                     |
| Model            | {modelId from GenerateAssistantResponse request body} |
| Region           | {from request URL hostname}                           |
| Capture tool     | mitmdump (mitmproxy)                                  |
| Raw log          | [raw.log](raw.log)                                    |

## API Call Summary

| #   | API                     | Status   | Size   | File                           |
| --- | ----------------------- | -------- | ------ | ------------------------------ |
| 01  | {ServiceName}.{APIName} | {status} | {size} | [01_APIName.md](01_APIName.md) |
| ... |

## API Category Breakdown

| Category                      | Count | APIs                                                                |
| ----------------------------- | ----- | ------------------------------------------------------------------- |
| CodeWhispererStreamingService | {n}   | GenerateAssistantResponse                                           |
| CodeWhispererService          | {n}   | GetProfile, ListAvailableModels, GetUsageLimits, SendTelemetryEvent |
| ToolkitTelemetry              | {n}   | ClientTelemetryMetrics                                              |
| AWSCognitoIdentityService     | {n}   | GetCredentialsForIdentity                                           |
| SSOOIDC                       | {n}   | CreateToken                                                         |

(Omit categories with count 0.)

## Authentication

1. **Bearer Token** (`authorization: Bearer <token>`): CodeWhisperer / kiro.dev API
2. **AWS Signature V4** (`authorization: AWS4-HMAC-SHA256 ...`): Telemetry API
3. **Cognito + OIDC**: `GetCredentialsForIdentity` yields the temporary AWS creds that SigV4-sign the telemetry calls; `CreateToken` (`grantType: refresh_token`) refreshes the Bearer token mid-session (note if/when the token rotates)

## Conversation Flow

Group requests by conversationId and agentContinuationId. Render as ASCII tree:

\`\`\`

1. kiro-cli startup
   ├── ClientTelemetryMetrics (...)
   ├── GetProfile
   ├── ...

2. User message sent
   ├── GenerateAssistantResponse #1 (...)
   ├── SendTelemetryEvent
   └── ClientTelemetryMetrics (...)

3. Tool result sent
   ├── GenerateAssistantResponse #2 (...)
   ...
   \`\`\`

## Context Usage

| #   | GenerateAssistantResponse | History length    | contextUsagePercentage |
| --- | ------------------------- | ----------------- | ---------------------- |
| 1   | #NN                       | {history entries} | {percentage}%          |
| ... |

## Model Info

- Model ID: {modelId}
- Reasoning/thinking: {active/inactive — active if the response has a `reasoningContentEvent` stream. kiro-cli 2.10.0 uses native reasoning, so there is no `thinking` tool in the tools array}
- Tool count: {length of tools array}

## Tool Usage Patterns

| Tool name                     | Invocation count |
| ----------------------------- | ---------------- |
| {tool name from toolUseEvent} | {count}          |

(If no toolUseEvent occurred, report `(none) | 0` and note the turns were plain text.)

## Notable Findings

Bullet list of anything noteworthy vs. prior captures, e.g.:

- New event types or APIs observed (e.g. `reasoningContentEvent`, `meteringEvent`)
- Bearer token refresh / rotation via OIDC `CreateToken`
- Model-catalog specifics from `ListAvailableModels` (rateMultiplier, maxOutputTokens, context window, thinking.type enum)
- APIs that were expected but absent (e.g. `GetUsageLimits`)
- Metering / credit usage per turn
```

### Step 12 — Update state.json

Set `status` to `"completed"`. Add `completed_at` timestamp.

### Step 13 — Report to user

Tell the user:

"Capture analysis complete.

- Session directory: `{SESSION_DIR}`
- Raw log: `{SESSION_DIR}/raw.log`
- Analysis report: `{SESSION_DIR}/report.md`
- Individual API calls: `{SESSION_DIR}/NN_*.md` ({count} files)

Total API calls: {total_count}

- GenerateAssistantResponse: {count}
- Others: {count}

Context usage (final): {last_percentage}%"

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…