v0.2.1-draft AI Drafted

Snyk Hardening Guide

Security Last updated: 2026-08-08

AppSec platform security for service accounts, SCM integrations, and Broker configs

View:

Overview

Snyk provides developer security for vulnerability scanning across code, dependencies, containers, and IaC. REST API, CLI tokens, and SCM integrations access source code repositories and vulnerability data. Compromised access exposes vulnerability findings and potentially enables code access through integrations.

Intended Audience

  • Security engineers managing AppSec tools
  • DevSecOps administrators
  • GRC professionals assessing development security
  • Third-party risk managers evaluating security scanning tools

How to Use This Guide

  • L1 (Crawl): Essential controls for all organizations
  • L2 (Walk): Enhanced controls for security-sensitive environments
  • L3 (Run): Strictest controls for regulated industries

Scope

This guide covers Snyk security configurations including authentication, access controls, and integration security.


Table of Contents

  1. Authentication & Access Controls
  2. Integration Security
  3. Data Security
  4. Monitoring & Detection

1. Authentication & Access Controls

1.1 Enforce SSO with MFA

Profile Level: L1 (Crawl) NIST 800-53: IA-2(1)

Description

Require SAML SSO through your corporate identity provider and enforce multi-factor authentication for every user who accesses the Snyk platform.

Rationale

Why This Matters:

  • Centralizes Snyk authentication in your IdP so MFA, conditional access, and session policies apply to every login
  • Local or password-only logins bypass corporate identity controls and are prime targets for credential stuffing and phishing
  • SSO with automated deprovisioning removes departed users’ access immediately, preventing orphaned accounts from reaching vulnerability data
  • Snyk holds your organization’s known-vulnerability inventory and SCM connections, so a single compromised login can reveal exactly where you are exploitable

Attack Prevented: Credential theft, phishing, MFA bypass, orphaned-account access

ClickOps Implementation

Step 1: Configure SAML SSO (Business/Enterprise)

  1. Navigate to: Settings → SSO
  2. Configure SAML IdP
  3. Enable: Require SSO

Step 2: Enable MFA (Non-SSO)

  1. Configure MFA through account settings
  2. Enforce for all users

1.2 Role-Based Access

Profile Level: L1 (Crawl) NIST 800-53: AC-3, AC-6

Description

Assign Snyk group and organization members the least-privileged role required for their function instead of granting broad administrative access by default.

Rationale

Why This Matters:

  • Least-privilege roles limit how much a single compromised or insider account can change, export, or expose
  • Group Admin and Org Admin can alter integrations, ignore policies, and member access, so these rights should be tightly held
  • Scoping collaborators to view-and-test prevents accidental or malicious changes to scanning configuration and findings
  • Clear role separation makes access reviews and audit attribution far easier across many organizations

Attack Prevented: Privilege escalation, insider misuse, unauthorized configuration changes, lateral movement

ClickOps Implementation

Step 1: Define Roles

Role Permissions
Group Admin Full organization access
Org Admin Organization management
Org Collaborator View and test projects
Org Custom Custom permissions

Step 2: Configure Organization Access

  1. Navigate to: Settings → Members
  2. Assign appropriate roles
  3. Use least privilege

2. Integration Security

2.1 Secure Service Account Tokens

Profile Level: L1 (Crawl) NIST 800-53: IA-5

Description

Choose the right service-account credential type for every non-interactive Snyk integration, and manage those credentials on a defined lifecycle. Snyk offers three service-account authentication types with materially different security properties — API key, access token, and OAuth 2.0 — and the choice determines whether the credential ever expires.

Rationale

Why This Matters:

  • Service account credentials are non-interactive and bypass MFA, so a leaked credential grants direct API access with the service account’s full role
  • API keys never expire. Snyk documents the API key service account as a legacy type and explicitly states it is not recommended — an API key leaked into a CI log or repository is a permanent credential until someone notices and deletes the account
  • Access tokens cap out at a one-year maximum expiry, and Snyk documents no in-place rotation: when an access token expires you must create a new service account and re-plumb every consumer, so the rotation has to be planned rather than discovered at expiry
  • OAuth 2.0 service accounts issue short-lived tokens with automated refresh, which is why they are the recommended type for CI/CD and any long-running integration
  • Snyk credentials can read vulnerability findings and drive SCM operations, so exposure reveals exploitable weaknesses and integration reach

