How Sentinel works.
The playground, CLI, MCP server, and agent skill all share one engine. This page covers every surface: what each one does, how to configure it, and how to read a verdict.
Overview
Sentinel is a universal security verification framework for AI agent installations. It sits between an agent (or a human) and any installer: nothing installs until the target has been acquired (download-only, never executed), analyzed, risk-scored, policy-checked, and explicitly approved.
The pipeline is always the same:
Acquire -> Analyze -> Score -> Policy -> Approve -> InstallThis website is the playground: a sandboxed browser UI that exposes read-only verify for npm, github, pip, uv, cargo, go, and docker. Install and local filesystem targets stay offline here. The full package also ships a CLI for your terminal, an MCP server for AI agents, and an agent skill that intercepts install requests and routes them through MCP.
This playground runs Sentinel v1.1.0 (August 26, 2026). See the npm release or the GitHub repository.
Playground
Type a command into the console on the playground. A leading sentinel is tolerated, so sentinel verify npm lodash works too.
verify npm <package>verify npm lodashA version is optional: lodash@4.17.21verify github <owner/repo>verify github expressjs/expressPublic repositories onlyverify pip <package>verify pip tomliPyPI packageverify uv <package>verify uv tomliSame acquire path as pipverify cargo <crate>verify cargo serdecrates.io packageverify go <module>verify go gopkg.in/yaml.v3Go module via proxy.golang.orgverify docker <image>verify docker hello-worldRegistry metadata + bounded layer sampling; never runshelphelpList every commandclearclearClear the console outputThe playground is verify-only. It cannot install packages or scan your local filesystem. See the security model below.
Reading the report
Every verification renders the same structure. The banner leads with the decision; color always encodes risk.
Decision
The policy engine resolves the findings into one verdict:
Risk & confidence
risk is a level plus a 0-100 score. confidence reflects how much data the engine had to work with. signals counts positive and negative indicators (for example, a long publish history versus a non-HTTPS source).
Artifact identity & analyzer checks
Version 1.1.0 records the exact artifact that was scanned. npm and npm-backed MCP reports include the resolved version and registry integrity digest; GitHub reports include the resolved commit SHA. Reports also list each analyzer as completed, skipped, or failed, with its duration. The playground surfaces both fields in every verdict.
Finding severities
Each finding carries a severity. A test tag marks findings located in test files, which usually matter less.
Scoring system
A verdict comes from two distinct things. The risk score answers "how dangerous does this look, based on what we found?" The policy decision answers "what action should we take?" Score feeds policy, but it does not decide everything on its own.
Pipeline
What happens when you run sentinel verify:
- 01Acquire
Download or read the target — an npm tarball, GitHub repo, local path, or skill.
- 02Identify
Record an immutable package integrity digest or repository commit SHA.
- 03Analyze
Run supported analyzers, recording completed, skipped, and failed checks.
- 04Filter
processTestFindings() drops benign noise from test and fixture files.
- 05Permissions
buildPermissionGraph() maps findings to the capabilities the target requests.
- 06Risk score
RiskCalculator produces a 0-100 score plus a confidence value.
- 07Data check
assessData() decides whether there was enough evidence to trust the result.
- 08Policy
PolicyEngine resolves one of AUTO_APPROVE, APPROVE, WARN, REQUIRE_APPROVAL, or BLOCK.
Risk score (0-100)
Every unique non-positive signal adds points by severity. Positive signals can reduce only LOW and MEDIUM risk; they can never cancel HIGH or CRITICAL evidence.
severeScore = Σ CRITICAL + HIGH signal weightslowerScore = min(Σ MEDIUM + LOW signal weights, 20)positiveReduction = min(uniquePositiveSignals × 5, 30)finalScore = clamp(severeScore + max(0, lowerScore − positiveReduction), 0, 100)
Each foul adds points by severity:
Every finding with positive: true subtracts 5 points from the capped LOW/MEDIUM subtotal, up to a maximum reduction of 30. It never offsets HIGH or CRITICAL findings. Examples include verified-publisher (npm verified badge) and signed-release (registry integrity matched).
Duplicate signals are damped: the first occurrence has full weight, the second has 10%, and later repeats add nothing. Related process-execution rules share one signal group so a single behavior is not counted repeatedly.
The final score maps to a risk level label:
Confidence (0-100%)
Confidence is separate from the risk score: it measures how much evidence was actually gathered. It never lowers the risk score — instead it gates whether auto-verification can be trusted.
+35 meaningful metadata (version, publish date, repo, license, author, downloads)+25 at least one file was scanned+min(fileCount × 2, 20) bonus for more files scanned+min(totalSignals × 2, 20) bonus for number of findings (positive + negative)
If confidence falls below minConfidence (default 40%), the decision becomes REQUIRE_APPROVAL — we found something, but not enough data to trust the scan.
Policy decision
Policy runs after scoring. These thresholds drive it, and can be overridden with a --policy file:
blockThreshold = 80 → score >= 80 → BLOCKwarnThreshold = 50 → score >= 50 → WARNminConfidence = 40 → confidence < 40 → REQUIRE_APPROVAL
The engine evaluates rules in order — the first match wins:
- 01BLOCK
corporateBlacklist match
- 02BLOCK
risk.score >= blockThreshold
- 03BLOCK
any CRITICAL finding
- 04REQUIRE_APPROVAL
insufficient data (confidence < minConfidence)
- 05REQUIRE_APPROVAL
any HIGH finding
- 06AUTO_APPROVE
corporateWhitelist match
- 07AUTO_APPROVE
autoApproveTrusted + verified/trusted publisher
- 08WARN
install scripts present
- 09REQUIRE_APPROVAL
shell access detected
- 10REQUIRE_APPROVAL
network access detected
- 11REQUIRE_APPROVAL
filesystem-write access detected
- 12WARN
risk.score >= warnThreshold
- 13APPROVE
otherwise
The five possible decisions:
Example score math
A package with one typosquat, a fresh publish, an install script, and a verified badge:
1× CRITICAL typosquatting +501× MEDIUM new-package +101× MEDIUM install script +101× positive verified-publisher −5severeScore = 50 = 50lowerScore = min(20, 20) = 20positiveReduction = 5 (cap 30)finalScore = 50 + (20 − 5) = 65 → HIGHPolicy: CRITICAL finding → BLOCK (first-match; score is irrelevant) HIGH alone (e.g. eval) → REQUIRE_APPROVAL (yes / auto approve) trust signals never bypass CRITICAL/HIGH gates
Analyzers & fouls
Each analyzer emits findings. A finding is a category + severity + ruleId + reason. Comments are stripped before static analysis, so an eval() inside a // comment is ignored. The matching line or snippet is attached as evidence when possible.
A · Metadata analyzer
Package identity and reputation.
missing-nameMEDIUMNo package name — hard to identify the source.missing-licenseLOWNo license — legal and audit risk.missing-repoLOWNo linked source repo — origin cannot be verified.new-packageMEDIUMFirst published < 30 days ago — a common supply-chain attack window (impersonation, premature publish before reputation builds).recent-updateLOWCurrent version published < 7 days ago — attacks often hide in fresh releases of otherwise trusted packages.low-downloadsMEDIUM< 100 weekly downloads — low community trust.long-historyINFO (+)Package has existed > 1 year — positive signal.verified-publisherINFO (+)npm verified publisher badge — positive signal.signed-releaseINFO (+)Downloaded package matches the registry integrity digest.npm-provenanceINFO (+)Registry attestation/signature metadata is present (presence only — not cryptographically verified by Sentinel).archived-repositoryMEDIUMLinked source repository is archived.established-repositoryINFO (+)Repository has at least 1,000 stars.security-policyINFO (+)Repository publishes a security policy.B · Source analyzer
Where the package comes from.
non-httpsHIGHSource URL is not HTTPS — MITM / tampering risk.suspicious-tldHIGH/MEDIUMHostname-anchored match for .tk, .ml, .ga, .cf, .gq, .xyz, .top, .work, or .click. .xyz is MEDIUM; the rest are HIGH.typosquattingCRITICALnpm name within Levenshtein distance 1 of a popular package (names ≤ 4 chars skipped). Only flagged when the package also looks suspicious — not verified, not from a trusted repo, and new (< 30d) or low-downloads (< 100) or missing repo/homepage. Established packages are skipped.C · Static code analyzer
Hybrid analysis — Babel AST for JS/TS, tree-sitter AST for Python, regex fallback.
Scans .ts .tsx .js .jsx .mjs .cjs .py .go .rs .sh .bash .lua
evalHIGHDynamic code execution presence — review gate (REQUIRE_APPROVAL), not an automatic BLOCK.function-constructorHIGHnew Function() presence — equivalent capability to eval; HIGH, not CRITICAL.execHIGHchild_process.exec() presence. RegExp.exec() is ignored via negative lookbehind.exec-sync-fileHIGHexecSync / execFile / execFileSync presence.spawnHIGHProcess spawning.child-processHIGHchild_process module import or usage.os-systemHIGHPython os.system() presence.subprocessHIGHPython subprocess.run / call / Popen.powershellHIGHPowerShell invocation.dynamic-importMEDIUMimport() — runtime module loading.require-dynamicHIGHrequire() with string concatenation — evasion.curl-pipeCRITICALcurl ... | bash/sh — remote code execution (stays CRITICAL → BLOCK).wget-pipeCRITICALwget ... | bash/sh — remote code execution (stays CRITICAL → BLOCK).chmod-xMEDIUMMaking files executable.rm-rfMEDIUMRecursive force delete capability.sudoHIGHElevated privilege execution.registry-editHIGHWindows registry modification.cronHIGHCron / scheduled task persistence.startup-folderHIGHStartup / LaunchAgent persistence.base64-blobMEDIUMLarge base64 blob — possible hidden payload.hex-blobMEDIUMLarge hex blob — possible hidden payload.packed-upxHIGHUPX-packed executable.minifiedMEDIUM> 500KB file with < 10 lines — hard to audit.high-entropyMEDIUMEntropy > 5.5 on a large file — sign of obfuscation.D · Secret analyzer
Credential leaks in any file.
Skips .env.example and .env.sample — intentional placeholders.
aws-keyMEDIUMAWS access key ID (AKIA...) — identifier; often paired with a secret elsewhere.aws-secretCRITICALAWS secret access key.gcp-keyHIGHGCP service account JSON.azure-keyHIGHPossible Azure storage key.openai-keyCRITICALOpenAI API key (sk- / sk-proj- / sk-svcacct-...).anthropic-keyCRITICALAnthropic API key (sk-ant-...).jwtHIGHJSON Web Token embedded in source (test/doc paths de-noised).private-keyCRITICALPEM private key block (test/doc fixtures de-noised).github-tokenCRITICALGitHub personal access token (ghp_...).generic-api-keyHIGHapi_key / secret_key = "..." patterns (tightened to cut placeholder noise).E · Network analyzer
Exfiltration, C2, and tracking.
hardcoded-ipMEDIUMHardcoded public IP.discord-webhookHIGHDiscord webhook — data exfiltration channel.telegram-botHIGHTelegram bot API — exfiltration / C2.pastebinHIGHPastebin URL — stolen data dumps.ngrokHIGHngrok tunnel — bypasses firewalls.cloudflare-tunnelHIGHCloudflare tunnel — covert egress.torHIGH.onion address — anonymous C2.crypto-minerCRITICALcoinhive, xmrig, stratum+tcp — cryptojacking.dynamic-dnsMEDIUMno-ip, duckdns — unstable C2 infrastructure.private-ipLOW10.x / 172.16 / 192.168 / 127.x (non-test paths).F · Install script analyzer
Scripts that run automatically on npm install.
Any script-* finding causes a WARN ("Package has install scripts").
script-postinstallMEDIUMDefines a postinstall script — runs on install.script-preinstallMEDIUMDefines a preinstall script.script-prepareMEDIUMDefines a prepare script.script-installMEDIUMDefines an install script.script-prepublishMEDIUMDefines a prepublish script.dangerous-*VARIESInside a script: curl|bash CRITICAL, wget|bash CRITICAL, Invoke-WebRequest HIGH, sudo HIGH, rm -rf HIGH, chmod +x MEDIUM, npx / npm exec / docker pull / pip install MEDIUM.standalone-scriptHIGHpostinstall.sh / postinstall.ps1 / postinstall.js file present.G · Runtime capability analyzer
Filesystem and network APIs used by runtime code.
filesystem-read-apiMEDIUMRuntime code imports Node.js filesystem APIs.filesystem-write-apiMEDIUMRuntime code can mutate the filesystem.network-apiMEDIUMRuntime code imports Node.js network APIs.H · AI prompt analyzer
Skills, prompts, and instruction files.
Scans SKILL.md, explicit prompt files, and all .md/.txt in skill/local targets. Skips generic README/CHANGELOG/LICENSE in npm packages.
ignore-instructionsCRITICAL"ignore previous instructions" — prompt injection.system-prompt-extractHIGHAttempt to reveal the system prompt.tool-escalationHIGH"use all available tools" — privilege escalation.memory-poisonHIGH"remember this in memory" — agent poisoning.self-updateCRITICAL"update your own instructions" — self-modification.hidden-goalHIGH"secretly / without telling" — covert objectives.jailbreakCRITICALDAN mode, bypass safety, jailbreak patterns.recursive-agentHIGH"spawn another agent" — unbounded delegation.fake-successHIGH"pretend it succeeded" — deception.activation-phraseMEDIUMHidden trigger phrases.zero-widthCRITICALZero-width Unicode only when prompt-injection text is on the same line.invisible-unicodeHIGHOther invisible Unicode characters.html-commentMEDIUMLarge hidden HTML comments (> 200 chars); tooling boilerplate skipped.I · Dependency analyzer
Supply-chain surface.
excessive-depsMEDIUM> 200 dependencies — large attack surface.many-depsMEDIUM> 50 dependencies.insecure-dep-sourceHIGHDependency pulled over http:// or git+http.local-depMEDIUMfile: or ../ dependency — unusual sourcing.optional-native-packageMEDIUMOptional native dependency adds opaque platform-specific code.cveVARIESKnown OSV vulnerability — severity passes through from the advisory (CRITICAL/HIGH/MEDIUM/LOW).J · Binary analyzer
Opaque executables and WebAssembly that require manual review.
opaque-binaryHIGH/MEDIUM.exe/.dll/.so/.dylib are HIGH; .node / .wasm / .bin are MEDIUM.Permission graph
Findings are mapped to the capabilities a target requests. The policy engine then uses these for its network and shell checks.
shellspawn, exec, child-process, os-system, subprocess, powershellnetwork-internet / network-lannetwork-api plus network analyzer findingsnetwork-localhostprivate-ipsecretsaws-key, openai-key, anthropic-key, private-key, github-tokenfilesystem-deleterm-rffilesystem-readfilesystem-read-apifilesystem-writefilesystem-write-api, chmod-x, registry-edit, cron, startup-folderA network-* permission, or any network finding above LOW severity, escalates the decision to REQUIRE_APPROVAL.
Test & fixture files
Test paths are detected by directory (test/, tests/, __tests__/, fixtures/, __mocks__/, e2e/, test_runner/) and by filename (*.test.*, *.spec.*, *_test.py, test_*.py).
By default (scoreTestCodeFully = false), test files are not scanned with the full production ruleset. Benign development patterns are dropped: child_process, spawn, exec, eval, dynamic import, rm -rf, and the like.
Test files are still checked for high-signal threats:
- All secret leaks (category
secret). - Malware signatures:
curl-pipe,wget-pipe,crypto-miner,packed-upx. - Exfil / C2:
discord-webhook,telegram-bot,pastebin,ngrok,tor, etc. - Prompt injection rules in test fixtures.
Surviving test findings are tagged isTest: true and count at full weight — they are real threats, not noise. With --score-tests (scoreTestCodeFully = true), test files are scanned exactly like production code and all rules apply.
What is not a foul
- Comments containing dangerous patterns — stripped before static analysis.
- RegExp.exec() in normal JS code — the exec rule uses a negative lookbehind.
- README / CHANGELOG in npm packages scanned for AI injection — skipped.
- .env.example / .env.sample secret patterns — intentional placeholders.
- Typosquat lookalikes that are established trusted packages (nodejs/test, express, etc.).
- Benign test infrastructure (e.g. spawn in test_runner/) in the default test mode.
- INFO findings such as long-history — informational, score weight 0.
Verification flow
What happens between pressing enter and seeing a verdict:
- 01Parse
The command is validated client-side, then the target is sent to /api/verify.
- 02Guard
The route enforces the remote-ecosystem allowlist, input regex, a per-IP rate limit, and a 45s timeout.
- 03Download
The engine fetches the remote artifact (registry tarball, repo archive, crate, module zip, or image metadata) into an ephemeral temp directory.
- 04Analyze
Static analyzers inspect metadata, source, scripts, network calls, secrets, and permissions. Nothing runs.
- 05Report
A JSON verdict is returned and rendered, then the temp files are discarded.
Security model
The serverless function imports a single entry point: verify(). Capabilities that touch your shell, filesystem, or untrusted archives are never wired in. What you can reach is the whole attack surface.
npm package
Everything ships in one package: @rexymayderio/sentinel. Installing it gives you both binaries, the programmatic engine, and the agent skill files under skills/sentinel/. Version 1.1.0 is published under the MIT license and requires Node.js 20 or later.
$ npm install @rexymayderio/sentinel@1.1.0$ npm install -g @rexymayderio/sentinel@1.1.0
Review the npm release for acquisition hardening, policy changes, analyzers, and validation coverage in v1.1.0.
Two entry points, one shared engine:
sentinelnpx -y -p @rexymayderio/sentinel@1.1.0 sentinel verify npm expresssentinel-mcpnpx -y -p @rexymayderio/sentinel@1.1.0 sentinel-mcpSupported targets
The CLI and MCP support more ecosystems than the playground. Unsupported targets fail acquisition and escalate to REQUIRE_APPROVAL for manual review.
Set GITHUB_TOKEN in your environment to lift GitHub's unauthenticated rate limit on the github path.
CLI
The sentinel binary is the manual verification path. Use verify to analyze without installing, or install to verify first and then install behind an approval gate. Install scripts are never executed during analysis.
sentinel verify npm <package>sentinel verify github <owner/repo>sentinel verify pip <package>sentinel verify uv <package>sentinel verify cargo <crate>sentinel verify go <module>sentinel verify docker <image>sentinel verify git <url>sentinel verify skill <path>sentinel verify local <path>sentinel verify mcp <package>sentinel verify vscode <publisher.extension>sentinel verify agent-rules <path>sentinel verify zip <archive>sentinel install npm <package>sentinel install mcp <package>sentinel install skill <path> --yessentinel install skill <path> --block-acknowledgement '<phrase>'sentinel install agent-rules <path> --cwd . --yessentinel install docker <image> --yes --jsonsentinel verify npm express --sarifsentinel verify npm express --sbomsentinel verify npm express --policy ./policy.jsonsentinel verify local ./app --score-testsPolicy configuration
Pass --policy ./policy.json to override thresholds and publisher lists. Key fields include blockThreshold (default 80), warnThreshold (default 50), minConfidence (default 40), autoApproveTrusted (default false), requireApprovalForNetwork, requireApprovalForFilesystemWrite, trustedPublishers, corporateWhitelist, and corporateBlacklist.
{ "blockThreshold": 70, "minConfidence": 50, "autoApproveTrusted": false, "trustedPublishers": ["@myorg/"], "corporateBlacklist": ["leftpad-evil"]}
MCP deployments can load policy from SENTINEL_POLICY_JSON, enable full test scoring with SENTINEL_SCORE_TESTS=true, and restrict local reads and install destinations with the platform-delimited SENTINEL_ALLOWED_ROOTS variable. Skill/rules defaults use SENTINEL_SKILLS_DIR and SENTINEL_RULES_DIR. Registry/OSV caching uses SENTINEL_CACHE_DIR. Install decisions append to SENTINEL_AUDIT_LOG (JSONL, best-effort).
MCP server
sentinel-mcp exposes Sentinel as an MCP server over stdio. AI agents call its tools to verify targets, read risk reports, and install only after explicit approval. The playground uses the same engine programmatically via verify().
$ npx -y -p @rexymayderio/sentinel@1.1.0 sentinel-mcpThe versioned -p @rexymayderio/sentinel@1.1.0 flag pins this release and tells npx to run the sentinel-mcp binary from the package, not the CLI with a stray argument.
{ "mcpServers": { "sentinel": { "command": "npx", "args": ["-y", "-p", "@rexymayderio/sentinel@1.1.0", "sentinel-mcp"] } }}
Available tools
verify_packageVerify an npm package. Returns a full JSON report.verify_repositoryVerify a GitHub repository.verify_skillVerify a local AI skill directory.verify_mcpVerify an npm-backed MCP package.verify_extensionDownload and verify a VSCode Marketplace extension.verify_agent_rulesVerify agent rules/instructions (any host). Alias: verify_cursor_rules.verify_dockerVerify a Docker image via registry metadata (never runs the image).verify_pypiVerify a PyPI package.verify_cargoVerify a crates.io package.verify_goVerify a Go module.verify_gitVerify a generic git repository URL.compare_packagesCompare multiple npm packages and return a ranked summary.scan_directoryScan a local directory (ecosystem: local).scan_archiveSafely extract and scan a local ZIP or VSIX archive.calculate_riskQuick score summary: score, level, confidence, decision.generate_reportFull verification with terminal, json, markdown, or SARIF output.approve_installPreview gate: approvable, approvalKind, requiredPhrase?, suggestedPrompt — no install.installVerify and install. Review gate needs humanApproved; BLOCK needs blockAcknowledgement.install requires confirm: true. WARN / REQUIRE_APPROVAL need humanApproved: true (yes / auto approve). BLOCK needs blockAcknowledgement equal to approval.requiredPhrase — yes / auto approve / humanApproved are not enough.
Agent skill
The Sentinel agent skill teaches any MCP-capable assistant (Claude Code, Codex, Cursor, Windsurf, Gemini, Continue, …) to intercept install requests, verify through the MCP server above, explain risks in plain language, and only install after approval. The skill never performs analysis itself; it routes to MCP tools and interprets the JSON report.
Install the skill
Copy or symlink the skill folder from the package into your agent's skills directory (portable default shown first):
$ ./install-skill.sh$ ./install-skill.sh --list$ ./install-skill.sh --agent cursor,claude,codex,kiro$ # copies into detected agent skill dirs (Cursor fallback if none)
The MCP server must be configured first (see above). Without it, the skill has nothing to call.
What it does
- Automatic interception: when you say "install express" or "install this GitHub repo", the skill verifies first instead of running the installer directly.
- Manual commands: slash commands like
/verify-packageand/comparefor on-demand analysis. - Two distinct install gates: review (
WARN/REQUIRE_APPROVAL) accepts yes / auto approve viahumanApproved.BLOCKrequires the user to typeapproval.requiredPhraseintoblockAcknowledgement— never invent either signal. - Explain mode: every result includes an executive summary, technical breakdown, grouped findings, and a clear recommendation for dealbreakers and BLOCK decisions; clean installs stay concise.
Manual commands
/verify-package expressverify_package({ name: "express" })/verify-repository owner/repoverify_repository({ owner, repo })/verify-python requestsverify_pypi({ name: "requests" })/verify-docker nginxverify_docker({ image: "nginx" })/verify-skill ./skills/my-skillverify_skill({ path })/verify-mcp @modelcontextprotocol/server-filesystemverify_mcp({ name })/verify-extension publisher.extensionverify_extension({ name })/verify-agent-rules ./.agents/rulesverify_agent_rules({ path })/verify-folder ./my-projectscan_directory({ path })/verify-file ./download.zipscan_archive({ path })/verify-report npm express markdowngenerate_report({ type, target, format })/compare express hono fastifycompare_packages({ names: ["express","hono","fastify"] })Every /verify-* command is read-only. Only the MCP install tool can install. It always verifies first. Review-gate decisions need humanApproved; BLOCK needs the typed blockAcknowledgement phrase.
Limits
Playground
- Accepted ecosystems:
npm,github,pip,uv,cargo,go,docker. Anything else returns a 400. Install and local paths are disabled. - Verification aborts after 45 seconds so large targets fail gracefully (route
maxDurationis 60s). - A best-effort per-IP rate limit applies in memory. On multi-instance hosts the counters are not shared — wait and retry if you hit 429.
- Results are not stored. Each run is downloaded, analyzed, and discarded.
CLI / MCP
BLOCKis not overridden by--yes, MCPconfirm, orhumanApproved. Override only with the typed acknowledgement phrase (--block-acknowledgement/blockAcknowledgement). Any CRITICAL finding still yieldsBLOCK(advice); capability presence likeevalis HIGH → review gate.- All declared ecosystems (
pip,uv,cargo,go,docker,git) acquire and verify. Docker inspects registry metadata, samples small text layers when possible, and never runs the image. - Skill / agent-rules / zip installs use safe-copy or guarded extract. Skills default to
SENTINEL_SKILLS_DIRor~/.agents/skills; rules default under the workspace (.agents/rulesor an existing vendor rules dir). - Report formats include terminal, JSON, Markdown, SARIF, and CycloneDX SBOM (
--sbom). Install--jsonreturns{ success, message, report }. - ZIP and VSIX extraction rejects traversal and symlink entries and enforces file-count and expanded-size limits.
- Test/fixture files use a narrower ruleset by default. Pass
--score-teststo apply the full production ruleset.