registry  /  fullstackgtm  /  0.47.0

fullstackgtm@0.47.0

Open-source agentic GTM ops framework: canonical GTM data model, pluggable deterministic audits, reviewable dry-run patch plans, approval-gated write-back with conflict detection, and cross-system entity resolution. HubSpot, Salesforce, and Stripe connect

AI Security Review

scanned 3d ago · by lpm-firewall-ai

No confirmed malicious attack surface. Network, credential storage, dynamic imports, and timer writes are user-invoked product features with validation and package-aligned endpoints.

Static reason
One or more suspicious static signals were detected.; previous stored version diff introduced dangerous source
Trigger
Explicit CLI commands such as login, schedule install, configured audits, or paired run reporting.
Impact
No unconsented install-time execution, exfiltration, destructive behavior, or foreign AI-agent control mutation found.
Mechanism
User-invoked GTM CLI integrations and local scheduling.
Rationale
Static inspection found suspicious primitives, but they are activated by explicit CLI workflows and are constrained to the package's GTM/OAuth/scheduling functionality. There is no lifecycle install hook, stealth persistence, credential harvesting beyond user login storage, or unconsented exfiltration path.
Evidence
package.jsondist/bin.jsdist/cli/auth.jsdist/runReport.jsdist/cli/schedule.jsdist/schedule.jsdist/config.jsdist/credentials.js~/.fullstackgtm/credentials.json~/.fullstackgtm/schedules.json~/Library/LaunchAgents/com.fullstackgtm.<profile>.<id>.plistuser crontab
Network endpoints5
app.fullstackgtm.comapi.stripe.com/v1/customers?limit=1api.apollo.io/api/v1/auth/healthapi.openai.com/v1/chat/completionsapi.anthropic.com/v1/messages

Decision evidence

public snapshot
AI called this Clean at 86.0% confidence as Benign with low false-positive risk.
Evidence for block
  • dist/cli/auth.js sends hostname/platform/username as requesterLabel to hosted FullStackGTM during explicit login/pairing.
  • dist/cli/schedule.js can install user timers into crontab or ~/Library/LaunchAgents via explicit schedule install.
  • dist/config.js dynamically imports user-configured rulePackages from fullstackgtm.config.json.
Evidence against
  • package.json has no preinstall/install/postinstall hook; only prepublishOnly build checks.
  • dist/bin.js only dispatches CLI args; reporting is skipped unless a broker credential already exists.
  • dist/runReport.js is opt-in paired observability to broker.baseUrl and returns when unpaired.
  • dist/schedule.js validates schedulable argv, rejects control chars, avoids shell dispatch, and gates scheduled apply on approved plans.
  • dist/cli/auth.js stores user-entered credentials locally and validates against package-aligned provider APIs.
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsFilesystemNetworkShell
Supply chain
HighEntropyStringsUrlStrings
ManifestNo manifest risk signals triggered.
scanned 178 file(s), 2.65 MB of source, external domains: api.anthropic.com, api.apollo.io, api.ashbyhq.com, api.explorium.ai, api.heyreach.io, api.hubapi.com, api.lever.co, api.openai.com, api.pipe0.com, api.stripe.com, api.theirstack.com, app.fullstackgtm.com, app.hubspot.com, boards-api.greenhouse.io, example.com, github.com, gtm.example.com, gtm.yourco.com, login.salesforce.com, schemas.xmlsoap.org, serpapi.com, www.apple.com, www.google.com, yourco.my.salesforce.com, yourorg.my.salesforce.com

Source & flagged code

5 flagged · loading source
dist/config.jsView file
59: specifier; L60: const rulePackage = await import(__rewriteRelativeImportExtension(resolvedSpecifier)); L61: const imported = rulePackage.rules ?? rulePackage.default?.rules;
Medium
Dynamic Require

Package source references dynamic require/import behavior.

dist/config.jsView on unpkg · L59
dist/cli/schedule.jsView file
6import { createFileEnrichRunStore } from "../enrich.js"; L7: import { computeMissedFirings, createFileScheduleRunStore, createFileScheduleStore, installLaunchdAgents, isDuplicateCronFiring, nextCronFiring, parseCron, renderManagedBlock, repl... L8: import { runCli } from "../cli.js"; ... L58: L59: run executes the command in-process and records the outcome (exit code, L60: output tail, artifacts: plan ids / enrich run labels) under the profile's ... L173: const { installed } = installLaunchdAgents(profile, enabled, scheduleCliArgv(), io, { L174: environment: process.env.FSGTM_HOME ? { FSGTM_HOME: process.env.FSGTM_HOME } : undefined, L175: logDir, ... L184: if (subcommand === "uninstall") { L185: io.write(replaceManagedBlock(existing, profile, null)); L186: console.log(`Removed the fullstackgtm managed crontab block for profile "${profile}" (lines outside the sentinels untouched).`);
Medium
Install Persistence

Source writes installer persistence such as shell profile or service configuration.

dist/cli/schedule.jsView on unpkg · L6
dist/cli/auth.jsView file
30* minted live-CRM tokens, so it must be TLS unless it's an explicit localhost L31: * dev target. Refuse http:// (and non-http schemes) otherwise — single-quote L32: * shell escaping does nothing for a token sent in cleartext. ... L56: // and refuse one they didn't initiate. L57: const requesterLabel = `${os.hostname()} (${process.platform}, ${os.userInfo().username})`; L58: let startResponse; ... L62: headers: { "Content-Type": "application/json" }, L63: body: JSON.stringify({ requesterLabel }), L64: }); ... L72: } L73: const start = await startResponse.json(); L74: // Only auto-open a verification URL that belongs to the --via origin the user
High
Host Fingerprint Exfiltration

Source collects local host identity data and sends it to an external endpoint.

dist/cli/auth.jsView on unpkg · L30
30* minted live-CRM tokens, so it must be TLS unless it's an explicit localhost L31: * dev target. Refuse http:// (and non-http schemes) otherwise — single-quote L32: * shell escaping does nothing for a token sent in cleartext. ... L56: // and refuse one they didn't initiate. L57: const requesterLabel = `${os.hostname()} (${process.platform}, ${os.userInfo().username})`; L58: let startResponse; ... L62: headers: { "Content-Type": "application/json" }, L63: body: JSON.stringify({ requesterLabel }), L64: }); ... L72: } L73: const start = await startResponse.json(); L74: // Only auto-open a verification URL that belongs to the --via origin the user
High
Sandbox Evasion Gated Capability

Source gates dangerous network, credential, or execution behavior behind CI, host, platform, time, or geo fingerprint checks.

dist/cli/auth.jsView on unpkg · L30
dist/schedule.jsView file
matchType = previous_version_dangerous_delta matchedPackage = fullstackgtm@0.44.0 matchedIdentity = npm:ZnVsbHN0YWNrZ3Rt:0.44.0 similarity = 0.383 summary = stored previous version shares package body but lacks this dangerous source file
Critical
Previous Version Dangerous Delta

This package version adds a dangerous source file absent from the previous stored version; route for source-aware review.

dist/schedule.jsView on unpkg

Findings

1 Critical2 High5 Medium5 Low
CriticalPrevious Version Dangerous Deltadist/schedule.js
HighHost Fingerprint Exfiltrationdist/cli/auth.js
HighSandbox Evasion Gated Capabilitydist/cli/auth.js
MediumDynamic Requiredist/config.js
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencedist/cli/schedule.js
MediumStructural Risk Force Deep Review
LowNon Install Lifecycle Scripts
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings