Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,19 @@ console.log(formatDriftAlert(alert));
| `agentbom-llamaindex` | `@wasmagent/agentbom-llamaindex` | LlamaIndex adapter |
| `agentbom-autogen` | `@wasmagent/agentbom-autogen` | AutoGen adapter |

## Standards alignment

AgentBOM aligns with the emerging **[CycloneDX Agent BOM](https://github.com/CycloneDX/specification/issues/895)**
proposal (upstream issue #895). Rather than maintaining a parallel inventory
standard, WasmAgent tracks that proposal and positions `@wasmagent/agentbom-core`
as an **early reference implementation** of it — a runnable, published library
that describes an agent's tools, permission scopes, model dependencies, and
compliance posture as a single verifiable document.

We contribute practical implementation experience upstream. Even where the final
CycloneDX design differs from ours, being an early, publicly-engaged implementer
is itself a verifiable external trust signal.

## Related repositories

| Repository | Role |
Expand Down
15 changes: 10 additions & 5 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions packages/agentbom-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,10 @@
"build": "mkdir -p dist && bun build ./src/index.ts --target node --outfile dist/index.js",
"test": "bun test src/",
"typecheck": "tsc --noEmit"
},
"devDependencies": {
"@types/bun": "^1.3.14",
"@types/node": "^26.1.2",
"typescript": "^5.9.3"
}
}
5 changes: 3 additions & 2 deletions packages/agentbom-cli/src/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { fileURLToPath } from "node:url";
import {
inspectTrustPassport,
isExpired,
type TrustPassport,
validateTrustPassport,
} from "@openagentaudit/passport";
import { inspectAgentBOM, validateAgentBOM } from "@wasmagent/agentbom-core";
Expand Down Expand Up @@ -375,12 +376,12 @@ function runPassportStep(exampleDir: string): ChainStepResult {
"trust-passport: posture_ref.snapshot_id does not match posture identity.snapshot_id",
);
}
if (isExpired(passportObj)) {
if (isExpired(passportObj as unknown as TrustPassport)) {
errors.push("trust-passport: passport has expired");
}

outputHash = hashFile(passportPath);
summary = inspectTrustPassport(passportObj);
summary = inspectTrustPassport(passportObj as unknown as TrustPassport);
} catch (err) {
errors.push(
`trust-passport: ${err instanceof Error ? err.message : String(err)}`,
Expand Down
12 changes: 9 additions & 3 deletions packages/agentbom-cli/src/passport-inspect.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { inspectTrustPassport, isExpired } from "@openagentaudit/passport";
import {
inspectTrustPassport,
isExpired,
type TrustPassport,
} from "@openagentaudit/passport";

export function inspectPassportCommand(filePath: string): number {
const resolvedPath = resolve(filePath);
Expand Down Expand Up @@ -31,9 +35,11 @@ export function inspectPassportCommand(filePath: string): number {
const passport = data as Record<string, unknown>;
const identity = passport.identity as Record<string, string> | undefined;

console.log(inspectTrustPassport(passport));
console.log(inspectTrustPassport(passport as unknown as TrustPassport));
console.log(` Issuer: ${identity?.issuer ?? "?"}`);
console.log(` Status: ${isExpired(passport) ? "EXPIRED" : "Active"}`);
console.log(
` Status: ${isExpired(passport as unknown as TrustPassport) ? "EXPIRED" : "Active"}`,
);

return 0;
}
5 changes: 3 additions & 2 deletions packages/agentbom-cli/src/passport-validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { resolve } from "node:path";
import {
inspectTrustPassport,
isExpired,
type TrustPassport,
validateTrustPassport,
} from "@openagentaudit/passport";

Expand Down Expand Up @@ -49,9 +50,9 @@ export function validatePassportCommand(filePath: string): number {
}

const passport = data as Record<string, unknown>;
console.log(inspectTrustPassport(passport));
console.log(inspectTrustPassport(passport as unknown as TrustPassport));

if (isExpired(passport)) {
if (isExpired(passport as unknown as TrustPassport)) {
console.error("\nPassport has EXPIRED.");
return 1;
}
Expand Down
8 changes: 6 additions & 2 deletions packages/agentbom-cli/src/passport-verify-signed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
import { createPublicKey, verify } from "node:crypto";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { isExpired, validateTrustPassport } from "@openagentaudit/passport";
import {
isExpired,
type TrustPassport,
validateTrustPassport,
} from "@openagentaudit/passport";

// isRecord is a private utility not exported by @openagentaudit/passport
function isRecord(v: unknown): v is Record<string, unknown> {
Expand Down Expand Up @@ -189,7 +193,7 @@ export function verifySignedPassport(options: VerifyOptions): VerifyResult {
}

// Also check passport validity.expires_at
if (isExpired(payload as { validity?: { expires_at?: string } })) {
if (isExpired(payload as unknown as TrustPassport)) {
expired = true;
const expiresAt = (payload.validity as Record<string, unknown>)?.expires_at;
if (expiresAt && !errors.some((e) => e.includes("expired"))) {
Expand Down
7 changes: 6 additions & 1 deletion packages/agentbom-cli/src/regulatory-report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,12 @@ function assessRiskMonitoring(
medium: 0,
low: 0,
};
const mitigatedCount = { critical: 0, high: 0, medium: 0, low: 0 };
const mitigatedCount: Record<string, number> = {
critical: 0,
high: 0,
medium: 0,
low: 0,
};

for (const risk of riskLayer) {
if (typeof risk !== "object" || risk === null) continue;
Expand Down
4 changes: 3 additions & 1 deletion packages/agentbom-cli/src/sigstore-verify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,9 @@ function checkOidcIssuer(
): boolean {
// Method 1: structured extension access (Node.js ≥ 17.3)
try {
const san = cert.getExtension("subjectAltName");
const san = (
cert as unknown as { getExtension?: (name: string) => unknown }
).getExtension?.("subjectAltName");
if (san && typeof san === "object") {
const obj = san as Record<string, unknown>;
const altNames = obj.altNames as
Expand Down
3 changes: 2 additions & 1 deletion packages/agentbom-cli/src/trust-diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ function diffValues(
}

/** Check if a value is a plain object (not null, not array). */
function isPlainObject(value: unknown): boolean {
function isPlainObject(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}

Expand Down Expand Up @@ -393,6 +393,7 @@ export function trustDiffCommand(args: string[]): number {
agentbom: "AgentBOM",
"mcp-posture": "MCP Posture",
"trust-passport": "Trust Passport",
unknown: "Unknown",
}[result.artifactType] ?? result.artifactType;

if (!json) {
Expand Down
6 changes: 6 additions & 0 deletions packages/agentbom-cli/src/trust-subscribe.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ describe("runDriftCheck", () => {
agentIdentity: "test-agent-sub",
baselinePath,
watchDir: tmpDir,
intervalSeconds: 30,
once: true,
};

Expand All @@ -279,6 +280,7 @@ describe("runDriftCheck", () => {
agentIdentity: "test-agent-sub",
baselinePath,
watchDir: tmpDir,
intervalSeconds: 30,
once: true,
};

Expand All @@ -301,6 +303,7 @@ describe("runDriftCheck", () => {
agentIdentity: "test-agent-sub",
baselinePath,
watchDir: tmpDir,
intervalSeconds: 30,
once: true,
};

Expand All @@ -314,6 +317,7 @@ describe("runDriftCheck", () => {
agentIdentity: "test-agent-sub",
baselinePath: "/nonexistent/baseline.json",
watchDir: tmpDir,
intervalSeconds: 30,
once: true,
};

Expand All @@ -333,6 +337,7 @@ describe("runDriftCheck", () => {
agentIdentity: "test-agent-sub",
baselinePath,
watchDir: tmpDir,
intervalSeconds: 30,
once: true,
};

Expand All @@ -348,6 +353,7 @@ describe("runDriftCheck", () => {
agentIdentity: "test-agent-sub",
baselinePath,
watchDir: tmpDir,
intervalSeconds: 30,
once: true,
};

Expand Down
2 changes: 1 addition & 1 deletion packages/agentbom-cli/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"compilerOptions": {
"rootDir": "src",
"outDir": "dist",
"types": ["bun-types"]
"types": ["node", "bun"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
Expand Down
Loading