BugbThreat-model preview

Send us a repository.
Get its threat model back.

GuardLink keeps a threat model inside your code as comments. Give us a public GitHub repository and we'll show you what that model looks like for it: the annotations we'd add, the assets they name, and the exposures and data flows they reveal.

Public repositories only. Paste the URL from your browser's address bar.

The preview is sent here.

A person on the Bugb team picks up each request. Nothing is pushed to your repository.

What happens after you request a preview

  1. You send a public repository

    Paste its GitHub URL and tell us where the preview should go.

  2. We read it with GuardLink

    Someone on the Bugb team clones the public repository and annotates it. GuardLink reads source files; it doesn't build or run your code.

  3. The preview arrives by email

    You get the suggested annotations and the threat model they produce. Keep them, commit them, or ask us what an exposure means.

What a preview contains

Here is the kind of preview you'd get, built from acme/shop, a fictional sample project we use to show GuardLink. Your preview is written from your own code.

Suggested annotations
GuardLink comments written against your actual files and line numbers, ready to commit next to the code they describe.In acme/shop: @exposes, @flows, @comment
Assets
The components and data stores worth protecting, named so the rest of the model can refer to them.In acme/shop: #avatar-api, #uploads
Exposures
Where an asset is open to a threat, with severity, a CWE where one fits, and the reason in plain words.In acme/shop: 2 high: unrestricted upload, stored XSS
Data flows
How data moves between users, services and storage, so trust boundaries are visible.In acme/shop: User → #avatar-api → #uploads → User
acme/shop src/api/avatar.ts Example only, fictional project
// @exposes #avatar-api to #unrestricted-upload [high] cwe:CWE-434 -- "handleAvatarUpload() passes req.headers['x-filename'] to writeFile() with no signature check on the body"// @comment -- "path.basename() stops directory traversal in x-filename; it does not restrict the file type, so #unrestricted-upload stays open"// @flows User -> #avatar-api via HTTPS -- "Raw request body plus x-filename header"// @flows #avatar-api -> #uploads via fs.writeFile -- "Stored under the client-chosen name"export async function handleAvatarUpload(req: IncomingMessage, res: ServerResponse) {  const name = path.basename(String(req.headers['x-filename'] ?? 'avatar.png'));Lines omitted  await writeFile(path.join(UPLOAD_DIR, name), body);Lines omitted// @exposes #avatar-api to #stored-xss [high] cwe:CWE-79 -- "serveUpload() maps TYPES['.html'] to text/html, so an uploaded .html file renders in the shop origin"// @flows #uploads -> User via HTTPS -- "Content-Type chosen from the stored extension"export async function serveUpload(req: IncomingMessage, res: ServerResponse) {
$ guardlink validate .

⚠  2 unmitigated exposure(s):
   #avatar-api → #unrestricted-upload [high] (src/api/avatar.ts:19)
   #avatar-api → #stored-xss [high] (src/api/avatar.ts:34)

Previews cover public repositories only. A preview is a starting threat model from reading the code; it isn't a penetration test and doesn't prove an exposure is exploitable. We use your contact details to send the preview and follow up about it, as described in our privacy policy.