Releases: 0xmariowu/AgentLint
Release list
AgentLint 0.8.6
New checks (4)
- W7 You can now see when
CLAUDE.mdis missing a documented local fast test command — AI agents need a single runnable command (e.g.pytest tests/unit/ornpm test) to verify before pushing. - W8 You can now detect Node.js projects where
package.jsonhas noscripts.testentry —npm testsilently fails with "missing script" when agents try to run it. - H7 You can now detect gate workflows (
test-required,*-check, etc.) that alwaysexit 0— warn-only gates never block merge despite appearing to enforce rules. - S9 You can now detect personal email addresses in git history — PII leak in public commit history that survives even after source code is cleaned.
Fixes
- ci: fix codex-autofix-dispatch marker mismatch — loop-prevention guard searched
codex-autofix-dispatch:but write-block emittedcopilot-autofix-dispatch:, so repeat CI failures on the same PR head spammed fresh@copilot please fixcomments. Unified both tocopilot-autofix-dispatch:. - npm: add
scripts.testtopackage.json—npm testnow works as the canonical local test entry point.
AgentLint 0.8.5
Infrastructure
scripts/sanitize.sh— new read-only pre-release PII audit. Eight checks cover author emails (git log), personal paths (tracked files + commit messages + recent history), Tailscale and mDNS machine hostnames, and optional.internal-codenamesenforcement across files / commits / branches. Scans tracked-only so untracked test artifacts don't create noise. Mirrors the placeholder filter from.husky/pre-commitso documentation examples don't trip it.- Commit-message PII scan workflow. New
.github/workflows/commit-message-scan.ymlrejects PRs whose commit messages contain personal paths or machine hostnames. Closes the gap where.husky/pre-commitandhygiene.ymlonly scanned staged file contents, not commit metadata.
Chore
.husky/pre-commitnow excludesscripts/sanitize.shfrom the private-pattern scan — same rationale as the existing.gitleaks.tomlexclusion: detection tools must be allowed to mention the patterns they detect.
Notes
- Docs and tooling only. No scanner behavior, check set, or scoring changes. Check count stays 49.
AgentLint 0.8.4
Fixed
docs/ship-boundary.mdno longer references artifacts that don't exist in this repo. The v0.8.3 import from VibeKit left behind pointers tostandards/ship-boundary.json,.ship-boundary-deny.local,bootstrap.sh,tests/e2b/,configs/**,hooks/**, and rule IDs likeSB-L-01/SB-N-05. SHIP / LOCAL / NEVER examples now match agent-lint's actual layout, and a new "How this is enforced today" section points to the real enforcement surface (.husky/pre-commit,hygiene.yml,author-email.yml,gitleaks.yml,semgrep.yml).docs/rules-style.md§3.12error-message example now uses.husky/pre-push's real rebase-failure message instead of VibeKit'sscripts/committer. Dead pointers toconfigs/templates/*,atomic-dev-environment.md, and external wiki sections removed.
Notes
- Docs only. No scanner behavior, check set, or scoring changes. Check count stays 49.
AgentLint 0.8.3
Infrastructure
- Public Repo Hygiene workflow. New
hygiene.ymlenforces codename, personal-path, and container-image-pin checks on every PR — complementing the existingauthor-email.ymlcommit-identity gate. - Workflow Sanity workflow. New
workflow-sanity.ymlruns actionlint (with shellcheck) plus no-tabs and no-conflict-marker checks whenever.github/workflows/**changes. - CodeQL analysis. New
codeql.ymlrunsjavascript-typescriptscans on every PR, push tomain, and weekly cron. Closes the CodeQL gap from the public-repo security audit. - Composite actions.
ensure-base-commitprogressively deepens shallow clones until a required base SHA is reachable;detect-docs-changesemitsdocs_only=truewhen a PR touches only docs — reusable building blocks for future workflows. .shellcheckrcsets the repo-wide shellcheck baseline (warning severity, bash dialect, sourced-file following)..husky/pre-pushrebases feature branches onorigin/mainbefore push so CI always sees an up-to-date branch.- Test aggregator job (
test (20)/test (22)) wraps the OS × Node test matrix to satisfy stable branch-protection contexts without pinning individual OS variants as required.
Chore
docs/rules-style.mdanddocs/ship-boundary.md— rule-authoring style guide and file-tier decision framework imported from VibeKit.github/codeql-action3.35.2 → 4.35.2 (dependabot). Unifiesinit,analyze, andupload-sarifon v4 and ships CodeQL bundle 2.25.2.- Shellcheck cleanups in
accuracy.yml(find/xargs null-byte handling,ls→findfor counting, noop-truncate prefix) andrelease.yml(uselesscatremoved) to satisfy the new actionlint gate.
Notes
- No new checks, no scoring changes, no scanner behavior changes. Check count stays 49. Dimensions unchanged.
AgentLint 0.8.2
Security
- Symlink attack protection across scanner, fixer, and analyzers. A malicious repository could place a symlinked
CLAUDE.md(orAGENTS.md,.cursorrules,.cursor/rules/*.mdc) pointing to sensitive host files like~/.ssh/id_rsaor/etc/passwd. Running scanner, fixer, deep-analyzer, or session-analyzer on such a repo would read, leak (to LLM prompts or output), or overwrite the symlink target. All entry-file resolution now useslstat-based checks that reject symlinks. - I1 keyword scan no longer buffers entire entry file in memory. v0.8.1 introduced a bash variable accumulator that grew unbounded — a 29 MB
CLAUDE.mdcould crash the scanner withxrealloc: cannot allocate N bytesunder constrained memory. Replaced with streaming awk that uses O(1) memory regardless of file size. - S6 hardcoded secrets check now inspects
.envfiles. Previous':!*.env'exclusion allowed committed secrets in.env/.env.local/.env.productionto bypass detection. - Hook script paths confined to project directory.
extract_script_path(used by H3/H6) refuses absolute paths and traversal sequences that escape the scanned repo. - F8 rules directory check rejects symlinks and non-regular files. Symlinked
.claude/rulesor non-regular.mdrule files could cause tool crashes or unexpected reads. - S3 secret-scan detection refuses symlinked
.github/workflows.grep -rlfollows symlinks passed as command-line arguments; a symlinked workflows directory could cause the scanner to traverse outside the repo.
Notes
- Addresses 10 security findings from Codex code review.
- All local tests pass (scorer 15, fixer 20, reporter 11, scanner 93, e2e 45, sarif 10, action-smoke 6, install-script 16, traversal 7, malicious-fixtures 10) plus E2B extreme correctness suite 33/33.
AgentLint 0.8.1
Fixed
- S7 personal paths check no longer silently fails on git < 2.40. The
:!__tests__/*pathspec exclusion triggeredfatal: Unimplemented pathspec magic '_'on git 2.39 (Debian 12 default). The error was swallowed by|| true, causing the check to always report "no personal paths" — even when files contained/Users/or/home/paths. Fix moves the exclusion from git pathspec to a grep pipe filter. - I1 emphasis keywords are no longer counted inside code blocks.
IMPORTANT,NEVER,MUST, andCRITICALinside fenced code blocks (```) and indented code (4-space) were inflating keyword density for CLAUDE.md files with code examples. Fix strips code blocks before counting.
Notes
- Found via E2B cloud sandbox testing: 541 tests across 20 real repos, 22 edge cases, GitHub Action simulation, and Claude Code E2E — all passing after fix.
AgentLint 0.8.0
Added
- You can now get AgentLint findings in GitHub's Security tab and as inline PR annotations. Enable with
sarif-upload: 'true'in your workflow. Findings appear alongside CodeQL and Dependabot alerts — persistent, trackable, and integrated with your existing security notification workflow. SARIF upload requires Code scanning enabled (free for public repos, GHAS for private). - Inline PR annotations now appear on every run — even without SARIF/Code scanning. AgentLint emits
::warningand::errorworkflow commands that GitHub renders as yellow/red annotations on the PR Files changed tab. No configuration needed.
AgentLint 0.7.1
Added
- You can now install AgentLint on Windows from inside Git Bash or WSL (#82).
npm install -g @0xmariowu/agent-lintpreviously rejected Windows withEBADPLATFORMbefore the installer could even run; that block is gone. - Clear guidance when bash is missing on Windows. Running the installer from
cmd.exeor PowerShell now exits with a message pointing to Git for Windows or WSL instead of a cryptic shell error.
Fixed
- Postinstall detects
claudecross-platform (whereon win32,command -velsewhere) and verifiesbashavailability on Windows before invoking the installer. .gitattributesnow forces LF on*.sh,*.js,*.md, and other text files so Windows checkouts with defaultcore.autocrlf=trueno longer convert shell scripts to CRLF and break shebangs.
Notes
- The scanner itself (
src/scanner.sh) is still bash. Running it on Windows requires Git Bash or WSL — see the Platform requirements table inREADME.md. A native cmd.exe / PowerShell flow is out of scope for this patch.
AgentLint 0.7.0
Audit-driven minor release. Dimension count grows from 6 to 8, check count from 42 to 49 — your repo score will shift, because the scanner is now finally counting checks it had been silently dropping.
Added — two new dimensions, seven new checks
deep-analyzer and session-analyzer were already emitting D1-D3 and SS1-SS4 results, but weights.json had no dimension entry for either prefix, so scorer.js silently dropped every contribution. The audit caught this and the dimensions are now first-class:
- Deep (weight 0.05) — D1, D2, D3 from
deep-analyzer.js - Session (weight 0.05) — SS1-SS4 from
session-analyzer.js
Total dimension weight is now 1.10 instead of 1.0, so existing dimensions each contribute ~9% less of the total — see standards/weights.json for the rationale. This is intentional and the score formula now reflects every check the analyzers emit.
Fixed — pipeline contract bugs
- F5 medium-severity findings now actually auto-fix.
inferFixTypewas returning'guided'for F5 with score ∈ [0.5, 0.8), butfixer.jsonly handled F5 in theassistedbranch — so medium-severity broken-reference findings fell through to text guidance and never ranexecuteAutoFix. scorer.jsno longer crashes silently on missing input. A bad path (scorer.js /no/such/file) used to surface as an unhandled stream error stack trace; now it printsscorer: cannot read input '...': ENOENTand exits 1.reporter.js --plan plan.json scores.jsonno longer eatsplan.jsonas the scores file. Positional argument lookup now skips indices that are values for--plan,--output-dir,--format, and--before.- S1-S4 evidence sources corrected to
corpus-4533— theevidence_textquoted 4,533-repo statistics but theevidence_sourcesfield referenced the small qualitativepractical-auditset. - PR #72 regression coverage — added scanner tests for BASH_REMATCH multi-link isolation and the three
emit_resultdefense paths (unknown check_id, jq failure, empty jq output).
Added — accuracy baseline observability
The full-corpus baseline runner used to swallow per-repo failures with 2>/dev/null || true, leaving the operator no signal about how many of the 4,533 repos silently failed reconstruction or scanner timeout:
- Per-stage failure counters in
tests/accuracy/run-full-baseline.sh— separate counts for reconstruct / timeout / scanner-error, list of first 10 failed repo names, warning when failure rate exceeds 5%. --dry-runflag validates paths, tarball, and script binaries without running the 10-30 minute scan.- Wilson 95% confidence intervals in
tests/accuracy/compare-results.js. Several checks have small N (S6=25, S7=354) where the headline accuracy point estimate can swing several percentage points just from labelling noise. The console table is unchanged; a new "Low-N warning" section flags checks where the CI width exceeds 10 percentage points. CI bounds are saved to JSON output for cross-run comparison.
Engineering hygiene
- All three Dockerfiles (
tests/Dockerfile.e2e,tests/docker-e2e/Dockerfile,tests/docker-e2e/Dockerfile.full-corpus) pinnode:20-slimto a SHA256 digest. Dependabot'sdockerecosystem can now propose explicit upgrades. - New
.dockerignorekeeps.env,.git/,node_modules/, and the multi-MB corpus tarballs out of the build context — both a leak fix and a build-time bloat fix, since all three Dockerfiles useCOPY . /app/. npm/package-lock.jsonis now committed for reproducible consumer installs..gitignoreexcludes__pycache__/,*.pyc, andstate/.
Known follow-up
- #79 — C2 (CHANGELOG) recall regression: 60% → 12% in the v0.6.1 baseline. Wilson CI in this release surfaces the kind of regression that's currently invisible.
AgentLint 0.6.2
Scanner correctness fixes. Your repo score may change — it is now what scanner says it is.
Fixed — six silent-failure bugs in scanner
All of these made scanner report higher scores than reality:
- S2 (SHA pinning) now actually checks standard workflow syntax. The grep only matched bare
uses:keys; the- uses:list-item form used by every normal workflow slipped through, so wf_total stayed at 0 and S2 always scored 1 regardless of pinning. - W6 (pre-commit hook speed) now emits score 0 when a slow command (tsc / eslint --fix / jest / pytest / etc.) is detected. Both branches previously returned 1.
- F5 (broken references) no longer follows
../paths out of the project. A CLAUDE.md that linked to../../../etc/passwdused to resolve against the real filesystem and score as "valid." The check also stopped resolving against the shell's CWD, which let bare references match wherever the user happened to run scanner from. - emit_result now validates jq output. Unknown check_ids used to emit the literal string
"null"as dimension, poisoning scorer/plan-generator/reporter downstream. A broken jq returning exit 0 with empty stdout used to produce an empty JSONL line. - F5 reference extraction no longer crashes on markdown links. Helper functions reset
BASH_REMATCH, and the tail of the while-loop then hit an unbound variable underset -u— F5 emitted 0 broken references regardless of content. Matches are now cached into locals before the helper call.
Fixed — accuracy benchmark
Rebuilt against v0.6.2 scanner + all fixes. The tarball now also packages .claude/settings.json (1,574 of 4,533 corpus repos have it) so H1-H6 harness checks see real config:
- Overall precision 95.2% → 97.8% (+2.6)
- Overall recall 94.3% → 95.9% (+1.6)
- Overall F1 94.7% → 96.8% (+2.1)
- Overall accuracy 93.9% → 96.4% (+2.5)
Added
tests/robustness/malicious-fixtures.sh— 10-fixture robustness harness (paths with spaces/newlines,../traversal, symlink loops, files > 256 KB, non-UTF-8 CLAUDE.md, corrupt.git/HEAD, emoji filenames).tests/fixer-safety/test-traversal.js— 7 path-traversal guard assertions againstfixer.js.tests/accuracy/run-full-baseline.sh— one-shot orchestrator for rebuilding accuracy baselines. Extract → reconstruct → parallel scan → compare.- +99 scanner / JS test assertions (94 → 193). Four previously-orphan test files now run in CI:
test-e2e.sh,test-install-script.sh,test-session-analyzer.sh,test-deep-analyzer.sh.
Security
- npm
postinstall.jsnow fetchesinstall.shfrom the git tag matching the published package version, notmain. Before, any commit tomainsilently changed install behavior for every prior version. .husky/pre-commitmoved private patterns out of the public repo. Load from~/.agentlint-private-patterns(opt-in per-user file), missing file means scan is skipped.release.ymlnow declares top-level least-privilegepermissions: contents: read. The release job still elevates locally for creating the GitHub Release.
Quality
reporter.jsvalidates--formatand exits non-zero on unknown values (previously silently exited 0 with no output).reporter.jsesc()now also escapes single quotes (defense-in-depth).scorer.jswarns to stderr when a JSONL line fails to parse (was silent skip).- Dead code removed across
reporter.js,scorer.js, andsession-analyzer.js.