agentleFS
forefyforefy/.context/skills/applicative-pentest/webapp-probe/SKILL.md

webapp-probe

Skill153 starsChanged 44 days agoMITView on GitHub

Probe a web app for what it exposes or leaks - passively from captured traffic and actively against the target. Use to assess a web app's exposure or review Burp/ZAP history.

  • Reads credentials

The file

We split this skill into the rules it gives an agent

7 rules. About 0 are common, 2 are distinctive, and 5 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Only run against a web application the user owns or is contractually engaged to test.

    line 26
  2. Very specific:

    Look only at cookies that look session-bearing - the cookie name (case-insensitive) contains sess, token, auth, jwt or sid.

    line 64
  3. Very specific:

    Run the secret-regex set in references/secret-regexes.md over every captured response body.

    line 76
  4. Very specific:

    Run the error-signature set in references/error-signatures.md over every captured response body.

    line 86
  5. Distinctive:

    If every signature matches (hit count == number of signatures), discard the whole domain - the server answers 200 to everything and none of …

    line 134
  6. Very specific:

    if two-or-more segments remain: when the second segment is one of src, es, esm, lib, dist, node_modules, the package is just the first …

    line 187
  7. Very specific:

    Keep a derived package name as a company-owned candidate when fuzz.ratio(package_name, company_root_label) > 50 (thefuzz / …

    line 189

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Contents

  • Scope & authorization (blast-radius labels)
  • Passive analysis of captured traffic:
    1. Missing or weak security headers
    2. Insecure session cookies
    3. Hardcoded secrets & API tokens in bodies
    4. Improper error handling (stack traces, DB errors, debug pages)
    5. Outdated / dev-mode technology fingerprints
    6. RCE-prone parameters in captured requests
  • Active probing of the live target: 7. Disclosure-path brute (.git/config/logs, CVE paths) 8. Outdated / vulnerable software port probe 9. Wayback forgotten-endpoint mining + re-probe 10. Dependency confusion (sourcemaps -> npm)
  • Runnable snippets
  • Output
  • Reference files: references/secret-regexes.md, references/error-signatures.md, references/directory-signatures.md

Scope & authorization

Only run against a web application the user owns or is contractually engaged to test. This skill has two halves, each labelled by blast radius:

  • Passive (classes 1-6) - inspects responses and requests you already captured (proxy history, an authenticated crawl, a saved sitemap, files on disk). Sends no new HTTP requests, mutates nothing, and is safe against a frozen capture.
  • Active (checks 7-10) - sends live requests to the target and, for Wayback (9) and dependency confirmation (10), to third-party services (the Internet Archive, the npm registry). Check 8 is aggressive (multi-port sweep). Run these only in scope, and prefer a low-traffic window.

Take inputs as whatever you already hold: captured responses/requests for the passive half, and the target's domains / domain:port pairs for the active half. Report a finding exactly where each section says "Report a finding when...".

Passive analysis of captured traffic

Each class is one pass over the capture; each yields per-target findings.

0. Extensive attack surface flushout and coverage

Work through the given scope of the target, and work to maximize all the attack surface expansion via all techniques that comes to mind.

Take a webapp for example - seeing a 404 is one thing, but subdomain enumeration expanding the targets, on each running available browser tools to get extended sitemap, available source code, backup files, flush errors and stack traces with unexpected inputs and more.

Coverage is most important as you have to invent and act on lots of variations per the target type tailored to any customization opportunity you may discover that can further the search (e.g. if its next.js version xyz do we know how to trigger errors on there).

1. Missing or weak security headers

For every captured response, case-insensitively collect the response header names and report each of the ten headers below that is absent. Report a finding when: a response is missing any of these. Remediation is "add the <Header> in responses returning from the server".

HeaderWhy it matters
X-Frame-OptionsBlocks embedding the site in iframes (clickjacking).
Content-Security-PolicyControls which resources (e.g. JS) the page may load.
Strict-Transport-SecurityForces HTTPS, including on the initial HTTP connection.
Permissions-PolicyDisables specific browser APIs; propagates to iframes.
X-Content-Type-OptionsStops MIME sniffing; browser trusts only the declared Content-Type.
Referrer-PolicyPrevents leaking sensitive query params via the Referer to third parties.
Cross-Origin-Resource-Policy(xs-leaks) Restricts cross-origin access to the document's resources.
Cross-Origin-Embedder-Policy(xs-leaks) Blocks loading cross-origin resources that don't grant permission via CORP/CORS.
Cross-Origin-Opener-Policy(xs-leaks) Stops popup/opener documents from reaching the page's global object.
Cache-ControlPrevents responses being cached in intermediary proxies and leaked to other users.

2. Insecure session cookies

Look only at cookies that look session-bearing - the cookie name (case-insensitive) contains sess, token, auth, jwt or sid. For each such Set-Cookie with a non-empty value, report a finding when any of:

  • No attributes at all - the cookie string has no ; or no =. The whole cookie is insecure.
  • Missing HttpOnly - Cookie '<name>' doesn't have the HTTPOnly attribute set. Fix: set HttpOnly on important cookies.
  • Missing Secure - Cookie '<name>' doesn't have the Secure attribute set. Fix: set Secure.
  • SameSite=None - Cookie '<name>' has the SameSite attribute set to 'none'. Fix: set SameSite=Strict, or at least Lax.
  • Long lifetime - an Expires (parsed as a unix timestamp here) more than 14 days out. Cookie '<name>' has a long expiration date set of more than N days. Fix: give important cookies a short-lived expiration.

Cookies whose name matches none of those, and empty-valued cookies, are skipped to keep the signal high.

3. Hardcoded secrets & API tokens in bodies

Run the secret-regex set in references/secret-regexes.md over every captured response body. Report an INSIGHT (not a hard finding - these are high-value leads that need confirmation) when: any pattern matches. Record <secret name> ( <matched value(s)> ) while requesting <paths>; de-duplicate matches per target and truncate the joined match string to 400 chars.

The set (~60 patterns) covers provider credentials and identifiers: OpenAI legacy/sk-proj-/sk-svcacct- and Anthropic sk-ant-, npm npm_, Discord bot tokens & webhooks, DB connection URIs with embedded creds (MongoDB, Redis, PostgreSQL, MySQL, MSSQL), Azure Blob / GCS / Firebase Storage bucket URLs, Slack tokens/webhooks, GitHub classic/fine-grained PATs and git+https URIs, AWS access-key IDs / MWS tokens / S3 bucket URLs, Google API keys / OAuth / GCP service-account JSON / ya29. access tokens, Stripe/Square/PayPal Braintree/Picatic/Mailgun/MailChimp payment & mail keys, DigitalOcean, HuggingFace, Grafana Cloud, Segment, Okta, Fullstory, Adobe, Heroku, Telegram, Firebase URLs, and a generic "Password": "..." JSON pattern. Full patterns in the reference file.

The reference file's False-positive gates section is not optional - it is what decides whether a match is worth reporting: a credential-keyword gate on the generic connection string, a placeholder/localhost filter on the connection URIs (without it those five rows are net-negative), a snowflake decode for Discord tokens, a repetition floor on the remaining unanchored rows, and the rule that rows tagged (identifier) are public by design and get an insight with a next step attached, never a credential finding.

Secrets in third-party JS may be intentional publics (e.g. a Google Maps browser key) - verify before reporting as a leak; treat the finding as a lead.

4. Improper error handling - stack traces, DB errors, debug pages

Run the error-signature set in references/error-signatures.md over every captured response body. First skip responses that are JavaScript bundles (they produce false positives): skip the body if it matches sourceMappingURL|window\.addEventListener|window\.document|webpackJsonp|jQuery. Report a finding when: any signature matches; record <signature name> ( <match> ) while requesting <paths>.

The set (~130 signatures) spans: SQL/DB errors (MySQL, MSSQL OLE DB, PostgreSQL, Oracle ORA-, DB2, SQLite, MongoDB E11000, Elasticsearch mapper_parsing_exception); language runtime exceptions (Java java.lang.*/java.io.*/java.sql.*, Python Traceback/ValueError/KeyError/etc., Ruby, C++ std::*, .NET System.*); framework error pages (Django, Flask/Werkzeug, Laravel/Symfony, Spring/Spring Boot/Hibernate, Rails ActionView::Template::Error, Express.js, ASP.NET "Server Error in '/' Application"); insecure-deserialization gadget-chain traces (Java ObjectInputStream.readObject, InvokerTransformer/LazyMap/ChainedTransformer, readObject/writeObject, Python pickle/yaml.load, Ruby Marshal.load/YAML.load, PHP unserialize(, C# BinaryFormatter, Go encoding/gob, Jackson); config/secret disclosure (<compilation debug="true", DATABASES = {...}, secret_key_base, Web.config, Node config errors); and CSRF/JWT errors. Full name+pattern table in the reference file.

5. Outdated / dev-mode technology fingerprints

Because this is a passive body-string search (not endpoint probing), the patterns are deliberately precise. Run over every captured response body; report an INSIGHT when any matches (<name> ( <match> ) while requesting <paths>). This is the passive counterpart to the active port probe in check 8 - a passive hit tells you where to point check 8.

FingerprintBody regexMeaning
Tomcat Dev Interfacetomcat\.gifDefault Tomcat page/manager exposed.
Jenkins Dev InterfaceWelcome to Jenkins!Jenkins UI reachable.
Werkzeug Dev InterfaceWerkzeug powered traceback interpreterFlask/Werkzeug interactive debugger (RCE-prone).
AD Self Service Management ServeradscsrfADSelfService Plus portal.
Frontend Code Editor`ace_editorcodemirrormonaco-editor`In-page code editor surface.
Pulse Secure File Readdana-na\/cssPulse Secure (CVE-2019-11510 arbitrary file read).

Reference: nuclei-templates http/cves/2019/CVE-2019-11510.yaml.

6. RCE-prone parameters in captured requests

Over captured requests, inspect query-string params and body params (parsed by Content-Type: XML tags, JSON keys, or x-www-form-urlencoded keys). Report an INSIGHT when: a parameter key matches the RCE-suggestive wordlist below, or a parameter value equals ##class (a common template/gadget marker). Record which location matched, e.g. Query parameter key 'cmd' was found at path '<path>' or JSON body parameter key 'exec' was found at path '<path>'. These names don't prove a vuln - they flag parameters worth targeted, authorized command-injection testing.

Parameter keys (case-sensitive match, as captured):

daemon, execute, cmd, cli, ip, xp_cmdshell, CSPCHD, exec, func, function,
command, eval, shell, shell_exec, popen, proc_open, bash, python, system,
payload, cmdline, exe, execcommand, exec_code, exec_cmd, executeshell,
cmd_exec, cmd_inject, cmd_shell, cmd_script, run, runcmd, runcommand,
shellcode, shellexec, shellcmd, command_prompt, process, terminal,
execute_command, exec_file, load_module, load_script, proc_cmdline,
runtime_exec, shell_execute, system_command, sys_command

Parameter values: ##class.

Requests with a body but no Content-Type, or an unrecognized Content-Type, are skipped.

Active probing of the live target

These send live requests. Confirm scope first; they leave logs on the target (and, for 9-10, on third parties).

7. Disclosure-path brute - active

For each domain, GET a curated set of source/config/log/known-CVE paths (no redirects, TLS verification off, 10s). Each signature carries a path, an expected status regex and a body regex; a match must satisfy both. The full 30-signature table lives in references/directory-signatures.md (e.g. /.git/config, /.git/config~, /.git, /.svn, /package.json, /jsconfig.json, /config.json, /info.php, /phpinfo.php, /web.config, /global.asa, /storage/logs/laravel.log, /wp-content/debug.log, Eclipse Jetty /WEB-INF/web.xml and its /%2e/-prefixed traversal variant, Telerik /Telerik.Web.UI.WebResource.axd?type=rau, Pulse /dana-na/, /adminer.php, /phinx.yml, the .env family, /.npmrc, ten Swagger/OpenAPI doc paths, and Django-debug /djgo expecting a 4xx page containing DEBUG =).

False-positive controls (essential - catch-all responders are common):

  • Drop any response whose body contains 404 Not Found or This page can't be displayed.
  • Hash (MD5) each matching response body; collapse duplicates so one generic page counted many times becomes one hit.
  • If every signature matches (hit count == number of signatures), discard the whole domain - the server answers 200 to everything and none of it is real.

Report a finding when: at least one - but not all - signatures match after dedup. Severity: Information Disclosure (rate individually; exposed .git/.svn or a live source/config/log file is often high impact).

8. Outdated / vulnerable software port probe - aggressive

For each domain, probe management interfaces of RCE-prone stacks across their typical ports, matching a substring in the response body. Cache each port's response and reuse it so overlapping port lists don't re-request. On 80/443 use plain http://host / https://host; on any other port try both http and https (label the hit port (HTTP) / port (HTTPS)).

Service (RCE surface)PathBody substringPorts
Apache Tomcat/Tomcat80, 443, 8080, 8081, 8089, 8090, 9090, 9091
Jenkins/loginJenkins80, 443, 8080, 8081, 8089, 8090, 9090, 9091, 7443, 8443, 9443
Werkzeug debugger/consoleWerkzeug powered traceback interpreter80, 443, 8080, 4000
ManageEngine ADSelfService/showLogin.ccadscsrf8080, 8889
InterSystems Caché/CSPCHD443
ASP.NET ViewState/__VIEWSTATE443
Jolokia / Java RMI/jolokiajolokia443
Plone CMS/Plone443

Report a finding when: any service substring appears. Severity: potential RCE insight - report "<service> found on port(s) <list>". The Werkzeug /console interactive debugger and an exposed Jolokia agent are directly exploitable; the rest are version-review leads.

9. Wayback forgotten-endpoint mining + re-probe - active-3rdparty (harvest), then active (re-probe)

Harvest (active-3rdparty). Query the Internet Archive CDX index per domain:

https://web.archive.org/cdx/search/cdx?url={domain}*&collapse=urlkey&limit=40000&fl=urlkey,timestamp,original,mimetype,statuscode,length&output=json

The archive rate-limits ~15 req/min and imposes a ~5-minute block; use a retry/backoff of 5m -> 10m -> 20m on HTTP 429. Drop static/noise by mimetype (application/javascript, text/javascript, application/x-javascript, text/css, image/png, image/gif, font/woff) and by extension in the URL (.png .js .css .jpg .JPG .jpeg .gif .ttf .tif .eot .woff .woff2 .pdf .otf .svg .ico .html .swf .styl).

Filter to the interesting URLs (this de-noising is the point):

  • Skip URLs longer than 1000 chars.
  • Skip "cache-buster / hash-looking" URLs: those matching ^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?!.*\?)(?!.*\=)(?!.*\&)(?!.*\_).*$ (mixed-case+digits, no query, no underscore).
  • Skip boring path substrings: how-it-works, promotions, images, google-tag-manager-cart, terms-of, -products, frequently-asked-questions, wewaw, news, wp-json, wp-admin, diy.
  • Require a query string (?...); keep only distinct (path, frozenset(query-param-names)) tuples.
  • Compute the 20 most common path segments / query-param names across the survivors; keep an element only if it recurs >5 times and its length is >3 and <11; then drop any URL that contains one of those common elements - i.e. keep the unusual endpoints, discard the site-wide boilerplate.

Report the surviving URL set as an Information Disclosure insight (archived, possibly-still-live parameterized endpoints worth manual testing).

Targeted re-probe (active). For any surviving URL whose path matches a fingerprint below, send a live GET (5s) to the target and match status + body:

FingerprintPath regexStatusBody regexMeaning
Telerik Web UITelerik2.*.*Telerik UI present (CVE-2019-18935 lineage)
Java Server Pages / JSFjavax\.faces\.resource|javax\.faces\.ViewState2.*.*JSF ViewState deserialization surface
Pulse Secure File Readdana-na2.*dana-na\/cssPulse Connect Secure (CVE-2019-11510 arbitrary file read)

Report a finding when: a re-probed URL still returns 2xx and matches its body regex. Severity: potential RCE (HIGH) - flag URL (fingerprint description) for manual confirmation.

10. Dependency confusion: sourcemap -> company package -> npm - active (harvest), active-3rdparty (registry check)

Harvest private package names (active). For each domain:port on 443, GET the homepage, parse every <script src="...js">, and request the co-located sourcemap src + ".map" (resolved absolute). Only fetch maps whose URL is same-origin (domain in map_url). From each map's sources[], keep entries containing ../node_modules; take the path after ../node_modules/, split on /, and:

  • skip if the first segment is src;
  • drop any .js segment;
  • if two-or-more segments remain: when the second segment is one of src, es, esm, lib, dist, node_modules, the package is just the first segment; otherwise treat it as a scoped package @scope/name -> {seg0}/{seg1}.

Keep a derived package name as a company-owned candidate when fuzz.ratio(package_name, company_root_label) > 50 (thefuzz / Levenshtein-style ratio) - i.e. the dependency's name resembles the company's own name, the tell-tale of an internal package leaked into a public bundle.

Confirm dependency confusion (active-3rdparty). For each candidate, query the public npm registry (https://registry.npmjs.org/<name>, URL-encode a @scope/name). If it returns 404 / not found, the private name is unclaimed on the public registry and is dependency-confusion-claimable; if it resolves to a package not owned by the target org, it may already be squatted.

Report a finding when: a company-resembling node_modules package name derived from a target's own bundle is unregistered (or third-party-owned) on the public registry. Severity: dependency confusion (a malicious publish of that name can execute in the target's build/runtime). Also flag the exposed sourcemaps themselves as an information-disclosure insight.

Runnable snippets

Passive sweep (no requests sent)

These operate on a directory of already-captured responses/requests. Assume CAPDIR holds saved response bodies (e.g. *.body) and sibling *.headers files. Adapt the loader to your proxy's export format.

# 1 missing security headers - scan saved *.headers files (name: value per line)
python3 - "$CAPDIR" <<'PY'
import sys,glob,os
req=["x-frame-options","content-security-policy","strict-transport-security","permissions-policy","x-content-type-options","referrer-policy","cross-origin-resource-policy","cross-origin-embedder-policy","cross-origin-opener-policy","cache-control"]
for f in glob.glob(os.path.join(sys.argv[1],"*.headers")):
    have={l.split(":",1)[0].strip().casefold() for l in open(f,errors="ignore") if ":" in l}
    miss=[h for h in req if h not in have]
    if miss: print(os.path.basename(f),"MISSING:",", ".join(miss))
PY
# 2 insecure session cookies - parse Set-Cookie lines from saved *.headers
python3 - "$CAPDIR" <<'PY'
import sys,glob,os,time
for f in glob.glob(os.path.join(sys.argv[1],"*.headers")):
    for line in open(f,errors="ignore"):
        if not line.lower().startswith("set-cookie:"): continue
        c=line.split(":",1)[1].strip()
        if ";" not in c or "=" not in c: print(os.path.basename(f),"no-attributes:",c); continue
        parts=c.split(";"); nv=parts[0]; name=nv.split("=")[0]
        if not nv.split("=",1)[1]: continue
        if not any(p in name.casefold() for p in ("sess","token","auth","jwt","sid")): continue
        attrs=[a.strip().casefold() for a in parts[1:] if a.strip()]
        if "httponly" not in attrs: print(os.path.basename(f),name,"missing HttpOnly")
        if "secure" not in attrs:   print(os.path.basename(f),name,"missing Secure")
        if "samesite=none" in attrs:print(os.path.basename(f),name,"SameSite=None")
        for a in attrs:
            if a.startswith("expires="):
                try:
                    d=(int(a.split("=",1)[1])-time.time())/86400
                    if d>14: print(os.path.basename(f),name,"long expiry %d days"%d)
                except ValueError: pass
PY
# 3 secrets  &  4 error signatures  &  5 tech fingerprints - one regex sweep over bodies
# put the patterns from references/secret-regexes.md + references/error-signatures.md into rules.txt
# as "name<TAB>pattern" lines (prefix error-signature names with ERR:), then:
python3 - "$CAPDIR" rules.txt <<'PY'
import sys,glob,os,re
rules=[l.rstrip("\n").split("\t",1) for l in open(sys.argv[2]) if "\t" in l]
rules=[(n,re.compile(p)) for n,p in rules]
jsskip=re.compile(r"sourceMappingURL|window\.addEventListener|window\.document|webpackJsonp|jQuery")
for f in glob.glob(os.path.join(sys.argv[1],"*.body")):
    body=open(f,errors="ignore").read()
    isjs=bool(jsskip.search(body))
    for n,rx in rules:
        if isjs and n.startswith("ERR:"): continue
        m=rx.findall(body)
        if m:
            j=", ".join(sorted({x if isinstance(x,str) else "".join(x) for x in m}))
            print(os.path.basename(f),n,"(",(j[:400]+"..") if len(j)>400 else j,")")
PY
# 6 RCE-prone parameters - scan captured requests (one URL per line in reqs.txt)
python3 - reqs.txt <<'PY'
import sys,urllib.parse as u
keys={"daemon","execute","cmd","cli","ip","xp_cmdshell","CSPCHD","exec","func","function","command","eval","shell","shell_exec","popen","proc_open","bash","python","system","payload","cmdline","exe","execcommand","exec_code","exec_cmd","executeshell","cmd_exec","cmd_inject","cmd_shell","cmd_script","run","runcmd","runcommand","shellcode","shellexec","shellcmd","command_prompt","process","terminal","execute_command","exec_file","load_module","load_script","proc_cmdline","runtime_exec","shell_execute","system_command","sys_command"}
for line in open(sys.argv[1]):
    q=u.urlsplit(line.strip()).query
    for k,vs in u.parse_qs(q).items():
        if k in keys: print("param key",k,"in",line.strip())
        for v in vs:
            if v=="##class": print("param value ##class in",line.strip())
PY

Active probes (live requests to the target)

# 7 disclosure-path brute (no redirects; flag 2xx that isn't a soft-404)
for p in /.git/HEAD /.git/config /.svn /.env /.env.local /.env.production /.npmrc /package.json /config.json /info.php /phpinfo.php /web.config /storage/logs/laravel.log /wp-content/debug.log /adminer.php /phinx.yml /swagger.json /v3/api-docs /openapi.json; do
  code=$(curl -sk -o /tmp/b -w '%{http_code}' --max-time 10 "https://TARGET$p")
  grep -qE '404 Not Found|This page can.t be displayed' /tmp/b || { [ "${code:0:1}" = 2 ] && echo "$code  $p  md5=$(md5 -q /tmp/b 2>/dev/null || md5sum /tmp/b|cut -d' ' -f1)"; }
done   # if EVERY path returns 2xx, the host is a catch-all -> discard all

# 8 outdated / vulnerable software port probe (body-substring per service)
for pp in "80 / Tomcat" "8080 /login Jenkins" "8080 /console Werkzeug" "443 /jolokia jolokia" "443 / __VIEWSTATE" "443 / Plone"; do
  set -- $pp; port=$1; path=$2; sig=$3
  for sch in http https; do curl -sk --max-time 5 "$sch://TARGET:$port$path" | grep -q "$sig" && echo "$sig on $port ($sch)"; done
done

# 9 Wayback harvest (respect 15/min; back off on 429)
curl -s "https://web.archive.org/cdx/search/cdx?url=example.com*&collapse=urlkey&limit=40000&fl=urlkey,timestamp,original,mimetype,statuscode,length&output=json" \
 | python3 -c 'import sys,json;[print(r[2]) for r in json.load(sys.stdin)[1:] if r[3] not in ("application/javascript","text/javascript","application/x-javascript","text/css","image/png","image/gif","font/woff") and "?" in r[2]]'

# 10 sourcemap -> node_modules -> npm ownership
curl -s https://TARGET/ | grep -oE 'src="[^"]+\.js"' | sed 's/src="//;s/"//' | while read s; do
  curl -s "https://TARGET/${s}.map" | python3 -c 'import sys,json;
d=json.load(sys.stdin);
[print(x.split("../node_modules/")[1]) for x in d.get("sources",[]) if "../node_modules" in x]' 2>/dev/null; done | sort -u
curl -s -o /dev/null -w '%{http_code}\n' "https://registry.npmjs.org/CANDIDATE_PACKAGE"   # 404 => dependency-confusion-claimable

Output

Finish with a two-part ledger, then a verdict:

  • Passive - per class (1-6): targets scanned and findings, distinguishing confirmed findings (classes 1, 2, 4) from insights/leads (classes 3, 5, 6) that need authorized follow-up.
  • Active - per check (7-10): check / blast-radius / done? / result, with the confirming request for each hit (exposed path after dedup/catch-all filtering, fingerprinted software+port, still-live archived endpoint, claimable private package).

Report each class/check's true status - scanned, run, not-run, or rate-limited - so coverage is honest. A clean passive result only means the leak wasn't present in the captured traffic; never present an un-run or rate-limited active check as clean.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.