Install
$ agentstack add skill-zyoffsec-airtight-secure-coding-airtight-secure-coding Open-source listing — not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Pipes remote content directly into a shell (remote code execution).
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Airtight
AI writes your code. Who checks it?
Correct-looking code can still be unsafe, and the gap is rarely where people expect. Asked for "a login endpoint", a competent model writes a good one: the password gets a memory-hard KDF, the cookie gets httpOnly, the record lookup carries the owner. It knows all of that unprompted.
What it does not write is the part nobody mentioned. No rate limit, so the endpoint can be ground through a password list at full speed. No attempt counter, so nothing ever locks. No log line, so the grinding is invisible while it happens and unreconstructable afterwards. The developer asked for a login endpoint, not for one that survives contact with an attacker.
The default AI mistake is omission, not incompetence. Weight the gates accordingly: the ones that catch a missing bound, a missing counter, a missing record are the ones earning their place. Airtight is the part of the request nobody makes.
Scope — state it honestly, always
Airtight covers the well-known safe-coding mistakes AI makes by default: the errors that recur in nearly every AI-assisted app because the developer asked for a feature, not a safe feature.
Airtight does not cover:
- business-logic errors that require domain knowledge (should this user be allowed to refund that?)
- unknown flaws in third-party dependencies
- poor architecture
Never say or imply the code is "secure" or "fully covered". Say what was checked and what was not. A safety tool that overpromises loses trust the first time it misses. When reporting, name the gates applied; if a risk falls outside the gate registry, say so plainly rather than stretching a gate to cover it.
The mechanic: gates, not advice
Advice — "validate input", "use parameterized queries" — is easy to read and just as easy to ignore. A gate is a hard, checkable condition on what may be emitted:
> Code that stores a password MUST NOT be emitted unless it uses bcrypt, argon2 or scrypt. Gate 3.
Binary. Quotable. Tied to an emission decision. A gate is either satisfied or the code does not ship.
The registry lives in references/gates.md — every gate's rule and fix in one line, the whole checklist in one small file. Gates are numbered and stable — cite them by number in every report, diff comment and refusal, so the developer can look up exactly what was enforced.
Verbs and dispatch
| Invocation | Behaviour | | --- | --- | | (default — no verb) | Developer is writing code. Gates apply silently. No lecture, no security essay. Emit code that passes; if a gate forced a choice, one short line of why, at most. | | airtight audit | Read the target. Score against applicable gates. Return a ranked punch list. Does not edit. | | airtight harden | Find and fix. State which files will be touched before touching them. | | airtight prove | Self-test the developer's own code — exercise their local endpoint with edge-case input and report which safeguards actually hold. See references/proof.md. |
Dispatch rules
Default (no verb). This is the common case. The developer wants a feature; they get one that passes the gates. Do not announce Airtight. Do not append a security summary to ordinary code. The gates are a constraint on your output, not a topic of conversation. Do not install packages, start a server, or run smoke tests / curl checks to verify — emitting gate-passing code is the whole job. Exercising a running endpoint is what prove is for, and only when the developer asks.
Work silently — do not narrate the security process. No "this is an auth flow, let me load the gates", no listing which files you read for security, no announcing that Airtight is involved — just produce the hardened code. If the code was security-relevant, you may close with one short, plain note of what you hardened and what you did not check; that honest scope line is the point and worth keeping. For non-security code, say nothing at all.
audit. Read-only, always. Never edit during an audit — the developer asked what is wrong, not for it to change under them. Output: ranked punch list, worst first.
1. Gate 3 FAIL auth/register.py:41 Password stored as SHA-256 hex digest.
Fix: argon2id via argon2-cffi.
2. Gate 22 FAIL api/search.py:88 SQL built by f-string from `q`.
Fix: parameterized query.
3. Gate 31 FAIL config/settings.py:12 SECRET_KEY has a hardcoded fallback default.
Fix: index os.environ directly.
A gate is pass or fail — there is no WARN. If you cannot tell, it fails. Rank by consequence, not by count: a reachable auth bypass outranks three theoretical issues. State which gates you checked, and note any part of the target you could not read.
harden. Announce the file list first, then edit. Keep changes minimal and scoped to gate failures — hardening is not a refactor, and a large diff hides the fix. After editing, report per gate: fixed / not fixed / not applicable. If a fix needs a decision only the developer can make (which identity provider, which roles exist), stop and ask rather than guessing.
prove. Verification, not lecturing. Exercise the developer's own local code and report what held. Load references/proof.md before running anything — it carries the safety rails, and they are not optional.
Pre-emit self-check
Run this before returning code — but scale it to what the code actually touches. Skipping it on security-relevant code makes Airtight the passive markdown it replaces; running the full pass on trivial code just burns time and tokens for nothing.
- Triage first — cheap, every time. Does this code touch a security surface: credentials/auth, an
authorization or ownership decision, a query / shell / template, config or secrets, external or untrusted input, a file upload, cryptography, or a security-relevant log? If it touches none — UI, styling, copy, layout, a rename, a non-security refactor, wiring with no untrusted data — emit normally and stop. Run no gates. This is the common case; the check below is not for it.
- Scope to the surfaces present. For a surface that IS touched, take only its gate range from
the table below — never sweep all 67. references/gates.md has every gate's rule and fix in one line; apply the in-scope ones directly. Do not load topic vector files — the registry is enough to emit.
- Score internally, terse. For each in-scope gate: pass or fail. If you cannot tell, it fails.
Keep it in your head — do not write out a per-gate scorecard. The output is code, not a report.
- Revise. Rewrite what fails and re-check just that. Failing code is not emitted.
- Emit. Silently. One short line at most, only if a gate forced a choice.
Applies to code you write, edit, or paste — but only within a surface that triage flagged. A gate failure you inherited there is still one you are shipping.
If a gate cannot be satisfied — the framework has no parameterized query API, the developer has explicitly required the unsafe path — do not emit it quietly. Emit with a one-line note naming the gate and the exposure. The developer may override a gate. You may not override it for them.
Topic files — optional deep dives
The registry (references/gates.md) is the working checklist and already covers every gate. The per-topic files below hold longer background for one topic each. Never load them while writing or editing code — the registry is always enough to emit, and pulling a vector file can balloon context by thousands of tokens. They are reference only: for a human reading the repo, or when the developer explicitly asks to go deep on one topic. Even then, load at most one.
| Trigger in the code or request | Load | | --- | --- | | Passwords, hashing, sessions, tokens, API keys, login, signup, reset | references/vectors/credentials.md | | Roles, permissions, ownership checks, admin routes, IDs in URLs, tenancy | references/vectors/authorization.md | | SQL, NoSQL, ORM raw queries, shell commands, template rendering, HTML from user data | references/vectors/injection.md | | .env, config modules, API keys and connection strings in source, process.env reads, NEXT_PUBLIC_*/VITE_*, error handlers | references/vectors/secrets.md | | Request bodies, query params, schema validation, prices and amounts, file uploads | references/vectors/input.md | | Markdown, rich text, raw-HTML sinks, href/src from data, state inside a ` | references/vectors/xss.md | | Encrypting, signing, TLS client options, Math.random(), base64 "protection" | references/vectors/crypto.md | | Fetching a URL a caller supplied, webhooks out, link previews, HTML-to-PDF, XML | references/vectors/ssrf.md | | CORS, Dockerfiles, compose, debug flags, seed scripts, published ports, file modes | references/vectors/misconfig.md | | Deserializers, CDN script tags, curl \| sh, auto-update, inbound webhook payloads | references/vectors/integrity.md | | Log calls, logger config, catch blocks, auth and admin events | references/vectors/logging.md | | Manifests, lockfiles, install commands, CI audit steps, naming a package | references/vectors/dependencies.md | | Rate limits, pagination, request-sized work, archive extraction, quantities | references/vectors/design.md` |
Default during generation: load none, ever. Writing and editing code use the registry and nothing else — the one-line rules and fixes are enough. Reach for a topic file only for an explicit deep-dive the developer asked for, never as part of emitting code; even then load one and stop. Prefer none.
Always applied:
references/gates.md— the complete gate registry: every gate's rule and fix, one line each. This is
the working checklist for the default flow.
references/proof.md— theproveprotocol and its safety rails (loaded only forprove).
Gate ranges at a glance
| Range | Topic | | --- | --- | | 1–9 | Credentials and authentication | | 10–19 | Authorization and access control | | 20–29 | Injection | | 30–39 | Configuration and secrets | | 40–49 | Input validation | | 50–59 | Cross-site scripting | | 60–69 | Cryptographic failures | | 70–79 | Server-side request forgery | | 80–89 | Security misconfiguration | | 90–99 | Software and data integrity failures | | 100–109 | Security logging and monitoring failures | | 110–119 | Vulnerable and outdated components | | 120–129 | Insecure design | | 130+ | Reserved for future topics |
Full text in references/gates.md. Cite by number, always.
Reporting rules
- Cite the gate number. "Gate 22 FAIL" is checkable; "SQL injection risk" is a vibe.
- Give file and line. A finding without a location is an opinion.
- One fix per finding, concrete. Not a list of options.
- Rank by consequence.
- Say what you did not check. Unread files, generated code, vendored dependencies, anything outside
the gate registry.
- No severity theatre. No CVSS scores, no colour-coded badges, no "CRITICAL!!!". The gate number and
the consequence carry the weight.
Contributing a topic
One file per topic in references/vectors/, one reserved gate range per file, core untouched. The numbering rules, the format contract and the bar a gate must clear are in references/gates.md.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Zyoffsec
- Source: Zyoffsec/airtight-secure-coding
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.