discover-attack-surface
Skill172 starsChanged 2 months agoApache-2.0View on GitHub
Classify project-used dependency members and record taint sources as rule-authoring units. Use for the source-discovery depth pass
In this repository15 other files it gives its agents.
- analyze-external-methodsSkill
- analyze-findingsSkill
- appsec-agentSkill
- assemble-lib-rulesSkill
- build-projectSkill
- create-dataflow-modelSkill
- create-pass-through-modelSkill
- create-ruleSkill
- create-test-projectSkill
- debug-ruleSkill
- generate-pocSkill
- orchestrate-stageSkill
- report-analyzer-issueSkill
- run-scanSkill
- triage-dependenciesSkill
The file
We split this skill into the rules it gives an agent
1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 24
Read references/<language>.md before starting.
≈ “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.
Files
Skill: Discover Attack Surface
Work one assignment of project-used dependency members and pick out the taint sources among them — the methods where untrusted data first enters. The assigned language reference defines the concrete inspection commands and identifier formats for the workflow below.
Inputs
Provided by the caller, fall back to the default value when omitted. Ask back only when a required input is missing and has no sensible default
project-root(optional) — root of the target project. Opentaint keeps all analysis artifacts under the fixed<project-root>/.opentaint/directory, so every.opentaint/...path below resolves there. Default: current directorylanguage(required) — target language for this project and language-specific instructionsplan(required) — path to this agent's partition plan.opentaint/tracking/rules/plans/<id>.yaml: the project-used dependency members to classify
Workflow
Read references/<language>.md before starting. Its numbered steps provide the language-specific details for the workflow below.
1. Inspect the plan's members
The assigned plan's scopes contains the already-extracted project-used dependency members that still need a verdict. Inspect only those members. Confirm their dependency identity and exact signatures, then read application source, dependency source and API documentation, representative usages, and relevant framework configuration to understand how data enters the project.
2. Classify the plan's members
A source is the exact boundary where untrusted data first enters from a network, persistence, serialization, messaging, execution, or another external channel. For a callable member, decide whether it returns or otherwise exposes attacker-controlled data. A member that merely passes along data it was handed is a propagator, not a source.
Classify behavior rather than package or class names. For an individual member, prefer recording a borderline source with the uncertainty noted: later scan and triage can reject a false positive, while an omitted source becomes an unrecoverable false negative.
3. Record verdicts and source units
Complete the plan's source list in the form required by the language reference. Record every discovered source in its plan and write its source unit with tag: untrusted-data-source; resolving that unit to an existing or new rule happens later in create-rule. Non-sources create no unit. Mark an empty result explicitly so the reconcile join can distinguish it from a plan whose agent never returned. Where an owned unit already exists, merge new entries without rewriting its existing entries or stages.
4. Verify before returning
Re-check the full assigned scope against the classification. Re-read every rejected member and make sure it does not establish an external-input boundary. Confirm every source appears both in the completed plan and its source unit, no rejected member has a unit, and no pending/null verdict remains.
Output
Short and concise report of what was done
Artifacts:
.opentaint/tracking/rules/sources/<unit>.yaml— each source unit required by the completed plan- the assigned plan with the discovered sources recorded under
source
Summary:
- the source members found, one line each
- anything blocked or left uncertain
Tracking
.opentaint/tracking/rules/sources/<package-kebab>.yaml — one source unit per package (a dependency can span several packages), the file named for that package with . → -. tag is always the reusable untrusted-data-source group. dependencies names the dependency the package comes from, sources each an entry point { method, signature, note, rule_id } (method and signature use the exact language-specific identifiers from the plan), stages tracks the unit through rule authoring, and a blocker string is added under it when the unit can't be made to pass. Keep it clear from comments
dependencies:
- <dependency-id>
tag: untrusted-data-source
sources:
- { method: "<qualified-member>", signature: "<language-signature>", note: untrusted message payload, rule_id: null }
stages:
test_project: pending
tests_passing: pendingThis skill sets tag: untrusted-data-source, fills dependencies, and adds one { method, signature, note, rule_id } entry per source. Copy method + signature from the plan, explain why the data is untrusted in note, and leave rule_id: null and the stages for rule authoring.
The plan .opentaint/tracking/rules/plans/<id>.yaml — read your members from its scopes map, record the sources you find under a top-level source list; the join then ledgers source + safe (members − source), keyed by the exact method and signature so distinct callable variants stay separate. It is regenerable and disposable, not durable state:
id: lib-001
scopes:
<package-kebab>:
- { method: "<qualified-member-a>", signature: "<language-signature-a>" }
- { method: "<qualified-member-b>", signature: "<language-signature-b>" }
source:
- { method: "<qualified-member-a>", signature: "<language-signature-a>" }source: null is the generated plan's unprocessed sentinel. On completion, replace it with the exact sources found, or source: [] when there are none; mark-safe leaves a null plan for re-dispatch instead of incorrectly classifying all its members as safe. Every member listed as a source must also appear in its source unit.
Constraints
OpenTaint is a whole-program, interprocedural, field-sensitive alias analysis engine. It already propagates through visible application code, calls, aliases, and individual fields; custom rules and models cover only the assigned source, sink, or opaque-method boundary. Compile-time constants and literals carry no taint, so a source or carrier whose output is only a constant introduces nothing.
- This stage finds only sources — the boundaries where untrusted data enters, sinks are found later from the taint frontier
- Work only your own plan and the source units it maps to — never another agent's plan or unit, shared coverage/classification state, or
tags.yaml. Plans partition their write ownership according to the language reference - Stored / second-order injection (data persisted then read back) is modeled by the engine itself — don't record a source for the read-back or a propagator for the store→read path
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
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.

