// npm 패키지
@stelnyx/apigate
Tiny static API surface audit — enumerates HTTP endpoints, classifies auth posture, diffs against OpenAPI specs. Zero network, deterministic, one report.
버전
4
메인테이너
1
라이선스
MIT
최초 publish
2026-05-19
publisher
doceno
tarball
151,755 B
AUTO-PUBLISHED·3개 버전 인덱싱됨·최근 publish: 2026-05-20
// publisher 캠페인by doceno
이 계정에서 catch된 패키지 3건고립된 catch가 아닙니다. 동일 publisher가 2개의 다른 패키지를 추가로 발행했고, 모두 파이프라인이 catch했습니다 — 일회성이 아닌 조직적 캠페인의 형태. 아래 링크는 각 형제 catch의 분석으로 이동합니다.
// offending code· @0.3.0· 3 files flagged
llm: benign · 0.85→ 의심 전송지 없음, 원격 실행 형태 없음 — 1 known-vendor host(s).
- @0.3.0··AUTO-PUBLISHED·publisher: docenoheuristic 55/100static flags 3llm benign (0.85) via ollamanew-publisher:1dknown-actor-target:teampcp:telnyxreads-env-varspublic-github-pushchild-process-spawn
→ 의심 전송지 없음, 원격 실행 형태 없음 — 1 known-vendor host(s).
// offending code· 3 files flaggedpatterns: 3
--- package/apigate.js (excerpt) --- #!/usr/bin/env node import fs from "fs"; import path from "path"; import { fileURLToPath } from "url"; import { loadConfig } from "./lib/config.mjs"; import { buildInventory } from "./lib/inventory.mjs"; import { classifyAll } from "./lib/auth.mjs"; import { diff as specDiff } from "./lib/drift.mjs"; import { computeScore, SCORE_VERSION, bandFromScore } from "./lib/score.mjs"; import { renderHtml, LIMITATIONS } from "./lib/report.mjs"; import { annotateIntentionalPublic, DEFAULT_PUBLIC_AUTH_PATTERNS } from "./lib/heuristics.mjs"; import { resolveGate, parseFailOnFlag } from "./lib/gate.mjs"; import { PARSER_CAPABILITIES, KNOWN_UNRESOLVED_REASONS, RISK_TIER_INFO } from "./lib/capabilities.mjs"; import { annotateRisk } from "./lib/risk.mjs"; import { buildRefDiff } from "./lib/diff.mjs"; import { parseFilter, applyFilter, describeFilter } from "./lib/filter.mjs"; import { explain } from "./lib/explain.mjs"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf-8")); const argv = process.argv.slice(2); if (argv.includes("--version") || argv.includes("-v")) { console.log(pkg.version); process.exit(0); } if (argv.includes("--help") || argv.includes("-h")) { console.log(` ░▒▓█ APIGATE █▓▒░ v${pkg.version} Static API surface audit — Express · Fastify · NestJS · OpenAPI 2/3 Usage: apigate [target] [options] Output: --output-dir <dir> Directory to write report files (defa --- package/package.json (excerpt) --- { "name": "@stelnyx/apigate", "version": "0.3.0", "description": "Tiny static API surface audit — enumerates HTTP endpoints, classifies auth posture, diffs against OpenAPI specs. Zero network, deterministic, one report.", "type": "module", "bin": { "apigate": "apigate.js" }, "main": "apigate.js", "engines": { "node": ">=18" }, "files": [ "apigate.js", "lib/", "README.md", "LICENSE", "SECURITY.md", ".apigate.config.example.json" ], "keywords": [ "api", "audit", "static-analysis", "openapi", "swagger", "express", "fastify", "nestjs", "auth", "ci", "cd", "gate", "devsecops" ], "author": "Stelnyx", "license": "MIT", "repository": { "type": "git", "url": "git+https://github.com/Stelnyx/ApiGate.git" }, "bugs": { "url": "https://github.com/Stelnyx/ApiGate/issues" }, "homepage": "https://github.com/Stelnyx/ApiGate#readme", "publishConfig": { "access": "public", "provenance": true }, "scripts": { "test": "node test/parser-express.mjs && node test/parser-fastify.mjs && node test/parser-nest.mjs && node test/parser-openapi.mjs && node test/auth.mjs && node test/drift.mjs && node test/score.mjs && node test/risk.mjs && node test/diff.mjs && node test/filter.mjs && node test/explain.mjs && node test/config.mjs && node test/gate.mjs && node test/gates.mjs && node test/capabilities.mjs && node test/heuristics.mjs && node test/golden-apigat --- package/lib/diff.mjs (excerpt) --- import fs from "fs"; import os from "os"; import path from "path"; import { execFileSync } from "child_process"; import { normalizePath, normalizeMethod } from "./utils.mjs"; import { buildInventory } from "./inventory.mjs"; import { classifyAll } from "./auth.mjs"; import { annotateIntentionalPublic, DEFAULT_PUBLIC_AUTH_PATTERNS } from "./heuristics.mjs"; import { annotateRisk } from "./risk.mjs"; /** * Ref-diff — compare the current scan to the inventory at a git ref. * * Materialize the base ref via `git worktree add --detach`. Worktrees are * cheap (no clone, no objects copy), preserve the repo's `.git` state, and * give us a real filesystem path for `buildInventory` to walk. * * Determinism: * - Resolve `<ref>` to a full SHA up front and emit `baseSha` in the * report. Two runs against the same ref produce byte-equal diffs even * if the branch tip moves between invocations. * - Worktree dir name uses short_sha so concurrent CI runs on different * refs don't collide. * - Stale worktrees from prior crashes are pruned at start. * - Cleanup runs in a `finally` so partial failures don't leak state. */ const SHORT_SHA_LEN = 8; const WORKTREE_PREFIX = "apigate-diff-"; function git(args, cwd) { // Force-quiet, machine-readable output. Surface stderr on failure. return execFileSync("git", args, { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }).trim(); } export function resolveSha(ref, cwd) { return git(["rev-
