A security auditor where the tool owns no model — the calling agent is the LLM.
Single ~88 KB binary. Deterministic regex rules. Agent-managed verdicts. CI-native.
secure already has a model; it reads the findings, reasons, and
writes back a verdict that persists across scans.
Read the vision →
Every finding carries a stable id (sha256(rule|file|line)). The tool never calls an LLM to triage its own false positives — the calling agent does it with the model it already has, and persists the call.
#!/ the whole loop, no API key, no network call to a model provider ./secure --target . # JSONL findings on stdout ./secure --target . | jq 'select(.severity=="critical")' # agent reasons: this one is a Vue prop binding, not a secret ./secure verdict --target . <id> drop --reason "Vue prop binding, not a secret" # future scans suppress it automatically; --show-all brings it back
Same BYOK split as grepapi's /v1/brief: the tool returns structured data, the operator's own LLM completes the reasoning.
Two independent levers, aimed at two different situations — scope for CI, parallelism for full audits.
| scan mode | 10.4k-file repo | findings |
|---|---|---|
| --diff (8 changed files) | 0.23s | same 1950 |
| full scan, 1 worker | ~4m37s | 1950 |
| full scan, 8 workers | 1m28s | 1950 |
Byte-identical findings every way. --diff is the actual fix for CI latency; the engine didn't need to get faster for this case to be fast.
./build.sh # machin encode + build -> ./secure ./secure --target ./some/repo # JSONL findings on stdout ./secure --target ./some/repo --summary # one JSON summary object ./secure --target ./some/repo --sarif # SARIF 2.1.0 (GitHub Code Scanning) ./secure --target ./some/repo --diff # only working-tree-changed files ./secure --target ./some/repo --diff-base origin/main # only files changed vs a base ref (PR CI) ./secure --target ./some/repo --workers 16 # parallel full-audit (default: 8) ./secure --target ./some/repo --hart # guidance for the agent's own hart report ./secure verdict --target . <id> drop --reason "..." # persist the agent's judgment ./secure verdict --target . --stdin # batch verdicts via JSON Lines
Exit codes: 0 clean · 1 error · 2 high/critical findings present.
rules.json is plain data, read fresh from disk every run — extend it without recompiling. The rule pack is the actual product; the engine is interchangeable.
CWE-798 AWS, Google, Slack, GitHub PAT, Stripe, JWT, private keys, generic high-entropy, connection strings, config files (.properties, TOML, INI), hardcoded JWT secrets.
CWE-78/89/95 command injection (shell=True, eval, exec, os.system, Runtime.exec, Command::new), SQL injection (string concat, f-strings, template interp).
CWE-502 pickle, yaml.load, ObjectInputStream, PHP unserialize, Ruby YAML.load.
CWE-79/918/611 dangerouslySetInnerHTML, innerHTML, document.write, template.HTML, HTTP concat URLs, XML external entities.
CWE-327/295 MD5, SHA-1, DES, InsecureSkipVerify, rejectUnauthorized:false, verify=False, trust-all certs, weak TLS versions, JWT alg:none (critical).
CWE-120/242 strcpy, strcat, sprintf, gets, Rust unsafe blocks.
CWE-732/668/311 Terraform (public S3, 0.0.0.0/0 SGs, unencrypted RDS), Kubernetes (privileged, runAsUser:0, hostPath, hostNetwork, :latest), Docker (ADD URL, :latest, apt-get upgrade, COPY . .).
CWE-352/489 Django (ALLOWED_HOSTS=*, @csrf_exempt, SECURE_SSL_REDIRECT=False), Flask (debug=True RCE, hardcoded secret_key), FastAPI (CORS *), Spring (actuator exposed), Express (no body limit).
CWE-285/532/94 pull_request_target with secrets, write-all permissions, secrets in run steps, PR event data in scripts (script injection), continue-on-error masking scans.
CWE-1104/798 unpinned deps (requirements.txt, package.json ^/~, Cargo.toml *, Gemfile), config file secrets (.properties, TOML, INI), npm --no-audit.
CWE-327/916/384 JWT alg:none (4 languages), unsalted password hashes, bcrypt low rounds, session fixation, plaintext password scheme, weak password length, non-crypto random for secrets.
CWE-942/601/352 CORS wildcard, open redirect, CSRF, SameSite=None, mass assignment, log injection, ReDoS, info exposure via tracebacks.
CWE-1336/1321/943/90 GraphQL (introspection, no depth/complexity limits), WebSocket origin, prototype pollution, NoSQL injection ($where, $gt), LDAP injection, SSTI (Jinja/EJS), SSRF (urlopen, axios, fetch, file_get_contents).
CWE-327/329/780 ECB mode, hardcoded IV/nonce/salt, AES-128/192, RSA <3072, PKCS1v1.5 padding (oracle attacks), deprecated crypto.random, MD5/SHA1 for passwords (5 languages).
CWE-89/95/98/502 SQL with $_GET/$_POST, eval/include/unserialize with user input, file_get_contents SSRF, md5/sha1/crypt for passwords.
CWE-209/489/532/547 debug console.log, print with secrets, hardcoded IPs, HTTP (not HTTPS) URLs, verbose errors in prod, assert for sensitive checks, file upload without validation.
CWE-134/120/770 format string attacks (printf/fprintf with variable), scanf %s without bounds, alloca (stack overflow), strtok (not thread-safe), atoi (no error handling), getenv without validation.
CWE-704/761/74/94 Rust transmute/from_raw/raw pointers/ptr::read/write, Go unsafe.Pointer/cgo/Sprintf-SQL/no-TLS, Java JNDI injection (Log4Shell), SpEL injection, XPath injection, SSRF, XML TransformerFactory (XXE).
CWE-489/319/749 Android: debuggable=true, cleartext traffic, allowBackup, exported components, WebView JS + addJavascriptInterface (RCE). iOS: ATS disabled, plist secrets.
CWE-352/1336/89/79 Rails: CSRF skip, render with params (SSTI), attr_accessible. Laravel: DB::raw SQL injection, Blade {!! !!} (XSS), env() in code.
CWE-732/89/94/943 AWS S3 public-read, IAM wildcard Action/Resource, hardcoded AWS creds. Redis EVAL injection, Elasticsearch query_string injection, ORDER BY injection.
CWE-319/1104 FTP/Telnet (cleartext), SMTP without TLS, GitHub Actions @main/@master (not pinned to SHA), npm postinstall scripts, pip install from git URLs.
PythonJS/TSVueGoRustC/C++C#Java/KotlinRubyShellSwiftPHPYAMLTerraformDockerfileXMLTOML.propertiesplistINIrequirements.txtGemfileJSON
--sarif emits a SARIF 2.1.0 report (validated against the official schema) that GitHub's Security tab, VS Code, and any SARIF consumer read directly. There's a reusable GitHub Action — drop this into any repo:
# .github/workflows/machin-secure.yml name: machin-secure on: [push, pull_request] permissions: contents: read security-events: write # required to upload SARIF jobs: scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: javimosch/machin-secure@v2 with: target: '.' - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: machin-secure.sarif category: machin-secure
The action exits 0 whether or not findings exist (so the SARIF upload always runs); severity gating is left to GitHub code-scanning settings.
No OpenAI/OpenRouter key, no budget, no network call to a model provider. The agent driving secure already is an LLM.
Read-only static analysis. Never executes target code, never mutates the target repo.
The filesystem is scanned fresh every time — freshness over sophistication. The one persistent state is the agent's verdict memory.
--hart prints guidance for the agent to author and publish its own HTML report with its own model. The tool doesn't bake prose judgment into a binary that owns none.
machin / MFL — a language optimized for the AI agent writing it. The scanner is ~500 lines of MFL, compiled to a single ~88 KB static binary. Read the vision & north star →