Skip to main content
Five Anti-Patterns Chained Into SDK Write AccessIncident
4 min readFor Security Engineers

Five Anti-Patterns Chained Into SDK Write Access

What Happened

Token Security researchers exploited a free Zapier account to gain write access to critical SDK packages on NPM. The attack didn't require zero-day vulnerabilities—just five known anti-patterns that, when combined across Zapier's systems, led to a compromise.

The exposed NPM token had three dangerous permissions: action: write, name: null, and bypass_2fa: true. With this token, an attacker could publish malicious code to Zapier's SDK packages without triggering two-factor authentication.

Timeline

February 12, 2026: Token Security disclosed the five-stage exploit chain to Zapier.

March 5, 2026: Zapier confirmed full remediation (21 days from disclosure to fix).

Post-remediation: Researchers received a $3,000 bounty, the program maximum.

Which Controls Failed or Were Missing

1. Exposed Environment Variables in Lambda Functions

Researchers found sensitive credentials in AWS Lambda environment variables. These variables are stored unencrypted by default, accessible to anyone with sufficient IAM permissions.

Control gap: Sensitive configuration data was not encrypted at rest. The NPM token was in plaintext, accessible to multiple roles.

2. Overprivileged Service Tokens

The NPM token had write permissions with no scope restrictions (name: null) and could bypass MFA (bypass_2fa: true). This violated the principle of least privilege.

Control gap: Service accounts were not limited to specific packages or operations. A token meant for automated publishing could modify any package in the organization's namespace.

3. Missing Token Rotation Policy

There was no evidence the exposed token had been rotated recently or had an expiration date, increasing the window for exploitation.

Control gap: No automated token lifecycle management. The token's age and last-used timestamp weren't monitored.

4. Insufficient Boundary Between Customer and Internal Systems

A free Zapier account could interact with systems that exposed paths to internal infrastructure. Researchers moved from customer-facing APIs to Lambda functions with infrastructure credentials.

Control gap: Network segmentation and access controls didn't adequately separate customer-accessible resources from internal tools.

5. Inadequate Secrets Detection in Code and Configs

The token was in Lambda environment variables, visible in CloudFormation templates, Terraform state files, and function configuration dumps, without triggering alerts.

Control gap: No automated scanning of infrastructure-as-code or runtime configurations for exposed credentials.

What the Relevant Standards Require

PCI DSS v4.0.1

Requirement 3.5.1: Cryptographic keys used to encrypt stored account data must be protected against disclosure and misuse. Storing the NPM token unencrypted in Lambda environment variables fails this requirement.

Requirement 7.2.2: Access to privileged accounts must be assigned based on job function and limited to least privileges necessary. The bypass_2fa: true permission violates this principle.

OWASP ASVS v4.0.3

Requirement 2.10.4: Verify that service accounts are not assigned interactive login capabilities. The NPM token's MFA bypass effectively granted it interactive-equivalent capabilities.

Requirement 6.4.1: Verify that sensitive data and APIs are protected against Insecure Direct Object Reference (IDOR) attacks. The lateral movement from customer-facing systems to internal Lambda functions indicates insufficient access controls.

NIST 800-53 Rev 5

AC-6: Least Privilege: Organizations must employ the principle of least privilege. The name: null scope on the NPM token violated this control.

IA-5(7): No Embedded Unencrypted Static Authenticators: Authenticators must not be embedded in applications or stored in unencrypted form. Lambda environment variables without KMS encryption fail this requirement.

Lessons and Action Items for Your Team

1. Encrypt All Lambda Environment Variables

Enable AWS KMS encryption for every Lambda function handling credentials. Use separate KMS keys per environment (dev, staging, prod) and audit key usage with CloudTrail.

Implementation: In your Terraform or CloudFormation, set kms_key_arn on the aws_lambda_function resource. Rotate these keys annually.

2. Scope Service Tokens to Specific Resources

NPM tokens should specify exactly which packages they can modify. Use the --scope flag when generating tokens: npm token create --scope @yourorg/specific-package.

Implementation: Audit all service tokens this week. Replace any token with name: null or org-wide write access with resource-scoped alternatives.

3. Implement Automated Token Rotation

Service tokens should expire. Set a 90-day maximum lifetime for NPM tokens, GitHub PATs, and cloud service accounts.

Implementation: Use AWS Secrets Manager's automatic rotation feature for Lambda credentials. For NPM tokens, create a monthly rotation job that generates new tokens, updates Lambda environment variables, and revokes old tokens.

4. Scan Infrastructure-as-Code for Secrets

Your CI/CD pipeline should reject any commit containing credentials in Terraform files, CloudFormation templates, or Kubernetes manifests.

Implementation: Add gitleaks or trufflehog to your pre-commit hooks and CI pipeline. Configure custom patterns for your NPM token format.

5. Map Cross-System Trust Boundaries

Document which systems can communicate with others. A customer-facing API should not have a code path to infrastructure management credentials.

Implementation: Create a trust boundary diagram showing customer systems, internal tools, and infrastructure management. Each boundary crossing requires explicit authentication and authorization checks. Review this diagram quarterly as you add new integrations.

6. Monitor Service Account Activity

Track when service accounts authenticate, what they access, and whether the pattern matches expected behavior.

Implementation: Send all NPM publish events to your SIEM. Alert on publishes from unexpected IP ranges, to packages the token shouldn't touch, or outside your deployment windows.


The Zapier exploit chain succeeded because each team secured their component in isolation. The Lambda team encrypted some variables but not all. The NPM team issued scoped tokens for some workflows but not others. The network team segmented production from dev but didn't fully separate customer-facing from internal systems.

Your security posture is only as strong as the weakest chain of controls an attacker can traverse. Map those chains before someone else does.

Topics:Incident

You Might Also Like