Loading npm security reports…
suppa-mcp-2@1.42.5: Agent extension lifecycle risk – flagged | LPM Firewall
Flagged as agent extension risk
Allowed by default with warning: install-time first-party agent extension setup was detected.
suppa-mcp-2@1.42.5 MCP server for the Suppa platform (modern.suppa.me) — Tasks, Docs/Pages, Entities & Schema, Forms, Automations, and file attachments, with multi-tenant Google auth. Node port of PyPI suppa-mcp.
AI Security Reviewscanned 12d ago · by lpm-firewall-ai The postinstall hook conditionally installs first-party agent guard configuration in matching Suppa projects. This warrants a warning for guarded agent extension lifecycle risk, but the inspected source does not establish a concrete attack or support blocking publication.
Static reason
One or more suspicious static signals were detected.; source matched previously finalized malicious package; routed for review; previous stored version diff introduced dangerous source
Trigger
Installing the package in a repository containing Suppa schema code or an @suppa dependency, unless an exclusion applies.
Impact
The project receives automatic agent hooks and instructions that run or guide entity-code validation.
Mechanism
The postinstall script invokes the bundled installer, which configures Claude Code hooks and writes managed sections to AGENTS.md and CLAUDE.md.
AI rationale
The postinstall hook conditionally installs first-party agent guard configuration in matching Suppa projects. This warrants a warning for guarded agent extension lifecycle risk, but the inspected source does not establish a concrete attack or support blocking publication.
Evidence
.claude/settings.json AGENTS.md CLAUDE.md
Decision evidencepublic snapshot AI called this Suspicious at 88.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for warning
The manifest runs a postinstall script during installation. The postinstall script can invoke the guard installer for a matching Suppa application. The installer configures Claude Code settings and adds instructions to AGENTS.md and CLAUDE.md. The setup is limited to repositories with Suppa schema code or an @suppa dependency, and skips this package's own install. Evidence against
The installer is a package-provided entity-code guard setup, and the postinstall checks for a matching application before invoking it. No source evidence inspected showed credential theft, unrelated payload execution, or destructive behavior. Behavioral surface
Source ChildProcess Crypto DynamicRequire EnvironmentVars Eval Filesystem Network
Supply chain HighEntropyStrings Minified PossibleObfuscation UrlStrings
Source & flagged code10 flagged · loading source • scripts.postinstall = node skills/suppa-entity-code/scripts/postinstall.mjs
High Install Time Lifecycle Scripts
Package defines install-time lifecycle scripts.
package.json View on unpkg • scripts.postinstall = node skills/suppa-entity-code/scripts/postinstall.mjs
Medium Ambiguous Install Lifecycle Script
Install-time lifecycle script is not statically allowlisted and needs review.
package.json View on unpkg skills/suppa-form-v2/scripts/vue-compiler-diagnostics.mjs View file 9 `,-1),e.hoists.length)){let f=[At,Ct,Xe,Rt,Cn].filter(h=>p.includes(h)).map(Wn).join(", ");i(`const { ${f} } = _Vue
L10: `,-1)}Ni(e.hoists,t),r(),i("return ")}function Et(e,t,{helper:n,push:s,newline:i,isTS:r}){let o=n(t==="filter"?Pt:t==="component"?Dt:Lt);for(let a=0;a<e.length;a++){let l=e[a],c=l....
L11: /*! Bundled license information:
Findings7 High 5 Medium 6 Low
High Install Time Lifecycle Scripts package.json
High Entrypoint Foreign Package Code Overwrite dist/version.js
High Sandbox Evasion Gated Capability dist/config.js
High Semantic Analysis Limited dist/selfcheck.js#virtual:normalized:round1
High Known Malware Source Similarity skills/suppa-entity-code/scripts/validate-suppa-schema.mjs
High Known Malware Source Similarity dist/selfcheck.js
High Previous Version Dangerous Delta dist/auth.js
Medium Ambiguous Install Lifecycle Script package.json
Medium Dynamic Require dist/tools/entityCode.js
Medium Network
Medium Environment Vars
Medium Structural Risk Force Deep Review
Affected versions and remediation This report applies to suppa-mcp-2@1.42.5 .
See all versions of suppa-mcp-2 for other recorded verdicts.
Review the evidence and your use of suppa-mcp-2@1.42.5 before allowing it. Restrict the permissions described in this report. Choose an independently verified alternative or release. This report does not establish that other versions are safe. Evidence last updated: 2026-10-11 12:35:36.749Z (UTC) .
Think this verdict is wrong? Dispute it on GitHub or read how reports are produced .
Manifest No manifest risk signals triggered.
scanned 64 file(s), 2.46 MB of source, external domains: accounts.google.com, blocked.invalid, modern.suppa.me, registry.npmjs.org, service.example.com, sp.modern-expo.com, v3-migration.vuejs.org, vuejs.org
Eval
Package source references a known benign dynamic code generation pattern.
skills/suppa-form-v2/scripts/vue-compiler-diagnostics.mjs View on unpkg · L9 81 try {
L82: const mod = await import(pathToFileURL(p).href);
L83: return String(mod.BLOCKING_SUMMARY ?? "").trim() || "the house rules in SKILL.md";
Medium Dynamic Require
Package source references dynamic require/import behavior.
dist/tools/entityCode.js View on unpkg · L81 • Manifest-reachable source resolves another installed package, overwrites its runtime code, and injects package-defined remote behavior.
dist/version.js:
* node_modules holds; publishing a fix changes nothing until that client is
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
const REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
writeFileSync(tmp, `${JSON.stringify(cache, null, 2)}\n`, "utf-8");
High Entrypoint Foreign Package Code Overwrite
Manifest-reachable source overwrites another installed package with package-defined remote behavior.
dist/version.js View on unpkg 17 const candidates = [];
L18: const cwd = process.cwd();
L19: // cwd, then every parent up to the filesystem root (mirrors Path.cwd().parents).
...
L30: // this is Path(__file__).resolve().parent.parent.parent; here we walk up from
L31: // the compiled module location to the package root (the dir with package.json).
L32: const packageRoot = findPackageRoot(dirname(fileURLToPath(import.meta.url)));
...
L79: value = stripQuotes(value);
L80: if (key.startsWith("SUPPA_") && !(key in process.env)) {
L81: process.env[key] = value;
...
L115: loadDotenv();
L116: const BASE_URL = (process.env.SUPPA_BASE_URL || "https://modern.suppa.me").replace(/\/+$/, "");
L117: const API_KEY = process.env.SUPPA_API_KEY || process.env.SUPPA_TOKEN || "";
High Sandbox Evasion Gated Capability
Source gates dangerous network, credential, or execution behavior behind CI, host, platform, time, or geo fingerprint checks.
dist/config.js View on unpkg · L17 dist/selfcheck.js#virtual:normalized:round1 View file • stage = ast_semantic_analysis; reason = ast_parse_error; limitedFiles = 9
High Semantic Analysis Limited
A bounded semantic-analysis stage reached its safety limit; remaining detectors completed, but this package requires AI review.
dist/selfcheck.js#virtual:normalized:round1 View on unpkg skills/suppa-entity-code/scripts/validate-suppa-schema.mjs View file • matchType = normalized_sha256
matchedPackage = suppa-mcp-2@1.41.0
matchedPath = skills/suppa-entity-code/scripts/validate-suppa-schema.mjs
matchedIdentity = npm:c3VwcGEtbWNwLTI:1.41.0
similarity = 1.000
summary = normalized source hash matched finalized malicious source
High Known Malware Source Similarity
Source file is highly similar to a previously finalized malicious package; route for source-aware review.
skills/suppa-entity-code/scripts/validate-suppa-schema.mjs View on unpkg • matchType = normalized_sha256
matchedPackage = suppa-mcp-2@1.40.6
matchedPath = dist/selfcheck.js
matchedIdentity = npm:c3VwcGEtbWNwLTI:1.40.6
similarity = 1.000
summary = normalized source hash matched finalized malicious source
High Known Malware Source Similarity
Source file is highly similar to a previously finalized malicious package; route for source-aware review.
dist/selfcheck.js View on unpkg • matchType = previous_version_dangerous_delta
matchedPackage = suppa-mcp-2@1.42.1
matchedIdentity = npm:c3VwcGEtbWNwLTI:1.42.1
similarity = 0.938
summary = stored previous version shares package body but lacks this dangerous source file
High Previous Version Dangerous Delta
This package version adds a dangerous source file absent from the previous stored version; route for source-aware review.
dist/auth.js View on unpkg Low Non Install Lifecycle Scripts
Low Eval skills/suppa-form-v2/scripts/vue-compiler-diagnostics.mjs
Entrypoints main → dist/bin.js bin → suppa, suppa-entity-guards, suppa-mcp +1
Runtime node >=18
Artifact 2.94 MB · 114 files 2 signature(s)
Install lifecycle postinstall prepublishOnly
Behavioral surface ChildProcess Crypto DynamicRequire EnvironmentVars Eval Filesystem Network HighEntropyStrings Minified PossibleObfuscation UrlStrings Manifest: clean
Source & flagged code10 flagged Lines 9-49 json
9 "suppa" : "dist/cliBin.js" ,
10 "suppa-entity-guards" : "skills/suppa-entity-code/scripts/install-entity-code-guards.mjs"
12 "main" : "dist/bin.js" ,
24 "clean" : "node -e \" require('fs').rmSync('dist',{recursive:true,force:true}) \" " ,
25 "rebuild" : "npm run clean && npm run build" ,
26 "start" : "node dist/bin.js" ,
28 "test" : "node scripts/check-version-literals.mjs && vitest run" ,
29 "postinstall" : "node skills/suppa-entity-code/scripts/postinstall.mjs" ,
High Install Time Lifecycle Scripts
Package defines install-time lifecycle scripts.
package.json View on unpkg · L29 Medium Ambiguous Install Lifecycle Script
Install-time lifecycle script is not statically allowlisted and needs review.
package.json View on unpkg · L29 30 "test:watch" : "vitest" ,
31 "prepublishOnly" : "npm run rebuild && npm test" ,
32 "inspect" : "npx @modelcontextprotocol/inspector node dist/bin.js" ,
33 "live:install" : "node scripts/live-install.mjs" ,
34 "live:verify" : "node scripts/verify-live-install.mjs" ,
35 "schema:gate" : "node skills/suppa-entity-code/scripts/entity-code-guard.mjs --ci ." ,
36 "form:gate" : "node skills/suppa-form-v2/scripts/validate-form-schema.mjs" ,
37 "sync:formbuilder" : "node scripts/sync-formbuilder.mjs" ,
38 "sync:vue-compiler" : "node scripts/sync-vue-compiler.mjs" ,
39 "guards:install" : "node skills/suppa-entity-code/scripts/install-entity-code-guards.mjs"
43 "model-context-protocol" ,
skills/suppa-form-v2/scripts/vue-compiler-diagnostics.mjs View file Lines 1-29 javascript
1 // @vue/compiler-dom 3.5.12, esm-bundler build, NODE_ENV=development (MIT, (c) Evan You and Vue contributors), bundled by scripts/sync-vue-compiler.mjs. Do not edit.
2 function J ( e ){ let t = Object. create ( null ); for ( let n of e. split ( "," ))t[n]
• Manifest-reachable source resolves another installed package, overwrites its runtime code, and injects package-defined remote behavior.
dist/version.js:
* node_modules holds; publishing a fix changes nothing until that client is
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
const REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
writeFileSync(tmp, `${JSON.stringify(cache, null, 2)}\n`, "utf-8");
High Entrypoint Foreign Package Code Overwrite
Manifest-reachable source overwrites another installed package with package-defined remote behavior.
dist/version.js View on unpkg Lines 1-37 javascript
2 * Configuration loaded from environment variables or .env file.
4 * Faithful 1:1 port of the Python `suppa_mcp/config.py`.
6 import { existsSync, readFileSync, statSync } from "node:fs" ;
7 import { dirname, join, resolve } from "node:path" ;
dist/selfcheck.js#virtual:normalized:round1 View file • stage = ast_semantic_analysis; reason = ast_parse_error; limitedFiles = 9
High Semantic Analysis Limited
A bounded semantic-analysis stage reached its safety limit; remaining detectors completed, but this package requires AI review.
dist/selfcheck.js#virtual:normalized:round1 View on unpkg skills/suppa-entity-code/scripts/validate-suppa-schema.mjs View file • matchType = normalized_sha256
matchedPackage = suppa-mcp-2@1.41.0
matchedPath = skills/suppa-entity-code/scripts/validate-suppa-schema.mjs
matchedIdentity = npm:c3VwcGEtbWNwLTI:1.41.0
similarity = 1.000
summary = normalized source hash matched finalized malicious source
High Known Malware Source Similarity
Source file is highly similar to a previously finalized malicious package; route for source-aware review.
skills/suppa-entity-code/scripts/validate-suppa-schema.mjs View on unpkg • matchType = normalized_sha256
matchedPackage = suppa-mcp-2@1.40.6
matchedPath = dist/selfcheck.js
matchedIdentity = npm:c3VwcGEtbWNwLTI:1.40.6
similarity = 1.000
summary = normalized source hash matched finalized malicious source
High Known Malware Source Similarity
Source file is highly similar to a previously finalized malicious package; route for source-aware review.
dist/selfcheck.js View on unpkg • matchType = previous_version_dangerous_delta
matchedPackage = suppa-mcp-2@1.42.1
matchedIdentity = npm:c3VwcGEtbWNwLTI:1.42.1
similarity = 0.938
summary = stored previous version shares package body but lacks this dangerous source file
High Previous Version Dangerous Delta
This package version adds a dangerous source file absent from the previous stored version; route for source-aware review.
dist/auth.js View on unpkg =
1
;
return
n
=>
n
in
t}
var
zt
=
Object.
freeze
({}),Cr
=
Object.
freeze
([]),
je
=
()
=>
{},
Me
=
()
=>!
1
,
Ke
=
e
=>
e.
charCodeAt
(
0
)
===
111
&&
e.
charCodeAt
(
1
)
===
110
&&
(e.
charCodeAt
(
2
)
>
122
||
e.
charCodeAt
(
2
)
<
97
);
var
ee
=
Object.assign;
var
te
=
Array.isArray;
var
w
=
e
=>typeof
e
==
"string"
,
qe
=
e
=>typeof
e
==
"symbol"
,
Qt
=
e
=>
e
!==
null
&&typeof
e
==
"object"
;
var
ht
=
J
(
",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"
),Zt
=
J
(
"bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,m ..
.
3 Details: ${o} `:""}` ,l =new SyntaxError (a);l.code = e,n && (l.loc = n),t. onWarn (l)} function Ht ( e ){ throw e} function Pn ( e ){console. warn ( `[Vue warn] ${ e . message }` )} function b ( e , t , n , s ){ let i = (n || Us)[e] + (s || "" ),r =new SyntaxError ( String (i)); return r.code = e,r.loc = t,r}var Us = { 0 : "Illegal comment." , 1 : "CDATA section is allowed only in XML context." , 2 : "Duplicate attribute." , 3 : "End tag cannot have attributes." , 4 : "Illegal '/' in tags." , 5 : "Unexpected EOF in tag." , 6 : "Unexpected EOF in CDATA section." , 7 : "Unexpected EOF in comment." , 8 : "Unexpected EOF in script." , 9 : "Unexpected EOF in tag." , 10 : "Incorrectly closed comme .. .
4 Use a v - bind binding combined with a v - on listener that emits update:x event instead. `,45:"Error parsing JavaScript expression: ",46:"<KeepAlive> expects exactly one child component.",51:"@vnode-* hooks in templates are no longer supported. Use the vue: prefix instead. For example, @vnode-mounted should be changed to @vue:mounted. @vnode-* hooks support has been removed in 3.4.",47:'"prefixIdentifiers" option is not supported in this build of compiler.',48:"ES module mode is not supported in this build of compiler.",49:'"cacheHandlers" option is only supported when the "prefixIdentifiers" opti ...
5 ` );else if ( ri (r.content)){let o = e[i - 1 ] && e[i - 1 ].type,a = e[i + 1 ] && e[i + 1 ].type; ! o ||! a || n && (o === 3 && (a === 3 || a === 1 ) || o === 1 && (a === 3 || a === 1 && oi (r.content))) ? (s =! 0 ,e[i] = null ) : r.content = " " }else n && (r.content = Hn (r.content))}return s ? e. filter (Boolean) : e} function ri ( e ){ for ( let t = 0 ;t < e. length ;t ++ ) if ( ! Y (e. charCodeAt (t))) return! 1 ; return! 0 } function oi ( e ){ for ( let t = 0 ;t < e. length ;t ++ ){ let n = e. charCodeAt (t); if (n === 10 || n === 13 ) return! 0 } return! 1 } function Hn ( e ){ let t = "" ,n =! 1 ; for ( let s = 0 ;s < e. length ;s ++ ) Y (e. charCodeAt (s)) ? n || (t += " " ,n =! 0 ) : (t += e[s],n =! 1 ); return t} function Ot ( e ){( D [ 0 ] || Ue).children. push (e)} function P ( e , t ){ ...
6 `+" ".repeat(m),0)}return u}function _i(e,t={}){let n=mi(e,t);t.onContextCreated&&t.onContextCreated(n);let{mode:s,push:i,prefixIdentifiers:r,indent:o,deindent:a,newline:l,scopeId:c,ssr:p}=n,f=Array.from(e.helpers),h=f.length>0,u=!r&&s!=="module";gi(e,n);let m=p?"ssrRender":"render",_=(p?["_ctx","_push","_parent","_attrs"]:["_ctx","_cache"]).join(", ");if(i(` function $ {m}(${_}) { `),o(),u&&(i("with (_ctx) {"),o(),h&&(i(` const { $ { f . map ( Wn ). join (", ")} } = _Vue
7 `,-1),l())),e.components.length&&(Et(e.components,"component",n),(e.directives.length||e.temps>0)&&l()),e.directives.length&&(Et(e.directives,"directive",n),e.temps>0&&l()),e.filters&&e.filters.length&&(l(),Et(e.filters,"filter",n),l()),e.temps>0){i("let ");for(let A=0;A<e.temps;A++)i(` ${ A > 0 ? ", " : "" }_temp${ A } `)}return(e.components.length||e.directives.length||e.temps)&&(i(`
8 `,0),l()),p||i("return "),e.codegenNode?B(e.codegenNode,n):i("null"),u&&(a(),i("}")),a(),i("}"),{ast:e,code:n.code,preamble:"",map:n.map?n.map.toJSON():void 0}}function gi(e,t){let{ssr:n,prefixIdentifiers:s,push:i,newline:r,runtimeModuleName:o,runtimeGlobalName:a,ssrRuntimeModuleName:l}=t,c=a,p=Array.from(e.helpers);if(p.length>0&&(i(` const _Vue = ${c}
9 `,-1),e.hoists.length)){let f=[At,Ct,Xe,Rt,Cn].filter(h=>p.includes(h)).map(Wn).join(", ");i(` const { $ { f } } = _Vue
10 `,-1)}Ni(e.hoists,t),r(),i("return ")}function Et(e,t,{helper:n,push:s,newline:i,isTS:r}){let o=n(t==="filter"?Pt:t==="component"?Dt:Lt);for(let a=0;a<e.length;a++){let l=e[a],c=l.endsWith("__self");c&&(l=l.slice(0,-6)),s(` const $ {Fe(l, t )} = ${o}(${JSON.stringify(l)}${c? ", true" : "" })${r ? "!" : "" } `),a<e.length-1&&i()}}function Ni(e,t){if(!e.length)return;t.pure=!0;let{push:n,newline:s}=t;s();for(let i=0;i<e.length;i++){let r=e[i];r&&(n(` const _hoisted_$ {i+1} = `),B(r,t),s())}t.pure=!1}function Si(e){return w(e)||e.type===4||e.type===2||e.type===5||e.type===8}function jt(e,t){let n=e.length>3||e.s ...
11 /*! Bundled license information:
Low Eval
Package source references a known benign dynamic code generation pattern.
skills/suppa-form-v2/scripts/vue-compiler-diagnostics.mjs View on unpkg · L9 13 @vue/shared/dist/shared.esm-bundler.js:
16 * (c) 2018-present Yuxi (Evan) You and Vue contributors
19 (*! #__NO_SIDE_EFFECTS__ *)
21 @vue/compiler-core/dist/compiler-core.esm-bundler.js:
23 * @vue/compiler-core v3.5.12
24 * (c) 2018-present Yuxi (Evan) You and Vue contributors
28 @vue/compiler-dom/dist/compiler-dom.esm-bundler.js:
Long lines were clipped for display.
68 function validatorPath () {
69 return skillScript ( "validate-suppa-schema.mjs" );
72 * What the gate blocks on, read from the file that defines the rules rather than
73 * restated here. A hand-written list understated it: it named four rules while
74 * the checker blocked on seven, so an agent whose run failed on a code the note
75 * never mentioned could reasonably read the failure as advisory.
77 async function blockingSummary () {
78 const p = skillScript ( "house-rules.mjs" );
80 return "the house rules in skills/suppa-entity-code/SKILL.md" ;
82 const mod = await import ( pathToFileURL (p).href);
83 return String (mod. BLOCKING_SUMMARY ?? "" ). trim () || "the house rules in SKILL.md" ;
Medium Dynamic Require
Package source references dynamic require/import behavior.
dist/tools/entityCode.js View on unpkg · L81 86 return "the house rules in skills/suppa-entity-code/SKILL.md" ;
90 * Run the schema gate over an application repo (or a single file).
92 * `path` is an app root — the whole repo is walked, which is also what lets the
93 * unreferenced-enum-name rule speak, since it argues from absence and needs to
94 * see every file that could hold a reference.
97 * Is the validator USABLE, not merely present?
99 * existsSync cannot tell a working checker from a truncated one, and the difference only shows up
100 * when someone runs the gate — measured: a 300-byte validate-suppa-schema.mjs still reported
101 * "present" while the guard refused to run.
import
{ fileURLToPath }
from
"node:url"
;
10 * Return candidate .env locations, in priority order.
12 * Searches the current working directory and every parent up to the
13 * filesystem root, then the packaged project root. This makes the server
14 * work no matter which directory an MCP client launches it from.
16 export function candidateEnvFiles () {
17 const candidates = [];
18 const cwd = process. cwd ();
19 // cwd, then every parent up to the filesystem root (mirrors Path.cwd().parents).
20 let folder = resolve (cwd);
22 candidates. push ( join (folder, ".env" ));
23 const parent = dirname (folder);
24 if (parent === folder) {
25 break ; // reached the filesystem root
29 // Project root relative to this module (…/suppa-mcp-node/.env). In Python
30 // this is Path(__file__).resolve().parent.parent.parent; here we walk up from
31 // the compiled module location to the package root (the dir with package.json).
32 const packageRoot = findPackageRoot ( dirname ( fileURLToPath ( import . meta .url)));
High Sandbox Evasion Gated Capability
Source gates dangerous network, credential, or execution behavior behind CI, host, platform, time, or geo fingerprint checks.
dist/config.js View on unpkg · L17 33 candidates. push ( join (packageRoot, ".env" ));
34 // De-duplicate while preserving order.
35 const seen = new Set ();
37 for ( const c of candidates) {