veracarto 0.1.5 → 0.1.6

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/dist/cli/index.js CHANGED
@@ -42963,6 +42963,81 @@ var init_build5 = __esm({
42963
42963
  });
42964
42964
 
42965
42965
  // src/cli/ui/Detail.tsx
42966
+ function getFixCommands(item) {
42967
+ const meta = typeof item.metadata === "string" ? (() => {
42968
+ try {
42969
+ return JSON.parse(item.metadata);
42970
+ } catch {
42971
+ return {};
42972
+ }
42973
+ })() : item.metadata || {};
42974
+ const resource = item.affected_resource || "";
42975
+ const projectId = meta.projectId || meta.gcp_project_id || "YOUR_PROJECT_ID";
42976
+ switch (item.playbook_id) {
42977
+ case "gcp-firewall-broad":
42978
+ return {
42979
+ fix: [
42980
+ `gcloud compute firewall-rules update ${resource} \\`,
42981
+ ` --project=${projectId} \\`,
42982
+ ` --source-ranges=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16`
42983
+ ],
42984
+ rollback: [
42985
+ `gcloud compute firewall-rules update ${resource} \\`,
42986
+ ` --project=${projectId} \\`,
42987
+ ` --source-ranges=0.0.0.0/0`
42988
+ ]
42989
+ };
42990
+ case "gcp-public-bucket":
42991
+ return {
42992
+ fix: [
42993
+ `gcloud storage buckets update gs://${resource} --uniform-bucket-level-access`,
42994
+ `gcloud storage buckets remove-iam-policy-binding gs://${resource} \\`,
42995
+ ` --member=allUsers --role=roles/storage.objectViewer`
42996
+ ],
42997
+ rollback: [
42998
+ `gcloud storage buckets add-iam-policy-binding gs://${resource} \\`,
42999
+ ` --member=allUsers --role=roles/storage.objectViewer`
43000
+ ]
43001
+ };
43002
+ case "gcp-overpermissioned-iam": {
43003
+ const member = meta.member || `serviceAccount:${resource}`;
43004
+ const role = meta.role || "roles/editor";
43005
+ return {
43006
+ fix: [
43007
+ `gcloud projects remove-iam-policy-binding ${projectId} \\`,
43008
+ ` --member=${member} \\`,
43009
+ ` --role=${role}`
43010
+ ],
43011
+ rollback: [
43012
+ `gcloud projects add-iam-policy-binding ${projectId} \\`,
43013
+ ` --member=${member} \\`,
43014
+ ` --role=${role}`
43015
+ ]
43016
+ };
43017
+ }
43018
+ case "gcp-audit-logging-disabled":
43019
+ return {
43020
+ fix: [
43021
+ `gcloud projects get-iam-policy ${resource || projectId} --format=json > /tmp/policy.json`,
43022
+ `# Add audit config to policy.json`,
43023
+ `gcloud projects set-iam-policy ${resource || projectId} /tmp/policy.json`
43024
+ ],
43025
+ rollback: [
43026
+ `gcloud projects set-iam-policy ${resource || projectId} /tmp/policy-backup.json`
43027
+ ]
43028
+ };
43029
+ case "github-dependabot":
43030
+ return {
43031
+ fix: [
43032
+ `# Draft PR: bump ${meta.dependency || "package"} ${meta.fromVersion || ""} \u2192 ${meta.toVersion || "latest"}`,
43033
+ `# PR opened automatically by Veracarto`
43034
+ ],
43035
+ rollback: []
43036
+ };
43037
+ default:
43038
+ return null;
43039
+ }
43040
+ }
42966
43041
  function Detail({ item, slackTeamId, onBack, onApprove, onDismiss, onTierChange, onNoise }) {
42967
43042
  const [loading, setLoading] = (0, import_react31.useState)(false);
42968
43043
  const [dismissMode, setDismissMode] = (0, import_react31.useState)(false);
@@ -43065,7 +43140,11 @@ function Detail({ item, slackTeamId, onBack, onApprove, onDismiss, onTierChange,
43065
43140
  setLoading(false);
43066
43141
  }
43067
43142
  }
43068
- return /* @__PURE__ */ import_react31.default.createElement(Box_default, { flexDirection: "column" }, /* @__PURE__ */ import_react31.default.createElement(Box_default, { borderStyle: "single", borderBottom: false, paddingX: 1, justifyContent: "space-between" }, /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#888888" }, "\u2190 back"), /* @__PURE__ */ import_react31.default.createElement(Box_default, null, /* @__PURE__ */ import_react31.default.createElement(Text, { color: tierColor, bold: true }, "T", item.tier), /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#888888" }, " \xB7 ", confidencePct, "%"))), /* @__PURE__ */ import_react31.default.createElement(Box_default, { flexDirection: "column", borderStyle: "single", borderTop: false, borderBottom: false, paddingX: 2, paddingY: 1 }, /* @__PURE__ */ import_react31.default.createElement(Text, { bold: true, color: "white" }, item.title), /* @__PURE__ */ import_react31.default.createElement(Text, null, " "), /* @__PURE__ */ import_react31.default.createElement(Text, { bold: true, color: "#888888" }, "RESOURCE"), /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#cccccc" }, item.affected_resource_type || "unknown", " \xB7 ", item.affected_resource), /* @__PURE__ */ import_react31.default.createElement(Box_default, null, item.is_production ? /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#f59e0b" }, "production") : /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#888888" }, "non-production"), /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#444444" }, " \xB7 "), item.is_internet_facing ? /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#f59e0b" }, "internet-facing") : /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#888888" }, "internal")), /* @__PURE__ */ import_react31.default.createElement(Text, null, " "), /* @__PURE__ */ import_react31.default.createElement(Text, { bold: true, color: "#888888" }, "AGENT REASONING"), /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#cccccc" }, item.agent_reasoning || item.description || "No reasoning available."), /* @__PURE__ */ import_react31.default.createElement(Text, null, " "), /* @__PURE__ */ import_react31.default.createElement(Text, { bold: true, color: "#888888" }, "RECOMMENDED ACTION"), /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#cccccc" }, item.recommended_action || "No recommendation."), /* @__PURE__ */ import_react31.default.createElement(Text, null, " "), /* @__PURE__ */ import_react31.default.createElement(Text, { bold: true, color: "#888888" }, "BLAST RADIUS"), /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#cccccc" }, item.blast_radius || "Unknown"), loading && /* @__PURE__ */ import_react31.default.createElement(import_react31.default.Fragment, null, /* @__PURE__ */ import_react31.default.createElement(Text, null, " "), /* @__PURE__ */ import_react31.default.createElement(Box_default, null, /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#22c55e" }, /* @__PURE__ */ import_react31.default.createElement(build_default2, { type: "dots" })), /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#888888" }, " executing..."))), resultMessage && /* @__PURE__ */ import_react31.default.createElement(import_react31.default.Fragment, null, /* @__PURE__ */ import_react31.default.createElement(Text, null, " "), /* @__PURE__ */ import_react31.default.createElement(Text, { color: resultMessage.startsWith("\u2713") ? "#22c55e" : "#ef4444" }, resultMessage)), dismissMode && /* @__PURE__ */ import_react31.default.createElement(import_react31.default.Fragment, null, /* @__PURE__ */ import_react31.default.createElement(Text, null, " "), /* @__PURE__ */ import_react31.default.createElement(Box_default, null, /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#888888" }, "Dismiss reason: "), /* @__PURE__ */ import_react31.default.createElement(
43143
+ return /* @__PURE__ */ import_react31.default.createElement(Box_default, { flexDirection: "column" }, /* @__PURE__ */ import_react31.default.createElement(Box_default, { borderStyle: "single", borderBottom: false, paddingX: 1, justifyContent: "space-between" }, /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#888888" }, "\u2190 back"), /* @__PURE__ */ import_react31.default.createElement(Box_default, null, /* @__PURE__ */ import_react31.default.createElement(Text, { color: tierColor, bold: true }, "T", item.tier), /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#888888" }, " \xB7 ", confidencePct, "%"))), /* @__PURE__ */ import_react31.default.createElement(Box_default, { flexDirection: "column", borderStyle: "single", borderTop: false, borderBottom: false, paddingX: 2, paddingY: 1 }, /* @__PURE__ */ import_react31.default.createElement(Text, { bold: true, color: "white" }, item.title), /* @__PURE__ */ import_react31.default.createElement(Text, null, " "), /* @__PURE__ */ import_react31.default.createElement(Text, { bold: true, color: "#888888" }, "RESOURCE"), /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#cccccc" }, item.affected_resource_type || "unknown", " \xB7 ", item.affected_resource), /* @__PURE__ */ import_react31.default.createElement(Box_default, null, item.is_production ? /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#f59e0b" }, "production") : /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#888888" }, "non-production"), /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#444444" }, " \xB7 "), item.is_internet_facing ? /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#f59e0b" }, "internet-facing") : /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#888888" }, "internal")), /* @__PURE__ */ import_react31.default.createElement(Text, null, " "), /* @__PURE__ */ import_react31.default.createElement(Text, { bold: true, color: "#888888" }, "AGENT REASONING"), /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#cccccc" }, item.agent_reasoning || item.description || "No reasoning available."), /* @__PURE__ */ import_react31.default.createElement(Text, null, " "), /* @__PURE__ */ import_react31.default.createElement(Text, { bold: true, color: "#888888" }, "RECOMMENDED ACTION"), /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#cccccc" }, item.recommended_action || "No recommendation."), /* @__PURE__ */ import_react31.default.createElement(Text, null, " "), /* @__PURE__ */ import_react31.default.createElement(Text, { bold: true, color: "#888888" }, "BLAST RADIUS"), /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#cccccc" }, item.blast_radius || "Unknown"), (() => {
43144
+ const cmds = getFixCommands(item);
43145
+ if (!cmds) return null;
43146
+ return /* @__PURE__ */ import_react31.default.createElement(import_react31.default.Fragment, null, /* @__PURE__ */ import_react31.default.createElement(Text, null, " "), /* @__PURE__ */ import_react31.default.createElement(Text, { bold: true, color: "#888888" }, "FIX COMMAND"), /* @__PURE__ */ import_react31.default.createElement(Box_default, { flexDirection: "column", borderStyle: "single", paddingX: 1 }, cmds.fix.map((line, i) => /* @__PURE__ */ import_react31.default.createElement(Text, { key: i, color: "#22c55e" }, line))), cmds.rollback.length > 0 && /* @__PURE__ */ import_react31.default.createElement(import_react31.default.Fragment, null, /* @__PURE__ */ import_react31.default.createElement(Text, null, " "), /* @__PURE__ */ import_react31.default.createElement(Text, { bold: true, color: "#888888" }, "ROLLBACK"), /* @__PURE__ */ import_react31.default.createElement(Box_default, { flexDirection: "column", borderStyle: "single", paddingX: 1 }, cmds.rollback.map((line, i) => /* @__PURE__ */ import_react31.default.createElement(Text, { key: i, color: "#888888" }, line)))));
43147
+ })(), loading && /* @__PURE__ */ import_react31.default.createElement(import_react31.default.Fragment, null, /* @__PURE__ */ import_react31.default.createElement(Text, null, " "), /* @__PURE__ */ import_react31.default.createElement(Box_default, null, /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#22c55e" }, /* @__PURE__ */ import_react31.default.createElement(build_default2, { type: "dots" })), /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#888888" }, " executing..."))), resultMessage && /* @__PURE__ */ import_react31.default.createElement(import_react31.default.Fragment, null, /* @__PURE__ */ import_react31.default.createElement(Text, null, " "), /* @__PURE__ */ import_react31.default.createElement(Text, { color: resultMessage.startsWith("\u2713") ? "#22c55e" : "#ef4444" }, resultMessage)), dismissMode && /* @__PURE__ */ import_react31.default.createElement(import_react31.default.Fragment, null, /* @__PURE__ */ import_react31.default.createElement(Text, null, " "), /* @__PURE__ */ import_react31.default.createElement(Box_default, null, /* @__PURE__ */ import_react31.default.createElement(Text, { color: "#888888" }, "Dismiss reason: "), /* @__PURE__ */ import_react31.default.createElement(
43069
43148
  build_default,
43070
43149
  {
43071
43150
  value: dismissReason,
@@ -45058,7 +45137,7 @@ var {
45058
45137
  // src/cli/index.ts
45059
45138
  init_config();
45060
45139
  var program2 = new Command();
45061
- program2.name("veracarto").description("Security findings, down to what matters").version("0.1.5");
45140
+ program2.name("veracarto").description("Security findings, down to what matters").version("0.1.6");
45062
45141
  program2.command("init").description("Interactive onboarding wizard").option("--step <step>", "Jump to a specific step (gcp, github, slack)").action(async (opts) => {
45063
45142
  const { runInit: runInit2 } = await init_init().then(() => init_exports);
45064
45143
  await runInit2(opts.step);