Attack Prevented: Token theft, credential leakage in CI/CD, standing-credential abuse, unauthorized data export

Attack Scenario: Exposed API token enables vulnerability data export; attackers gain insight into exploitable vulnerabilities before patches.

ClickOps Implementation

Step 1: Choose the Credential Type

Type Expiry Rotation Snyk guidance
API key Never expires Manual only (delete + recreate) Legacy — explicitly not recommended
Access token Configurable, 1 year maximum No in-place rotation — requires a new service account Acceptable where OAuth is not supported; plan around the 1-year ceiling
OAuth 2.0 Short-lived access token Automated refresh Recommended — use for CI/CD and all new integrations

Default to OAuth 2.0. Never create API-key service accounts for new integrations, and treat any existing API-key service account as a standing credential to be migrated. See Choose a service account type.

Step 2: Audit Service Accounts

  1. Navigate to: Settings → Service accounts
  2. Review all service accounts and record the credential type of each
  3. Remove unused accounts
  4. Flag every API-key service account for migration to OAuth 2.0

Step 3: Credential Lifecycle

  1. Create one service account per CI/CD pipeline or integration — never share credentials across consumers
  2. Assign the least-privileged role the integration needs
  3. For access tokens, diary the expiry date and schedule the replacement service account before it lapses (there is no in-place renewal)
  4. Store credentials in a secrets manager; never commit them or echo them in pipeline logs

Code Implementation

Code Pack: API Script
hth-snyk-2.01-service-account-token-audit.sh View source on GitHub ↗
: "${SNYK_TOKEN:?Set SNYK_TOKEN to a Snyk API token with admin access}"
SNYK_API="${SNYK_API:-https://api.snyk.io}"
SNYK_API_VERSION="${SNYK_API_VERSION:-2024-06-10}"

