Skip to content
Back to skills

Grab Cookie

BSecurity

Capture, store, wire, and verify a browser-session credential for any site that has no API key and no OAuth path: an httpOnly session cookie, an opaque localStorage bearer token, or a custom auth header. The human step is one DevTools "Copy as cURL" paste, and everything around it is automated: parse the request, extract the secret per a per-site JSON profile, store it in the Windows Credential Manager or the macOS Keychain without the value entering the agent's context, regenerate whatever c...

  • 47 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 29, 2026
ai-agentsjavascriptpythongojavashellbashgitapisecurity

Works with

  • cli
  • api
  • mcp

Security analysis

B75/100
  • criticalAccesses system keychains or credential stores

Pro scans all 13 files and shows the line behind each finding

Scanned September 29, 2026

npx -y skills add Servosity/msp-skills --skill grab-cookie --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Grab Cookie?

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

Security grade badge for Grab Cookie
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/servosity-grab-cookie/badge)](https://www.skillsdirectory.com/skills/servosity-grab-cookie)

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: grab-cookie
description: >
  Capture, store, wire, and verify a browser-session credential for any site that
  has no API key and no OAuth path: an httpOnly session cookie, an opaque
  localStorage bearer token, or a custom auth header. The human step is one
  DevTools "Copy as cURL" paste, and everything around it is automated: parse the
  request, extract the secret per a per-site JSON profile, store it in the Windows
  Credential Manager or the macOS Keychain without the value entering the agent's
  context, regenerate whatever config file consumes it, and prove the result with
  a real authenticated call. A daily doctor re-probes every stored credential and
  warns before a known expiry instead of after.
  Use when the user says a tool stopped working after about a month, my session
  expired, re-auth this site, the cookie died again, refresh my token, this vendor
  has no API key, or set up auth for a site that only works when logged in.
  This Skill does NOT drive a browser. It reads a cURL command the user pastes.
  For vendors that DO expose OAuth or an API key, use connect-tool instead.
allowed-tools: "Read, Write, Bash, PowerShell, AskUserQuestion"
author: "Mike Bramm"
license: "Apache-2.0"
vendor: "BomberJacket Networks"
metadata:
  markdown_only: true
---

# grab-cookie - session credentials for sites with no API path

Some vendors never issue an API key. Their web app authenticates with an httpOnly
session cookie or an opaque token in localStorage, and the only way to reach the
API your agent needs is to borrow the session the browser already has.

That capture is irreducibly human: an httpOnly cookie is invisible to page
JavaScript by design, and a headless browser does not carry your login. What is
NOT irreducible is everything around it. This Skill automates the rest, so a
thirty-day re-auth costs one paste instead of an afternoon of remembering where
the token was supposed to go.

## When to use this Skill, and when not to

Use it when the vendor has no API-key or OAuth path for the surface you need, and
the working credential exists only inside a logged-in browser session.

Do not use it when the vendor does issue an API key or supports OAuth. The
`connect-tool` Skill in this repository handles those properly, including scope
changes and rotation. `connect-tool` deliberately refuses cookie import and never
reads `document.cookie` or `localStorage`, which is the correct choice for its
threat model. This Skill covers the case that choice leaves open, and it makes
the opposite tradeoff explicitly.

## 0. Running the helpers

Every helper is a stdlib Python script next to this file. Python 3.12 or newer,
no third-party packages, no compiled binary, no MCP server:

```bash
python "<this-skill-dir>/scripts/credgrab.py" <command> [args]
```

`<this-skill-dir>` is the directory containing this SKILL.md, which you already
know because you just read it. Use that path directly rather than searching the
filesystem, and do not hardcode an install location: a plugin install lands
somewhere other than `~/.claude/skills/grab-cookie`.

On Windows use `python`; on macOS use `python3`.

## 1. Pick or write a profile

A profile is one JSON file describing a single site: where the secret lives in
the request, where the consuming config file is, and how to prove the credential
works. Adding a site means adding a profile, not changing code.

Two annotated examples ship in `profiles/`:

- `example-cookie-site.json` for an httpOnly session cookie
- `example-bearer-token.json` for an opaque bearer token plus a second header

Copy one, rename it, and edit the four blocks: `extract`, `wire`, `verify`, and
the optional `ttl_days`.

## 2. Capture

Tell the user, in these words or close to them:

> Log into the site in Chrome. Press F12, open the Network tab, click any request
> to the site's API, right-click it, and choose Copy as cURL (bash). Paste it into
> `captures/<profile>.curl.txt` and save.

Copy as cURL is the right capture surface because DevTools shows the real request
the browser sent, including the httpOnly cookie that no script can read. The
parser accepts both the bash and cmd variants, since which one a user gets depends
on their platform. Choose **Copy as cURL (bash)** when it is offered: "Copy as
PowerShell" is a different menu item that emits `Invoke-WebRequest` rather than a
curl command, carries no `-H` flags, and parses to nothing.

The capture file is disposable. Delete it after seeding.

## 3. Seed

```bash
# macOS: use python3
python "<this-skill-dir>/scripts/credgrab.py" seed --profile <name> --curl captures/<name>.curl.txt
```

This parses the request, extracts each configured value, writes it to the OS
credential store, regenerates the consumer file from what was stored, and then
runs the profile's verify command. It prints a receipt (length, a short hash
prefix, last four characters) and never the secret.

