Auditing Code For Vulnerabilities logo

Auditing Code For Vulnerabilities

Community
trilwu
auditing-code-for-vulnerabilities

Audit source code for exploitable vulnerabilities using threat-model-driven review, taint tracing, invariant checking, and variant analysis. Use when reviewing a codebase or diff for security bugs, performing a security audit, hunting for vulnerabilities in a target's source, or validating whether a suspected finding is real.

Overview

Publishertrilwu
Repositorysecskills
Skill nameauditing-code-for-vulnerabilities
Stars
144
Forks
15
Bundled files
1
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 1 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by trilwu on GitHub. Read the source before you install it.

Installation

Install the Auditing Code For Vulnerabilities AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/trilwu/secskills.git /tmp/secskills
mkdir -p .claude/skills
cp -r /tmp/secskills/secskills-core/skills/auditing-code-for-vulnerabilities .claude/skills/auditing-code-for-vulnerabilities
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Auditing Code For Vulnerabilities in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Auditing Code For Vulnerabilities on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Auditing Code For Vulnerabilities is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Auditing Code for Vulnerabilities

Finding real bugs in source code is a different job from running a scanner. A scanner matches patterns; an auditor builds a model of what the code is supposed to guarantee and then hunts for the paths where that guarantee breaks. This skill is the methodology for the second job.

When to Use

  • Auditing a repository, service, or library for security defects
  • Reviewing a diff, branch, or pull request for introduced vulnerabilities
  • Hunting for a specific bug class across a large codebase
  • Validating whether a scanner finding or a reported vulnerability is real
  • Building an audit plan and coverage report for a client engagement