# Audit one scope: "groups <group_id>" or "orgs <org_id>"
audit_service_accounts() {
  local scope="$1" scope_id="$2"
  echo "== Service accounts for ${scope}/${scope_id} =="
  curl -sf \
    --header "Authorization: token ${SNYK_TOKEN}" \
    --header "Content-Type: application/vnd.api+json" \
    "${SNYK_API}/rest/${scope}/${scope_id}/service_accounts?version=${SNYK_API_VERSION}" \
  | jq -r '
      # Service account records carry: id, name, auth_type, role_id,
      # access_token_expires_at, access_token_ttl_seconds.
      # auth_type is one of: access_token, api_key,
      # oauth_client_secret, oauth_private_key_jwt.
      [.. | objects | select(.auth_type?)] | .[] |
      [ .name,
        .auth_type,
        (.access_token_expires_at // "n/a"),
        (if .auth_type == "api_key" then
           "FAIL: legacy API key - never expires, migrate to OAuth 2.0"
         elif .auth_type == "access_token" then
           "WARN: 1-year max expiry, no in-place rotation - plan replacement"
         else
           "PASS: OAuth 2.0 short-lived credential"
         end)
      ] | @tsv'
}

# Group-level service accounts, then each org you operate:
[ -n "${SNYK_GROUP_ID:-}" ] && audit_service_accounts "groups" "${SNYK_GROUP_ID}"
[ -n "${SNYK_ORG_ID:-}" ]   && audit_service_accounts "orgs"   "${SNYK_ORG_ID}"
# Remove a flagged legacy service account once its workload is migrated
# to an OAuth 2.0 service account (deletion also kills its API key).
#   DELETE /rest/orgs/{org_id}/service_accounts/{service_account_id}
#   DELETE /rest/groups/{group_id}/service_accounts/{service_account_id}
delete_service_account() {
  local scope="$1" scope_id="$2" sa_id="$3"
  curl -sf -X DELETE \
    --header "Authorization: token ${SNYK_TOKEN}" \
    "${SNYK_API}/rest/${scope}/${scope_id}/service_accounts/${sa_id}?version=${SNYK_API_VERSION}"
  echo "Deleted service account ${sa_id} from ${scope}/${scope_id}"
}

2.2 SCM Integration Security

Profile Level: L1 (Crawl) NIST 800-53: CM-7

Description

Review and restrict Snyk’s source-code-management integrations so each connection has only the repository access it needs, and route private-repo access through the Snyk Broker. Snyk ships the Broker in two deployment models — Universal Broker and Classic Broker — and new deployments should target Universal Broker.

Rationale

Why This Matters:

  • SCM integrations grant Snyk read access to source repositories, so an over-scoped or stale connection widens what a platform compromise can reach
  • The Snyk Broker keeps private repositories behind your perimeter and brokers only approved requests instead of exposing direct SCM credentials — Snyk documents that with Broker, “credentials remain within your network and are never stored by or transmitted to Snyk”
  • Universal Broker consolidates many connection types (GitHub, GitLab, Artifactory, Jira, container registry) behind a single client or set of replicas, so there is one hardened egress path to govern instead of one Broker deployment per integration
  • Classic Broker uses per-integration deployments with accept.json request filters that constrain which endpoints and operations the Broker permits, enforcing least privilege at the integration layer
  • Limiting repository scope contains the impact if a token or integration is abused, preventing access to unrelated codebases

Attack Prevented: Source code exposure, over-scoped integration abuse, supply chain reconnaissance, credential leakage

Changed default (April 2026): Snyk Broker now runs in high-availability mode by default. Deployments provisioned before this change may still be running single-instance; confirm your replica configuration rather than assuming the old default. Source: Snyk What’s New.

ClickOps Implementation

Step 1: Review Integrations

  1. Navigate to: Settings → Integrations
  2. Review SCM connections
  3. Limit repository access

Step 2: Choose a Broker Deployment Model (Enterprise)

Model Shape Use it for
Universal Broker One Broker client (or replica set) serving many connection types — GitHub, GitLab, Artifactory, Jira, container registry New deployments. Fewer moving parts, one egress path, centrally managed connections
Classic Broker One Broker deployment per integration type, each with its own accept.json filter file Existing estates already running per-integration Brokers

Step 3: Harden the Broker Deployment

  1. Deploy the Broker inside your network so SCM credentials never leave your perimeter
  2. Restrict the permitted request set — accept.json filters in Classic Broker, per-connection configuration in Universal Broker
  3. Limit exposed endpoints to the minimum the Snyk integration requires
  4. Verify high-availability replica count matches your availability requirement

3. Data Security

3.1 Project Visibility

Profile Level: L1 (Crawl) NIST 800-53: AC-21

Description

Configure project visibility, vulnerability-detail access, and report/export permissions so only authorized users can view sensitive findings.

Rationale

Why This Matters:

  • Vulnerability findings describe exactly where your software is exploitable, so over-broad visibility hands attackers a roadmap
  • Limiting who can view issue details and share findings keeps sensitive security data on a need-to-know basis
  • Controlling report generation and export prevents bulk exfiltration of findings outside monitored channels
  • Auditing report access lets you detect unusual harvesting of vulnerability data before it is misused

Attack Prevented: Information disclosure, vulnerability reconnaissance, data exfiltration, insider leakage

ClickOps Implementation

Step 1: Configure Project Settings

  1. Set appropriate project visibility
  2. Limit who can view vulnerability details
  3. Control issue sharing

Step 2: Report Access

  1. Limit report generation
  2. Control export permissions
  3. Audit report access

3.2 Ignore Policy

Profile Level: L2 (Walk) NIST 800-53: CM-7

Description

Govern how vulnerabilities are ignored by requiring a documented reason, an expiration date, and periodic review of all suppressed findings.

Rationale

Why This Matters:

  • Unbounded ignores silently suppress real vulnerabilities, letting exploitable issues ship while dashboards appear clean
  • Requiring a reason and approver creates accountability and an audit trail for every accepted risk
  • Expiration forces re-evaluation so a temporary exception does not quietly become permanent blindness
  • Auditing ignored issues catches abuse where suppression is used to bypass security gates rather than manage genuine false positives

Attack Prevented: Risk-acceptance abuse, suppressed-vulnerability exploitation, security-gate bypass, audit evasion

Implementation

Step 1: Ignore Workflow

  1. Require reason for ignores
  2. Set ignore expiration
  3. Audit ignored vulnerabilities

Code Implementation

Code Pack: CLI Script
hth-snyk-3.02-governed-ignore.sh View source on GitHub ↗
# Never ignore without a reason and a bounded expiry. Left alone, the CLI
# default expiry is 30 days — set it explicitly so the review date is a
# decision, not an accident. Expiry format: YYYY-MM-DD.
ISSUE_ID="${1:?Usage: $0 <snyk-issue-id> <expiry YYYY-MM-DD> <reason...>}"
EXPIRY="${2:?Usage: $0 <snyk-issue-id> <expiry YYYY-MM-DD> <reason...>}"
shift 2
REASON="${*:?A human-readable reason is required}"

snyk ignore \
  --id="${ISSUE_ID}" \
  --expiry="${EXPIRY}" \
  --reason="${REASON} (approved-by: ${SNYK_IGNORE_APPROVER:-unset})"
# The ignore lands in the repo's .snyk policy file as:
#   ignore:
#     '<ISSUE_ID>':
#       - '*':
#           reason: <REASON>
#           expires: <EXPIRY>
# Audit pass for review/CI: surface every suppression with its reason and
# expiry so unbounded or unjustified ignores are visible in code review.
POLICY_FILE="${SNYK_POLICY_FILE:-.snyk}"
if [ -f "${POLICY_FILE}" ]; then
  echo "== Suppression entries in ${POLICY_FILE} =="
  grep -nE "reason:|expires:" "${POLICY_FILE}" || echo "No ignores recorded"

  IGNORES=$(grep -cE "^ignore:" "${POLICY_FILE}" || true)
  REASONS=$(grep -cE "reason:" "${POLICY_FILE}" || true)
  EXPIRIES=$(grep -cE "expires:" "${POLICY_FILE}" || true)
  echo "ignore blocks: ${IGNORES} | reasons recorded: ${REASONS} | expiries recorded: ${EXPIRIES}"
  if [ "${REASONS}" -ne "${EXPIRIES}" ]; then
    echo "WARN: reason/expiry counts differ - review ${POLICY_FILE} for unbounded ignores"
  fi
fi

4. Monitoring & Detection

4.1 Audit Logs (Enterprise)

Profile Level: L1 (Crawl) NIST 800-53: AU-2, AU-3

Description

Review Snyk audit logs and forward them to your SIEM to retain a record of user and administrative activity across the platform. Snyk’s audit logs are an Enterprise-plan capability with a 90-day rolling retention window, and they exclude login and logout events — both facts drive how the control must be implemented.

Rationale

Why This Matters:

  • Audit logs provide the authoritative record of who changed integrations, roles, ignore policies, and tokens
  • Retention is a rolling 90 days. Any investigation, compliance evidence, or retrospective beyond that window is impossible from Snyk alone, which makes SIEM forwarding mandatory rather than optional
  • Login and logout events are excluded from the audit-log endpoints. Authentication activity must be reconstructed from your identity provider’s logs — treat the IdP as the system of record for Snyk sign-in, and correlate it with Snyk audit events in the SIEM
  • Without centralized logging, account compromise and configuration tampering can go undetected until damage is done
  • Reviewing activity supports incident response, forensics, and compliance evidence for access and change controls

Attack Prevented: Undetected account compromise, configuration tampering, audit gaps, delayed incident response

Prerequisites

  • Enterprise plan — audit logs are not available on Free, Team, or Business

ClickOps Implementation

Step 1: Access Audit Logs

  1. Navigate to: Settings → Audit logs
  2. Review user activities

Step 2: Forward to SIEM Before the 90-Day Window Closes

  1. Pull group- and org-level audit events via the audit logs API
  2. Schedule collection at an interval well inside the 90-day retention window so no events age out uncollected
  3. Retain forwarded events in the SIEM per your own retention policy — Snyk will not hold them

Step 3: Fill the Authentication Gap from the IdP

  1. Forward Snyk SSO sign-in and sign-out events from your identity provider (the Snyk audit endpoints do not carry them)
  2. Correlate IdP authentication events with Snyk audit events to reconstruct a complete session-to-action trail

Code Implementation

Code Pack: API Script
hth-snyk-4.01-audit-log-export.sh View source on GitHub ↗
: "${SNYK_TOKEN:?Set SNYK_TOKEN to a Snyk API token with admin access}"
SNYK_API="${SNYK_API:-https://api.snyk.io}"
SNYK_API_VERSION="${SNYK_API_VERSION:-2024-06-10}"

# Collection window — run at least daily; events age out after 90 days.
FROM="${SNYK_AUDIT_FROM:-$(date -u -d '1 day ago' +%Y-%m-%d)}"
TO="${SNYK_AUDIT_TO:-$(date -u +%Y-%m-%d)}"
OUT_DIR="${SNYK_AUDIT_OUT_DIR:-./snyk-audit-logs}"
mkdir -p "${OUT_DIR}"

# Export one scope: "orgs <org_id>" or "groups <group_id>".
#   GET /rest/orgs/{org_id}/audit_logs/search
#   GET /rest/groups/{group_id}/audit_logs/search
# Optional params: from, to, size, cursor, events, exclude_events.
export_audit_logs() {
  local scope="$1" scope_id="$2"
  local out="${OUT_DIR}/${scope}-${scope_id}-${FROM}_${TO}.json"
  local url="${SNYK_API}/rest/${scope}/${scope_id}/audit_logs/search?version=${SNYK_API_VERSION}&from=${FROM}&to=${TO}&size=100"
  [ -n "${SNYK_AUDIT_CURSOR:-}" ] && url="${url}&cursor=${SNYK_AUDIT_CURSOR}"

  curl -sf \
    --header "Authorization: token ${SNYK_TOKEN}" \
    --header "Content-Type: application/vnd.api+json" \
    "${url}" | jq '.' > "${out}"

  echo "Exported ${scope}/${scope_id} audit logs ${FROM}..${TO} -> ${out}"
}

# Pull group-level events (role, policy, membership changes) and each
# org's events, then forward the JSON files to your SIEM.
[ -n "${SNYK_GROUP_ID:-}" ] && export_audit_logs "groups" "${SNYK_GROUP_ID}"
[ -n "${SNYK_ORG_ID:-}" ]   && export_audit_logs "orgs"   "${SNYK_ORG_ID}"

Detection Focus


Appendix A: Edition Compatibility

Control Free Team Business Enterprise
SAML SSO
SCIM
Audit Logs
Service Accounts

Appendix B: References

Official Snyk Documentation:

API Documentation:

Compliance Frameworks:

Security Incidents:

  • No major public incidents involving Snyk identified

Changelog

Date Version Maturity Changes Author
2026-08-08 0.2.1 draft Added api Code Packs for §2.1 (service-account credential-type audit + legacy-key deletion via the REST service_accounts endpoints) and §4.1 (org/group audit-log export via audit_logs/search inside the 90-day window), plus a cli Code Pack for §3.2 (snyk ignore with mandatory reason and expiry, .snyk suppression audit), all verified against docs.snyk.io API and CLI references Claude Code (Fable 5)
2026-08-08 0.2.0 draft Currency pass (Tier 1 only): rewrote 2.1 for the three service-account credential types (API key never expires and is not recommended; access token 1-year max with no in-place rotation; OAuth 2.0 recommended); added Universal vs Classic Broker and the April 2026 Broker high-availability default to 2.2; documented Enterprise-only audit logs, 90-day rolling retention, and the login/logout exclusion in 4.1; repaired rotted docs.snyk.io links to the platform-administration tree and removed Trust Center / marketing pages from Appendix B. Tier 3/4 research sweep out of scope this pass. Claude Code (Opus 4.8)
2025-12-14 0.1.0 draft Initial Snyk hardening guide Claude Code (Opus 4.5)

Contributing

Found an issue or want to improve this guide?