GitHub - rsub122/tabsmith-lint: Pre-submission compliance linter for Manifest V3 Chrome extensions — catch Chrome Web Store rejection risks before you submit · GitHub
/" data-turbo-transient="true" />
Skip to content
Search or jump to...
Search code, repositories, users, issues, pull requests...
-->
Search
Clear
Search syntax tips
Provide feedback
--><br>We read every piece of feedback, and take your input very seriously.
Include my email address so I can be contacted
Cancel
Submit feedback
Saved searches
Use saved searches to filter your results more quickly
-->
Name
Query
To see all available qualifiers, see our documentation.
Cancel
Create saved search
Sign in
/;ref_cta:Sign up;ref_loc:header logged out"}"<br>Sign up
Appearance settings
Resetting focus
You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.
Dismiss alert
{{ message }}
rsub122
tabsmith-lint
Public
Notifications<br>You must be signed in to change notification settings
Fork
Star
main
BranchesTags
Go to file
CodeOpen more actions menu
Folders and files<br>NameNameLast commit message<br>Last commit date<br>Latest commit
History<br>1 Commit<br>1 Commit
.github/workflows
.github/workflows
corpus
corpus
fixtures
fixtures
scripts
scripts
src
src
test
test
.gitignore
.gitignore
LICENSE
LICENSE
README.md
README.md
package-lock.json
package-lock.json
package.json
package.json
tsconfig.json
tsconfig.json
vitest.config.ts
vitest.config.ts
View all files
Repository files navigation
tabsmith-lint
A pre-submission compliance linter for browser extensions. v0.1 analyzes an unpacked<br>Manifest V3 Chrome extension directory and reports likely Chrome Web Store rejection<br>risks before you submit — unused/excessive permissions, missing permissions, MV3<br>violations, and broken file references — with a clear verdict and actionable fixes.
Catch the "Purple Potassium" permission rejection before you submit. The most<br>common Chrome Web Store rejection is excessive/unused permissions — declaring tabs,<br>bookmarks, cookies, or your code never actually uses. tabsmith-lint<br>statically checks your manifest against your code and maps findings to the violations<br>Chrome reviewers flag:
Violation ID<br>What it means<br>tabsmith rules
Purple Potassium<br>Excessive / unused permissions<br>PERM001, PERM003, PERM004, PERM005
Blue Argon<br>Remotely hosted code / string execution<br>MV3001, MV3002
Yellow Magnesium<br>Functionality / broken packaging<br>FUNC001, FUNC002
npx tabsmith-lint ./my-extension<br>npx tabsmith-lint ./my-extension --format json<br>npx tabsmith-lint ./my-extension --min-severity reject
Exit codes: 0 pass · 1 needs fixes · 2 high rejection risk · 3 tool error.
No install needed — npx runs the latest published version. Or install it: npm i -g tabsmith-lint.
Develop
npm install<br>npm test # vitest: unit + e2e (one fixture per rule)<br>npm run build # tsc → dist/<br>node dist/cli.js ./my-extension
Validate against real extensions
Beyond the unit/e2e fixtures, the linter is validated on real extensions —<br>both Google's clean MV3 samples and real published, built/minified OSS<br>extensions (uBlock Origin, Dark Reader, Stylus, ...). All fetched on demand — see<br>corpus/:
npm run build # required first — the scripts use dist/<br>npm run validate # robustness: ~100 clean extensions, gate on 0 crashes<br>npm run score # accuracy: PERM001 false-positive rate vs ground truth<br>npm run validate:releases # robustness on real minified extensions<br>npm run score:releases # accuracy on the messy corpus<br>npm run demo # print reports for recognizable real extensions
npm run score gates promoting PERM001 to reject: under 5% false positives.<br>Across 28 hand-labeled extensions (22 samples + 6 minified releases): 0% false<br>positives, 0 false negatives, all verdicts matched — independently audited.<br>Building this corpus caught and fixed six real false positives (plus a<br>prototype-safety crash) the synthetic fixtures missed — see corpus/README.md. CI<br>runs the suite and all validation gates on every push (.github/workflows/ci.yml).
PERM001 accuracy gate
PERM001 (declared-but-unused permission) is the flagship rule, and its<br>false-positive rate is make-or-break — a wrong "remove this permission" suggestion<br>destroys trust. In v0.1 it ships at fix severity, never reject (the single<br>constant PERM001_SEVERITY in src/rules/permissions.ts). Promoting it to reject<br>is gated on validating under 5% false positives against a hand-labeled corpus of<br>20–30 real extensions, where the label is "permission actually used by<br>implementation" — not "extension passed review". That corpus is deferred; until it<br>exists, leave the severity at fix.
Status
v0.1. Chrome-only, directory input, 10 rules (PERM001-005, MV3001-003, FUNC001-002).
Firefox/Edge, ZIP/CRX input, SARIF, and a GitHub Action are on the roadmap.
Two rules are intentionally...