When NOT to Use

  • Black-box testing of a running app — use testing-web-applications or testing-apis
  • A PHP codebase specifically (type juggling, unserialize/phar POP chains, php:// wrappers) — this methodology plus auditing-php-applications
  • Hunting a planted webshell or backdoor rather than a vulnerability — use hunting-web-backdoors
  • Binary-only targets — use analyzing-binaries
  • Dependency and build-pipeline risk — use auditing-supply-chain
  • Cryptographic construction review — use reviewing-cryptography
  • Writing up finished findings — use reporting-security-findings
  • Running a multi-agent discovery campaign across a whole target with builder/critic separation and iteration — use orchestrating-vulnerability-research, which dispatches this skill as the per-slice hunter

The Loop

Auditing is four passes, not one. Do not skip to pass 3.

1. Context      → what does this system protect, and from whom?
2. Attack surface → where does untrusted input enter, and what does it reach?
3. Hunt          → trace specific bug classes along those paths
4. Verify        → prove exploitability before you write a word

Pass 1: Build context before reading code

Do not open files at random. Spend the first block of effort answering:

QuestionWhere to look
What are the security-relevant assets?README, docs, data models, DB schema
Who are the actors and trust tiers?Auth middleware, role enums, tenant models
What are the stated invariants?Tests, assertions, comments containing "must", "never", "invariant"
What has already been fixed here?git log --grep for security keywords, CVE files, SECURITY.md
What is out of scope?Engagement brief, vendor code, generated files
bash
# Prior security work is the cheapest source of bug leads
git log --oneline --grep='security\|CVE\|vuln\|injection\|auth bypass\|overflow' -i | head -40

# Stated invariants often mark where the author was nervous
rg -n --stats 'MUST NOT|must never|SECURITY|XXX|HACK|TODO.*(auth|secur|valid)' -i

# Where does privilege actually get checked?
rg -n 'is_admin|require_role|authorize|has_permission|@login_required|checkAccess'

Write a short target model before hunting: assets, actors, trust boundaries, and the three invariants whose violation would matter most. Everything after this is a search for counterexamples to those invariants.

Pass 2: Map the attack surface

Enumerate entry points, then rank them. An entry point matters in proportion to how far it reaches before it is validated.

bash
# HTTP/RPC routes
rg -n '@(app|router)\.(get|post|put|delete|patch)|app\.(get|post)\(|@RequestMapping|http\.HandleFunc'

# Deserialization, template rendering, and dynamic execution sinks
rg -n 'pickle\.loads|yaml\.load\(|Marshal|unserialize|ObjectInputStream|eval\(|new Function|exec\(|Runtime\.getRuntime'

# Command, SQL, and path sinks
rg -n 'os\.system|subprocess.*shell\s*=\s*True|child_process\.exec\(|execSync|Statement\.execute|\.raw\(|fmt\.Sprintf.*SELECT'

# Where authentication is decided rather than enforced
rg -n 'verify=False|InsecureSkipVerify|jwt\.decode\(.*verify.*False|algorithms=\[.*none'

Rank entry points by: reachable without authentication > reachable by a low privilege tier > reachable only by an admin. Then follow the highest-ranked ones inward. Depth beats breadth — one fully traced path is worth twenty grep hits.

Grep hits are candidates, not findings. The commands above are a cheap wide net; each match is an unresolved lead until you have traced it. Persist the candidate set — a worklist of (file:line, bug class, entry point) — and drive every entry to an explicit verdict: traced-safe, confirmed, or needs-PoC. Widen the net cheaply, then spend expensive reasoning per candidate — never the reverse. The failure mode is not a missing grep pattern; it is enumerating fifty candidates, eyeballing five, and calling the tree clean. On a large codebase, fold the project's own conventions into the net — its ORM's raw-query escape hatch, its auth decorator's name, its templating call — because the highest-yield sinks are the ones generic patterns miss.

Pass 3: Hunt bug classes along the traced paths

For each promising path, trace taint from source to sink and ask what the code assumes. The high-yield classes, in rough order of how often they survive to production:

Authorization, not authentication. Most real breaches are missing object level checks, not broken login. For every handler that takes an ID, ask: is the object scoped to the caller's tenant/user, or only looked up by ID? Check the query, not the decorator.

Trust-boundary confusion. Data validated at one layer and re-parsed at another. Look for values that cross a serialization boundary — a validated string re-parsed as a URL, a path, a template, or a query.

State and concurrency. Check-then-use gaps, non-atomic balance updates, idempotency keys that are not actually unique, retry paths that replay side effects. Search for reads followed by writes with no lock or transaction.

Injection into a secondary interpreter. SQL, shell, LDAP, XPath, template engines, log formats, and regex. The question is never "is there a filter" but "does the filter and the interpreter agree on the grammar."

Memory safety (C/C++/unsafe Rust/CGo). Length arithmetic before bounds checks, memcpy with an attacker-influenced size, off-by-one in loop bounds, signed/unsigned conversions, use-after-free on error paths.

Error and cleanup paths. The happy path is usually reviewed; the except, catch, defer, and goto fail branches are not. Audit them specifically.

Secrets and cryptographic misuse. Hardcoded keys, non-constant-time comparison of tokens, predictable IDs from Math.random/rand(), missing signature verification. Deep crypto review belongs in reviewing-cryptography.

Pass 4: Variant analysis

A bug is a template, not an incident. When you confirm one, immediately search for its siblings — the same mistake made by the same author, the same copied block, the same missing check on a neighbouring route.

bash
# You found one unscoped lookup. Find every other one.
rg -n 'find_by_id|findOne\(\{ *_id|get_object_or_404' -A3 | rg -v 'tenant|owner|user_id'

Variant analysis is where audits produce disproportionate value. Budget time for it explicitly — roughly one unit of variant search per confirmed finding.

Verification Before Reporting

A finding you cannot demonstrate is a hypothesis. Before it goes in the report, answer all four:

  1. Reachability — name the concrete entry point and the caller privilege required. "An attacker who can reach POST /api/export unauthenticated."
  2. Control — show which part of the dangerous value the attacker controls.
  3. Impact — state what breaks: which invariant from Pass 1, and what an attacker gains.
  4. No mitigating control — check for a WAF rule, a framework default, a middleware, a DB constraint, or a caller that already sanitizes.

If a proof of concept is in scope, write the smallest one that proves control of the sink — not a weaponized exploit.

Revalidate to prune false positives

The four checks above confirm a finding; this pass tries to kill it. Run it on every confirmed candidate before it reaches the report — a report's credibility is set by its worst false positive, not its best true finding.

  • Is it already fixed? The tree you are reading may lag the fix, or the fix may sit on a branch you have not pulled. Confirm the vulnerable code is what actually ships before you file it.

    bash
    git log -S'<dangerous token>' --oneline -- <file>   # when this line changed, and toward what
    git log --oneline <checkout>..origin/main -- <file> # a fix on main you are not reading
    git blame -L <line>,<line> <file>                    # the commit that introduced it, for context
  • Re-derive it adversarially. Argue the opposite case: assume the code is safe and go find the control that makes it so — the middleware, the DB constraint, the caller that already sanitizes. A finding that survives a genuine attempt to disprove it is one you can defend.

  • Confirm the sink still receives your value. Re-trace the last hop. A refactor often slips a validator or an encoder between source and sink that a first read glides past.

Drop what dies here, and say so in your coverage notes. A candidate you cannot revalidate is a note to yourself, not a finding.

Rationalizations to Reject

These are the thoughts that turn an audit into a formality. Each one is wrong.

  • "It's probably validated upstream." Then go read upstream. Unverified assumptions about a caller are the single most common source of missed bugs.
  • "The framework handles that." Frameworks handle the default path. Check the version, check the config, check whether this call uses the safe API.
  • "That input is internal." Internal today. Trace how it is populated; a queue consumer or admin import is usually reachable from outside.
  • "It's only exploitable by an authenticated user." That is a severity input, not a reason to drop the finding.
  • "It looks intentional." Intent is not a control. Note the intent, keep the finding.
  • "The scanner didn't flag it." Scanners find what they have rules for.
  • "I confirmed it, so it's real." You confirmed it against one checkout and your own first read. Revalidate it against what actually ships and against a genuine attempt to disprove it before it goes in the report.
  • "I've reviewed enough files." Coverage is measured against the attack surface you mapped in Pass 2, not against file count.

Tool Assist, Not Tool Substitute

Static analysis is for coverage and for variant search after you know the pattern. Write a rule once you have a confirmed bug, and let it find the rest.

bash
# Semgrep: broad pass, then a rule you write for your specific finding
semgrep --config=auto --severity=ERROR --json -o semgrep.json .
semgrep --config=./rules/my-variant-rule.yaml .

# CodeQL for dataflow questions grep cannot answer
codeql database create db --language=<lang> && codeql database analyze db --format=sarif-latest -o out.sarif

# Language-specific
bandit -r . -f json            # Python
gosec -fmt=json ./...          # Go
cargo audit && cargo geiger    # Rust deps + unsafe surface
npm audit --json               # JS deps

Triage every tool finding through the four verification questions above. A report of unverified scanner output is worse than no report — it burns the reader's trust and buries the real bugs.

Audit Deliverable

Track coverage as you go, and state it honestly:

markdown
## Coverage
| Component | Files | Depth      | Notes                          |
|-----------|-------|------------|--------------------------------|
| auth/     | 12    | Full trace | All routes traced to sinks     |
| billing/  | 30    | Partial    | Webhook handlers only          |
| vendor/   | -     | Excluded   | Out of scope per brief         |

## Findings
F1. [High] Tenant isolation bypass in GET /api/reports/:id — <impact><repro>

Say what you did not cover. An audit that claims full coverage it did not achieve is the most damaging artifact you can produce.

References

  • references/bug-class-checklist.md — per-language hunting checklists
  • reporting-security-findings — severity scoring and write-up format
  • OWASP Application Security Verification Standard (ASVS) for requirement-driven review
  • CWE Top 25 and the CWE hierarchy for classification

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Auditing Code For Vulnerabilities AI skill do?

Audit source code for exploitable vulnerabilities using threat-model-driven review, taint tracing, invariant checking, and variant analysis. Use when reviewing a codebase or diff for security bugs, performing a security audit, hunting for vulnerabilities in a target's source, or validating whether a suspected finding is real.

Why use Auditing Code For Vulnerabilities on TypingMind?

Because you install it once and use it with any model. Auditing Code For Vulnerabilities is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Auditing Code For Vulnerabilities in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/trilwu/secskills/tree/main/secskills-core/skills/auditing-code-for-vulnerabilities. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Auditing Code For Vulnerabilities?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Auditing Code For Vulnerabilities?

As many as you like. As long as a model supports skills, you can use Auditing Code For Vulnerabilities with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Auditing Code For Vulnerabilities AI skill free?

Yes. It is published on GitHub by trilwu under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