If verification fails, the seed is reported as failed. A stored credential that
does not actually work is worse than no credential, because it fails later and
somewhere else.

## 4. Re-wire without re-capturing

```bash
python "<this-skill-dir>/scripts/credgrab.py" wire --profile <name>
```

The credential store is the source of truth, so a consumer config file can be
deleted, corrupted, or excluded from a backup and rebuilt with no browser step.

One exception, and it is a hard failure rather than a surprise: an `env-file`
consumer is REGENERATED from scratch, so `wire` refuses to overwrite one that
holds any line this profile did not write - a hand-added key, a commented-out
setting, or a whole foreign config file. The message gives the line NUMBERS, never their content - a line this profile did not write can be another tool's secret, and the message is model-visible. Either
point `wire.path` at a file this profile owns exclusively and have your tool read
both, or delete the file and re-run the command you just ran if it is stale. (A refusal
during `seed` has already rolled the credential back, so re-run `seed`, not `wire` -
`wire` would rebuild the file from the old value.)
This is the command to reach for when a tool suddenly cannot authenticate but the
session itself has not expired.

## 5. Verify and monitor

```bash
python "<this-skill-dir>/scripts/credgrab.py" verify --profile <name>
python "<this-skill-dir>/scripts/credgrab.py" doctor --all
```

`doctor --all` is what you schedule. It probes every stored credential and reports
those that are dead or close to a known expiry, which converts a silent thirty-day
breakage into a warning that arrives before the tool stops working.

Wire it to whatever notifier you already use. A daily run is usually enough for a
thirty-day session.

## 6. Self-check

```bash
python "<this-skill-dir>/scripts/credgrab.py" --selfcheck          # offline checks only
python "<this-skill-dir>/scripts/credgrab.py" --selfcheck --live   # + real credential store
```

Plain `--selfcheck` runs the offline checks - redaction, blob round-trip, cURL
parsing, the consumer-file render and its ownership guard - and never touches the
credential store. Adding
`--live` round-trips a synthetic value through the real Keychain or Credential
Manager under a per-run unique account name and deletes it. The split is
deliberate: a live check can raise a macOS Keychain access prompt, which must not
happen behind a command documented as touching no credentials.

**Run `--selfcheck --live` first on a new machine**, before assuming a failure is
the vendor's fault - it is the only one of the two that proves the platform path.

## Security posture, stated plainly

- The secret is written to the OS credential store through the platform API. On
  Windows that is `CredWriteW` with the value passed as a memory buffer rather
  than on a command line, so it does not land in process-creation logs.
- The complete value is never printed, never logged, and never returned into the
  agent's context. A receipt carries length, a hash prefix, and the last four
  characters. For a short secret (under twelve characters) the last four AND the
  hash prefix are both withheld: publishing an exact length beside an unsalted
  digest is a verification oracle, and a six-character secret falls to brute
  force in about a second, so withholding only the last four would not have been
  enough.
- Capture files hold a real credential until deleted - the whole DevTools
  request, meaning every cookie for that origin and every auth header, not just
  the one value. A `.gitignore` in this Skill directory covers `captures/`,
  `*.curl.txt`, and `state.json`. **Delete the capture once the seed verifies.**
- Consumer config files are written with mode 0600 on macOS and Linux and are
  regenerated on demand, so they can be treated as a cache rather than as a
  secret store. On Windows the mode is best-effort and the file inherits its
  parent directory's NTFS ACLs. `state.json` uses the same 0600 path.
- **Platform status: Windows is verified against Credential Manager. On macOS
  the credential-store round trip passes (`--selfcheck --live`), but no full seed
  against a real site has been exercised there.** Say so rather than implying
  both platforms are equally proven.
- This Skill adds no browser automation and no network listener. It reads a file
  the user pasted.

## What this does not do

It does not refresh a session automatically. For an httpOnly session cookie,
re-authentication still means a human logging in again -- a vendor may offer its
own renewal path, but this workflow does not drive one. It shortens and schedules
that human step; it does not remove it. Any tool claiming to fully automate an
httpOnly session cookie is either driving a browser or storing your password.

Files in this skill

  • .claude-plugin/plugin.json1.1 KB
  • .gitignore618 B
  • NOTICE3.4 KB
  • README.md5.9 KB
  • SKILL.md9.5 KB
  • pain-point.md2.4 KB
  • profiles/example-bearer-token.json2.6 KB
  • profiles/example-cookie-site.json2.3 KB
  • references/security-model.md6.5 KB
  • scripts/credgrab.py40.5 KB
  • scripts/credstore.py15.9 KB
  • scripts/ctplatform.py926 B
  • scripts/curlparse.py20.4 KB

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…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.