Please report security vulnerabilities privately rather than filing a public GitHub issue. Email the Praglogic security team at aejaz.sheriff@pragmaticlogic.ai with the following, if known:
- A description of the issue and its impact.
- Steps to reproduce, or a proof-of-concept.
- The affected version (
package.jsonversionfield). - Any mitigating factors you are aware of.
We aim to acknowledge reports within two business days and to publish a coordinated fix with credit (unless you request anonymity) within a reasonable window agreed with the reporter.
Security fixes are issued against the most recent minor release. Older minors are supported for 90 days after a new minor ships.
| Version | Supported |
|---|---|
| 4.0.x | ✅ |
| 3.7.x | ✅ (until 2026-08-25) |
| 3.6.x | ✅ (until 2026-07-21) |
| ≤ 3.5.x | ❌ |
EmbedIQ is a local, deterministic configuration generator. Its security posture leans on three load-bearing design properties:
- Zero-persistence by default. The wizard runs entirely in-process; answers live in volatile memory unless the operator opts in to a server-side session backend. No database, no telemetry, no external service calls.
- No LLM dependency in the hot path. All output is produced by pure
TypeScript generators. No network requests, no vector databases, no
prompt-injection surface.
/init-style LLM-powered alternatives cannot offer the same audit guarantees. - Air-gap compatible. The CLI runs offline end-to-end. The web server also runs offline; the only outbound traffic is optional and opt-in (OpenTelemetry export, git PR integration, outbound webhooks).
| Threat | Mitigation |
|---|---|
| Sensitive data leaked into generated config (PHI, PCI, secrets) | HooksGenerator emits Python DLP scanners that run before every Claude Code tool call. Patterns come from the domain pack (e.g. MRN / ICD-10 / FHIR for healthcare, PAN / CVV / ABA for finance). Validator rejects generated output missing the expected DLP patterns for the active compliance framework. |
| Unauthorized access to the web wizard | Pluggable auth via EMBEDIQ_AUTH_STRATEGY (Basic, OIDC, reverse-proxy header, demo). Three-tier RBAC: wizard-viewer < wizard-user ≡ wizard-contributor < wizard-admin (legacy wizard-user preserved as a contributor-tier alias). Generation, session list, and session dump endpoints require wizard-admin. The demo strategy is admin/user persona-switching for demo recordings — permissive at the middleware level, never for production. |
| Session hijack | Server-side sessions are optional. When enabled, each session is bound to the authenticated user (when auth is on) or to a signed HTTP-only cookie token (embediq_session_owner, HMAC-signed with EMBEDIQ_SESSION_COOKIE_SECRET). Mismatched owners return 403. Optional AES-256-GCM payload encryption via EMBEDIQ_SESSION_DATA_KEY. |
| Forged answer attribution | SerializedAnswer.contributedBy is stamped server-side from the request context on every PATCH /api/sessions/:id. Any contributedBy value in the request body is stripped. Compliance reviewers can prove who provided each answer. |
| Forged autopilot webhook | Autopilot and compliance webhooks optionally require a shared secret via EMBEDIQ_AUTOPILOT_WEBHOOK_SECRET, validated against the X-EmbedIQ-Autopilot-Secret header. |
| Malicious external domain pack / skill | External packs and skills are loaded from user-configured directories (EMBEDIQ_PLUGINS_DIR, EMBEDIQ_SKILLS_DIR). Operators should treat these the same way they treat any node_modules dependency: audit before enabling. EmbedIQ never auto-downloads either. |
| Destructive shell execution via hooks | The built-in command-guard.py hook blocks destructive verbs (rm -rf, git push --force, git reset --hard) unless the user confirms. Strict/lockdown permission tiers add denies for entire tool categories. |
| Output drift silently corrupting production | npm run drift compares a project against expected output. CI can fail builds on detected drift (exit code 1). Autopilot runs the same check on a schedule and records every outcome. |
| Leaking strategic / internal content to the public surface | Every markdown file declares an audience directive (`<!-- audience: public |
| Supply-chain tampering in generated files | Each generated file carries a stamp (`Generated by EmbedIQ v |
| Surface | Enable via | What lands on disk |
|---|---|---|
| Wizard audit trail | EMBEDIQ_AUDIT_LOG=/path/to/log.jsonl |
JSONL: eventType, timestamp, userId?, requestId?, profileSummary?, validationPassed?, fileCount?. No answers, no generated file content. |
| Server-side sessions | EMBEDIQ_SESSION_BACKEND=json-file or database |
WizardSession records (answers + phase + contributors) under EMBEDIQ_SESSION_DIR (json-file) or at EMBEDIQ_SESSION_DB_URL (database + sqlite driver). AES-256-GCM optional via EMBEDIQ_SESSION_DATA_KEY. |
| Autopilot schedules + runs | EMBEDIQ_AUTOPILOT_ENABLED=true |
Schedule definitions + the last 500 run records under EMBEDIQ_AUTOPILOT_DIR (default .embediq/autopilot/). |
| OpenTelemetry traces + metrics | EMBEDIQ_OTEL_ENABLED=true |
Exported via OTLP HTTP to OTEL_EXPORTER_OTLP_ENDPOINT. Traces contain request IDs and user IDs; no question answers. |
- Answer values never leave the process unless a session backend is enabled.
- No LLM prompts or completions (there are no LLM calls).
- No telemetry to Praglogic — the project has no phone-home.
Output files land in the user-supplied targetDir. EmbedIQ writes only
to the managed subtrees listed in docs/reference/generated-files.md;
files outside those paths are never touched.
Built-in domain packs configure enforcement for the frameworks below. See
docs/user-guide/04-domain-packs.md for what each pack configures and
docs/evaluators/threat-coverage.md for our framework-by-framework
coverage report.
- Healthcare: HIPAA, HITECH, 42 CFR Part 2
- Finance: PCI-DSS, SOX, GLBA, AML/BSA, FINRA
- Education: FERPA, COPPA, state student-privacy laws
- AI governance (cross-industry): NIST AI RMF 1.0, NIST AI 600-1 GenAI Profile
- Federal (via OSCAL ingestion): NIST 800-53 Rev 5, FedRAMP Low / Moderate / High baselines
- Runtime dependencies are pinned in
package.jsonand locked inpackage-lock.json. npm auditruns as part of the release checklist.- Optional dependencies (
@opentelemetry/*,better-sqlite3) load viaimport()at runtime; EmbedIQ degrades gracefully when they are not installed.
- Session payload encryption: AES-256-GCM (Node
cryptostandard library). Key: 32 bytes, hex-encoded (64 hex chars), supplied viaEMBEDIQ_SESSION_DATA_KEY. Side-by-side key acceptance for zero-downtime rotation: setEMBEDIQ_SESSION_DATA_KEY_PREVto the prior key; reads accept both, writes use the current key (shipped v3.6.1). - Audit log integrity (optional): RFC-6962-pattern hash chain via
EMBEDIQ_AUDIT_CHAIN_ENABLED=true. Each appended JSONL entry carriesprevHash(SHA-256 of the prior entry's canonicalized content); tampering breaks the chain at the modified line. Offline verifier:make verify-audit-log INPUT=path/to/audit.jsonl(exit codes 0 / 1 / 2). - Owner-token cookies: HMAC-SHA-256 over a URL-safe base64 random
token. Key: 32 bytes, supplied via
EMBEDIQ_SESSION_COOKIE_SECRET. Both current and previous keys may be supplied (_PREVsuffix) for zero-downtime rotation. - No bespoke crypto primitives. No custom KDFs. No rolled implementations.