Connect your security and ticket tools
Push assure evidence to your GRC tool, run privacy requests from Transcend or OneTrust, send SBOM and VEX to your vulnerability tool, and open one ticket per failure.
Status Status is where the work is: Planned (in a milestone, not started), Building (tickets in progress), Preview (usable, may change), then the stability it ships at.
Stability The promise an interface ships with.
- Stable Follows semantic versioning; breaking changes need a new major, 12 months of overlap and a codemod.
- Beta Usable in production; may change before it becomes stable.
- Experimental May change or go away; needs an explicit opt-in in main.yaml.
You will send MainSDK's evidence to the tools your security team uses: control results to ServiceNow IRM, one GitHub issue per failure, and the SBOM and VEX to Dependency-Track. It takes about 30 minutes.
You need
- A MainSDK app with
secrets, and anassurerun to push (astandardand a list of control results). - A token for each tool, stored as a secret.
1. Declare the connectors
connectors:
grc: { driver: servicenow-irm, instance: https://acme.service-now.com, auth: secret:SN_TOKEN }
vulns: { driver: dependency-track, url: https://dt.acme.internal, auth: secret:DT_KEY }
tickets: { driver: github, repo: acme/web, auth: secret:GH_TOKEN }Always write auth: secret:NAME. A literal token fails mainsdk check.
2. Test them without writing
mainsdk connectors testEach connector is pinged and nothing is written.
3. Push a run
import { app } from "mainsdk";
import {
type AssureRun,
type ConnectorsConfig,
connectorsFrom,
httpOver,
pushAssure,
syncTickets,
} from "mainsdk/connectors";
const a = app();
const c = connectorsFrom(a.config.connectors as ConnectorsConfig, {
http: httpOver(fetch),
secrets: (name) => a.secrets.get(name),
log: (entry) => a.log.info("connector call", { ...entry }),
});
export async function push(run: AssureRun) {
if (c.grc) await pushAssure(c.grc, run);
if (c.tickets) await syncTickets(c.tickets, run, { owner: "web-team" });
}Running it twice opens each issue once. Pass previous (the controls that failed last time) so a fixed control closes its issue.
4. Send a release
import type { Connector, VexStatement } from "mainsdk/connectors";
import { importFindings, pushRelease } from "mainsdk/connectors";
export async function send(vulns: Connector, sbom: Record<string, unknown>, vex: VexStatement[]) {
await pushRelease(vulns, { app: "web", release: "1.4.0", sbom, vex });
return importFindings(vulns, "1.4.0");
}A CVE the VEX marks not_affected comes back suppressed, with its justification.
Check it worked
pnpm mainsdk checkpasses with noMAIN-SECRET-0002orMAIN-CONNECTOR-0001finding.mainsdk connectors testreports each connectorok.- The audit log has one line per call, and none holds a token.
If it fails
MAIN-SECRET-0002:authis a literal. Move the token to secrets and writesecret:NAME.MAIN-CONNECTOR-0001: the driver is not one of the listed ones, or the address is not https.MAIN-CONNECTOR-0002: the tool refused a call. The audit line names the operation and status.
Prompt for your coding agent
Wire my app's assure results into our tools with MainSDK's
connectorsinterface. Push control results to ServiceNow IRM, open one GitHub issue per failure that closes when fixed, send the SBOM and VEX to Dependency-Track, and keep every token in secrets.
Was this page helpful?