@i4ctime/q-ring 0.15.0 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -1
- package/dist/{chunk-MLBJCPX2.js → chunk-5LFKBZ3Q.js} +62 -7
- package/dist/chunk-5LFKBZ3Q.js.map +1 -0
- package/dist/{chunk-TPPPTL4J.js → chunk-NCM5GHNW.js} +62 -7
- package/dist/chunk-NCM5GHNW.js.map +1 -0
- package/dist/{dashboard-T2UG23KI.js → dashboard-A3GJQCJX.js} +2 -2
- package/dist/{dashboard-TFWCG23R.js → dashboard-R3FWTFFW.js} +2 -2
- package/dist/index.js +285 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +10 -3
- package/dist/mcp.js.map +1 -1
- package/package.json +2 -1
- package/dist/chunk-MLBJCPX2.js.map +0 -1
- package/dist/chunk-TPPPTL4J.js.map +0 -1
- /package/dist/{dashboard-T2UG23KI.js.map → dashboard-A3GJQCJX.js.map} +0 -0
- /package/dist/{dashboard-TFWCG23R.js.map → dashboard-R3FWTFFW.js.map} +0 -0
|
@@ -40,7 +40,9 @@ var SecretMetadataSchema = z.object({
|
|
|
40
40
|
validationUrl: z.string().optional(),
|
|
41
41
|
requiresApproval: z.boolean().optional(),
|
|
42
42
|
jitProvider: z.string().optional(),
|
|
43
|
-
jitExpiresAt: z.string().optional()
|
|
43
|
+
jitExpiresAt: z.string().optional(),
|
|
44
|
+
canary: z.boolean().optional(),
|
|
45
|
+
canaryFormat: z.string().optional()
|
|
44
46
|
});
|
|
45
47
|
var QuantumEnvelopeSchema = z.object({
|
|
46
48
|
v: z.literal(1),
|
|
@@ -73,7 +75,9 @@ function createEnvelope(value, opts) {
|
|
|
73
75
|
rotationPrefix: opts?.rotationPrefix,
|
|
74
76
|
provider: opts?.provider,
|
|
75
77
|
requiresApproval: opts?.requiresApproval,
|
|
76
|
-
jitProvider: opts?.jitProvider
|
|
78
|
+
jitProvider: opts?.jitProvider,
|
|
79
|
+
canary: opts?.canary,
|
|
80
|
+
canaryFormat: opts?.canaryFormat
|
|
77
81
|
}
|
|
78
82
|
};
|
|
79
83
|
}
|
|
@@ -561,6 +565,18 @@ function writeStoredAnchor(hash) {
|
|
|
561
565
|
} catch {
|
|
562
566
|
}
|
|
563
567
|
}
|
|
568
|
+
var auditAgentLabel = null;
|
|
569
|
+
function setAuditAgentLabel(label) {
|
|
570
|
+
if (label === null) {
|
|
571
|
+
auditAgentLabel = null;
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
const cleaned = label.replace(/[^\x20-\x7e]/g, "").trim().slice(0, 128);
|
|
575
|
+
auditAgentLabel = cleaned.length > 0 ? cleaned : null;
|
|
576
|
+
}
|
|
577
|
+
function getAuditAgentLabel() {
|
|
578
|
+
return auditAgentLabel;
|
|
579
|
+
}
|
|
564
580
|
function getAuditDir() {
|
|
565
581
|
if (process.env.QRING_AUDIT_DIR) {
|
|
566
582
|
if (!existsSync2(process.env.QRING_AUDIT_DIR)) {
|
|
@@ -612,6 +628,9 @@ function logAudit(event) {
|
|
|
612
628
|
pid: process.pid,
|
|
613
629
|
prevHash
|
|
614
630
|
};
|
|
631
|
+
if (full.agent === void 0 && auditAgentLabel) {
|
|
632
|
+
full.agent = auditAgentLabel;
|
|
633
|
+
}
|
|
615
634
|
const line = JSON.stringify(full);
|
|
616
635
|
const path = getAuditPath();
|
|
617
636
|
appendFileSync(path, line + "\n", { mode: 384 });
|
|
@@ -656,6 +675,7 @@ function queryAudit(query = {}) {
|
|
|
656
675
|
if (query.action) events = events.filter((e) => e.action === query.action);
|
|
657
676
|
if (query.source) events = events.filter((e) => e.source === query.source);
|
|
658
677
|
if (query.correlationId) events = events.filter((e) => e.correlationId === query.correlationId);
|
|
678
|
+
if (query.agent) events = events.filter((e) => e.agent === query.agent);
|
|
659
679
|
if (query.since) {
|
|
660
680
|
const since = new Date(query.since).getTime();
|
|
661
681
|
events = events.filter((e) => new Date(e.timestamp).getTime() >= since);
|
|
@@ -746,9 +766,9 @@ function exportAudit(opts = {}) {
|
|
|
746
766
|
return JSON.stringify(events, null, 2);
|
|
747
767
|
}
|
|
748
768
|
if (opts.format === "csv") {
|
|
749
|
-
const header = "timestamp,action,key,scope,env,source,pid,correlationId,detail";
|
|
769
|
+
const header = "timestamp,action,key,scope,env,source,agent,pid,correlationId,detail";
|
|
750
770
|
const rows = events.map(
|
|
751
|
-
(e) => `${e.timestamp},${e.action},${e.key ?? ""},${e.scope ?? ""},${e.env ?? ""},${e.source},${e.pid},${e.correlationId ?? ""},${(e.detail ?? "").replace(/,/g, ";")}`
|
|
771
|
+
(e) => `${e.timestamp},${e.action},${e.key ?? ""},${e.scope ?? ""},${e.env ?? ""},${e.source},${(e.agent ?? "").replace(/,/g, ";")},${e.pid},${e.correlationId ?? ""},${(e.detail ?? "").replace(/,/g, ";")}`
|
|
752
772
|
);
|
|
753
773
|
return [header, ...rows].join("\n");
|
|
754
774
|
}
|
|
@@ -1727,6 +1747,31 @@ function notifyApprovalRequested(key, source) {
|
|
|
1727
1747
|
);
|
|
1728
1748
|
}
|
|
1729
1749
|
|
|
1750
|
+
// src/core/canary-alert.ts
|
|
1751
|
+
var TRIP_THROTTLE_MS = 30 * 1e3;
|
|
1752
|
+
var lastAlerted = /* @__PURE__ */ new Map();
|
|
1753
|
+
function recordCanaryTrip(trip) {
|
|
1754
|
+
const agent = getAuditAgentLabel();
|
|
1755
|
+
logAudit({
|
|
1756
|
+
action: "canary",
|
|
1757
|
+
key: trip.key,
|
|
1758
|
+
scope: trip.scope,
|
|
1759
|
+
env: trip.env,
|
|
1760
|
+
source: trip.source,
|
|
1761
|
+
detail: `CANARY TRIPPED: honeytoken read via ${trip.source}`
|
|
1762
|
+
});
|
|
1763
|
+
if (!notificationsEnabled()) return;
|
|
1764
|
+
const now = Date.now();
|
|
1765
|
+
const last = lastAlerted.get(trip.key);
|
|
1766
|
+
if (last !== void 0 && now - last < TRIP_THROTTLE_MS) return;
|
|
1767
|
+
lastAlerted.set(trip.key, now);
|
|
1768
|
+
const who = agent ? `${trip.source} (${agent})` : trip.source;
|
|
1769
|
+
notifyUser(
|
|
1770
|
+
"q-ring: CANARY TRIPPED",
|
|
1771
|
+
`Honeytoken "${trip.key}" was read by ${who}. This credential is fake \u2014 but something reached for it. Investigate: qring audit --action canary`
|
|
1772
|
+
);
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1730
1775
|
// src/core/provision.ts
|
|
1731
1776
|
import { execFileSync, spawnSync } from "child_process";
|
|
1732
1777
|
import { z as z3 } from "zod";
|
|
@@ -2008,6 +2053,9 @@ function getSecret(key, opts = {}) {
|
|
|
2008
2053
|
const latest = readEnvelope(service, key) ?? envelope;
|
|
2009
2054
|
writeEnvelope(service, key, recordAccess(latest));
|
|
2010
2055
|
logAudit({ action: "read", key, scope, env, source });
|
|
2056
|
+
if (envelope.meta.canary) {
|
|
2057
|
+
recordCanaryTrip({ key, scope, env, source });
|
|
2058
|
+
}
|
|
2011
2059
|
}
|
|
2012
2060
|
return value;
|
|
2013
2061
|
}
|
|
@@ -2040,6 +2088,8 @@ function setSecret(key, value, opts = {}) {
|
|
|
2040
2088
|
const prov = opts.provider ?? existing?.meta.provider;
|
|
2041
2089
|
const reqApp = opts.requiresApproval ?? existing?.meta.requiresApproval;
|
|
2042
2090
|
const jitProv = opts.jitProvider ?? existing?.meta.jitProvider;
|
|
2091
|
+
const canaryFlag = opts.canary ?? existing?.meta.canary;
|
|
2092
|
+
const canaryFmt = opts.canaryFormat ?? existing?.meta.canaryFormat;
|
|
2043
2093
|
const mergedTags = opts.tags ?? existing?.meta.tags;
|
|
2044
2094
|
const ttlForPolicy = opts.ttlSeconds ?? existing?.meta.ttlSeconds;
|
|
2045
2095
|
const life = checkSecretLifecyclePolicy(
|
|
@@ -2067,7 +2117,9 @@ function setSecret(key, value, opts = {}) {
|
|
|
2067
2117
|
rotationPrefix: rotPfx,
|
|
2068
2118
|
provider: prov,
|
|
2069
2119
|
requiresApproval: reqApp,
|
|
2070
|
-
jitProvider: jitProv
|
|
2120
|
+
jitProvider: jitProv,
|
|
2121
|
+
canary: canaryFlag,
|
|
2122
|
+
canaryFormat: canaryFmt
|
|
2071
2123
|
});
|
|
2072
2124
|
} else {
|
|
2073
2125
|
envelope = createEnvelope(value, {
|
|
@@ -2080,7 +2132,9 @@ function setSecret(key, value, opts = {}) {
|
|
|
2080
2132
|
rotationPrefix: rotPfx,
|
|
2081
2133
|
provider: prov,
|
|
2082
2134
|
requiresApproval: reqApp,
|
|
2083
|
-
jitProvider: jitProv
|
|
2135
|
+
jitProvider: jitProv,
|
|
2136
|
+
canary: canaryFlag,
|
|
2137
|
+
canaryFormat: canaryFmt
|
|
2084
2138
|
});
|
|
2085
2139
|
}
|
|
2086
2140
|
if (existing) {
|
|
@@ -2572,6 +2626,7 @@ export {
|
|
|
2572
2626
|
checkDecay,
|
|
2573
2627
|
readProjectConfig,
|
|
2574
2628
|
collapseEnvironment,
|
|
2629
|
+
setAuditAgentLabel,
|
|
2575
2630
|
logAudit,
|
|
2576
2631
|
queryAudit,
|
|
2577
2632
|
verifyAuditChain,
|
|
@@ -2610,4 +2665,4 @@ export {
|
|
|
2610
2665
|
listMemory,
|
|
2611
2666
|
forget
|
|
2612
2667
|
};
|
|
2613
|
-
//# sourceMappingURL=chunk-
|
|
2668
|
+
//# sourceMappingURL=chunk-NCM5GHNW.js.map
|