Parse a security questionnaire — SIG, CAIQ, VSA, VSAQ, or a bespoke one — from
.xlsx, .docx, .pdf, or .csv into structured JSON: a normalized list of
questions plus the detected framework(s), with evidence and confidence.
Ingest and normalize only. This library extracts and classifies questions. It does not answer them, auto-fill responses, rank answers, or ship an answer library — by design. It's the parsing primitive, nothing more.
npm install questionnaire-parsernpx qparse ./SIG-Core-2025.xlsx --pretty
npx qparse ./caiq.xlsx --questions-only > questions.jsonimport { parseFile } from "questionnaire-parser";
const result = await parseFile("./caiq-v4.xlsx");
result.meta.questionCount; // 261
result.primaryFramework?.name; // "CAIQ v4 (CSA Cloud Controls Matrix)"
result.primaryFramework?.confidence; // "high"
result.questions[0]; // { id: "IAM-14", text: "Is MFA enforced…", section: "Identity & Access Management" }Parse an in-memory buffer (e.g. a browser upload passed to a server) instead:
import { parseBuffer } from "questionnaire-parser";
const result = await parseBuffer(buffer, "xlsx", "upload.xlsx");Or run the pure core directly on rows/text you've already extracted:
import { extractFromRows, detectFrameworks, pickPrimary } from "questionnaire-parser";
const questions = extractFromRows(rows, "Sheet1");
const frameworks = detectFrameworks(questions, rawText, sheetNames);
const primary = pickPrimary(frameworks); // null when bespoke/ambiguousOne generic scorer runs over a table of framework fingerprints (control-ID grammar, header/tab strings, approximate size). There is no per-framework code branch — adding a framework is a data entry, not a new code path. ID grammar and header text dominate; question count is only a weak tiebreaker. SOC 2 and ISO 27001 are treated as cross-maps (they often appear inside another questionnaire) and are down-weighted for primary selection.
Supported fingerprints: CAIQ (CSA CCM), SIG (Shared Assessments), SOC 2, ISO 27001, Google VSAQ, Vendor Security Alliance (VSA).
npm install
npm test # runs the core tests (node:test via tsx)
npm run build # emits dist/ (ESM + types)MIT. Framework names and control-ID grammars are referenced for interoperability and belong to their respective publishers (CSA, Shared Assessments, AICPA, ISO, NIST, Google).
{ "questions": [ { "id": "IAM-14", "text": "Is MFA enforced for privileged access?", "section": "Identity & Access Management" } ], "frameworks": [ { "framework": "caiq", "name": "CAIQ v4 (CSA Cloud Controls Matrix)", "confidence": "high", "evidence": ["43 control IDs match the CAIQ v4 grammar", "title/header text: \"caiq\""], "matchedIdCount": 43, "source": "CSA Cloud Controls Matrix / CAIQ v4 (cloudsecurityalliance.org)", "score": 133 } ], "primaryFramework": { "framework": "caiq", "...": "..." }, "meta": { "file": "caiq-v4.xlsx", "format": "xlsx", "questionCount": 261 } }