Snyk logo

Backstage Snyk Plugin

Created by Snyk

Snyk is a developer security platform. It helps you find and fix issues in code, open source packages, containers, and infrastructure as code. It brings security into the developer workflow so problems surface early while work is in progress.

The Snyk Backstage plugin brings that data into your portal. It adds a security tab to each service page with counts by severity. You can see vulnerability and license issues, plus any ignored items. A compact overview widget gives a quick status so teams know where to focus. You can drill into projects and follow links to Snyk for deeper detail and guidance.

This is useful when you want security insights next to ownership and operational context. Teams can review risk during standups. Platform groups can spot trends across services with less context switching. Engineering leaders get a shared view of posture inside the same place people plan and ship work.

Installation Instructions

These instructions apply to self-hosted Backstage only. To use this plugin on Roadie, visit the docs.

Install the frontend package

  1. Add the package to your Backstage app
Copy
yarn add --cwd packages/app backstage-plugin-snyk

Add the Snyk tab and widget to EntityPage

  1. Import the components
Copy
// packages/app/src/components/catalog/EntityPage.tsx

import {
  SnykOverview,
  EntitySnykContent,
  isSnykAvailable,
} from 'backstage-plugin-snyk';
  1. Add a Snyk tab on the entity page
Copy
// packages/app/src/components/catalog/EntityPage.tsx

const serviceEntityPage = (
  <>
    {/* other routes */}
    <EntityLayout.Route
      path="/snyk"
      title="Snyk"
      // Uncomment to only show when annotations are present
      // if={isSnykAvailable}
    >
      <EntitySnykContent />
    </EntityLayout.Route>
  </>
);
  1. Show the widget on the overview
Copy
// packages/app/src/components/catalog/EntityPage.tsx

const overviewContent = (
  <Grid container spacing={3} alignItems="stretch">
    {/* other widgets */}
    <Grid item md={6} if={isSnykAvailable}>
      <SnykOverview />
    </Grid>
  </Grid>
);
  1. Or make the widget conditional with an entity switch
Copy
// packages/app/src/components/catalog/EntityPage.tsx

const overviewContent = (
  <Grid container spacing={3} alignItems="stretch">
    <EntitySwitch>
      <EntitySwitch.Case if={isSnykAvailable}>
        <Grid item md={6}>
          <SnykOverview />
        </Grid>
      </EntitySwitch.Case>
    </EntitySwitch>
  </Grid>
);

Configure the proxy in app config

  1. Add a proxy entry for Snyk in app config
Copy
# app-config.yaml
proxy:
  endpoints:
    /snyk:
      # For regional hosting change target to api.eu.snyk.io or api.au.snyk.io
      target: https://api.snyk.io/
      headers:
        User-Agent: tech-services/backstage-plugin/1.x
        Authorization: token ${SNYK_TOKEN}
  1. Optional Snyk plugin config
Copy
# app-config.yaml
snyk:
  # Default is app.snyk.io
  # For EU use app.eu.snyk.io
  # For AU use app.au.snyk.io
  appHost: app.snyk.io
  # Default API version is 2024-02-28
  # apiVersion: 2024-02-28
  # Default issues API version is 2024-01-23
  # issuesApiVersion: 2024-01-23
  # Useful for local development without a Snyk account
  mocked: false
  # Show resolved issues in graphs
  showResolvedInGraphs: false

Set the Snyk token

  1. Export the token in your runtime environment
Copy
export SNYK_TOKEN="your-snyk-token"

A Snyk service account with Viewer at group level works well.

Add entity annotations

  1. Add Snyk annotations to your catalog entities
Copy
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: goof
  description: Goof
  annotations:
    snyk.io/org-id: 361fd3c0-41d4-4ea4-ba77-09bb17890967
    snyk.io/targets: Snyk Demo/java-goof,508d2263-ea8a-4e42-bc9d-844de21f4172
    snyk.io/target-id: aarlaud-snyk/github-stats
    snyk.io/project-ids: 7439e322-f9c1-4c42-8367-002b33b9d946,db066cb9-b373-46da-b918-b49b541e0d63
    snyk.io/exclude-project-ids: 4737fc9c-3894-40ba-9dc5-aa8ae658c9f6,38e02916-0cf7-4927-ba98-06afae9fef36
spec:
  type: service
  lifecycle: production
  owner: guest

You can also use snyk.io/org-ids to search across many Snyk orgs.

Backend setup for the old backend system

  1. Install the proxy backend plugin in your backend package if missing
Copy
yarn add --cwd packages/backend @backstage/plugin-proxy-backend
  1. Add a proxy plugin file
Copy
// packages/backend/src/plugins/proxy.ts

import { createRouter } from '@backstage/plugin-proxy-backend';
import { Router } from 'express';
import { PluginEnvironment } from '../types';

export default async function createPlugin(
  env: PluginEnvironment,
): Promise<Router> {
  return await createRouter({
    logger: env.logger,
    config: env.config,
  });
}
  1. Mount the proxy router
Copy
// packages/backend/src/index.ts

import proxy from './plugins/proxy';

// inside the main bootstrap function
apiRouter.use('/proxy', await proxy(env));

The Snyk frontend will call through this proxy path.

Backend setup for the new backend system

  1. Install the proxy backend plugin in your backend package if missing
Copy
yarn add --cwd packages/backend @backstage/plugin-proxy-backend @backstage/backend-defaults
  1. Register the proxy plugin in the new backend
Copy
// packages/backend/src/index.ts

import { createBackend } from '@backstage/backend-defaults';
import { proxyPlugin } from '@backstage/plugin-proxy-backend';

const backend = createBackend();

backend.add(proxyPlugin());

backend.start();

The proxy plugin reads the proxy endpoints from app config.

Troubleshooting

404 from the Snyk API can be a path issue behind the proxy. Add a path rewrite

Copy
# app-config.yaml
proxy:
  endpoints:
    /snyk:
      target: https://api.snyk.io/
      headers:
        User-Agent: tech-services/backstage-plugin/1.x
        Authorization: token ${SNYK_TOKEN}
      pathRewrite:
        "^/proxy/snyk/": "/"

Notes on version changes

If you upgrade from plugin version one to two update the proxy target to remove the v1 path if present.

Things to Know

Snyk Annotations

  • snyk.io/target-id: Specify a single target by name or ID. Using the target ID will avoid an API call and be faster. Use this API endpoint to get the Target IDs.
  • snyk.io/targets: Specify one or more targets by name or ID. Using the target ID will avoid an API call and be faster. Use this API endpoint to get the Target IDs.
  • snyk.io/project-ids: The project ID (see slug in URL or ID in project settings). If there are multiple projects (e.g., multiple package.json or pom files), add them comma-separated.
  • snyk.io/exclude-project-ids: Exclude specific projects you might not want.

Changelog

This changelog is produced from commits made to the Snyk plugin since a year ago, and based on the code located here. It may not contain information about all commits. Releases and version bumps are intentionally omitted. This changelog is generated by AI.

Bug Fixes

  • Show priority score for issues #207 merged 10 months ago

Documentation

  • Fix link to contributor agreement #217 merged 13 days ago

Set up Backstage in minutes with Roadie